Annotation of gcc/explow.c, revision 1.1.1.7

1.1       root        1: /* Subroutines for manipulating rtx's in semantically interesting ways.
1.1.1.7 ! root        2:    Copyright (C) 1987, 1991, 1994 Free Software Foundation, Inc.
1.1       root        3: 
                      4: This file is part of GNU CC.
                      5: 
                      6: GNU CC is free software; you can redistribute it and/or modify
                      7: it under the terms of the GNU General Public License as published by
                      8: the Free Software Foundation; either version 2, or (at your option)
                      9: any later version.
                     10: 
                     11: GNU CC is distributed in the hope that it will be useful,
                     12: but WITHOUT ANY WARRANTY; without even the implied warranty of
                     13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     14: GNU General Public License for more details.
                     15: 
                     16: You should have received a copy of the GNU General Public License
                     17: along with GNU CC; see the file COPYING.  If not, write to
                     18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
                     19: 
                     20: 
                     21: #include "config.h"
                     22: #include "rtl.h"
                     23: #include "tree.h"
                     24: #include "flags.h"
                     25: #include "expr.h"
                     26: #include "hard-reg-set.h"
                     27: #include "insn-config.h"
                     28: #include "recog.h"
                     29: #include "insn-flags.h"
                     30: #include "insn-codes.h"
                     31: 
1.1.1.4   root       32: /* Return an rtx for the sum of X and the integer C.
                     33: 
1.1.1.5   root       34:    This function should be used via the `plus_constant' macro.  */
1.1       root       35: 
                     36: rtx
1.1.1.4   root       37: plus_constant_wide (x, c)
1.1       root       38:      register rtx x;
1.1.1.4   root       39:      register HOST_WIDE_INT c;
1.1       root       40: {
                     41:   register RTX_CODE code;
                     42:   register enum machine_mode mode;
                     43:   register rtx tem;
                     44:   int all_constant = 0;
                     45: 
                     46:   if (c == 0)
                     47:     return x;
                     48: 
                     49:  restart:
                     50: 
                     51:   code = GET_CODE (x);
                     52:   mode = GET_MODE (x);
                     53:   switch (code)
                     54:     {
                     55:     case CONST_INT:
1.1.1.4   root       56:       return GEN_INT (INTVAL (x) + c);
1.1       root       57: 
                     58:     case CONST_DOUBLE:
                     59:       {
1.1.1.4   root       60:        HOST_WIDE_INT l1 = CONST_DOUBLE_LOW (x);
                     61:        HOST_WIDE_INT h1 = CONST_DOUBLE_HIGH (x);
                     62:        HOST_WIDE_INT l2 = c;
                     63:        HOST_WIDE_INT h2 = c < 0 ? ~0 : 0;
                     64:        HOST_WIDE_INT lv, hv;
1.1       root       65: 
                     66:        add_double (l1, h1, l2, h2, &lv, &hv);
                     67: 
                     68:        return immed_double_const (lv, hv, VOIDmode);
                     69:       }
                     70: 
                     71:     case MEM:
                     72:       /* If this is a reference to the constant pool, try replacing it with
                     73:         a reference to a new constant.  If the resulting address isn't
                     74:         valid, don't return it because we have no way to validize it.  */
                     75:       if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
                     76:          && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0)))
                     77:        {
                     78:          tem
                     79:            = force_const_mem (GET_MODE (x),
                     80:                               plus_constant (get_pool_constant (XEXP (x, 0)),
                     81:                                              c));
                     82:          if (memory_address_p (GET_MODE (tem), XEXP (tem, 0)))
                     83:            return tem;
                     84:        }
                     85:       break;
                     86: 
                     87:     case CONST:
                     88:       /* If adding to something entirely constant, set a flag
                     89:         so that we can add a CONST around the result.  */
                     90:       x = XEXP (x, 0);
                     91:       all_constant = 1;
                     92:       goto restart;
                     93: 
                     94:     case SYMBOL_REF:
                     95:     case LABEL_REF:
                     96:       all_constant = 1;
                     97:       break;
                     98: 
                     99:     case PLUS:
                    100:       /* The interesting case is adding the integer to a sum.
                    101:         Look for constant term in the sum and combine
                    102:         with C.  For an integer constant term, we make a combined
                    103:         integer.  For a constant term that is not an explicit integer,
1.1.1.4   root      104:         we cannot really combine, but group them together anyway.  
                    105: 
                    106:         Use a recursive call in case the remaining operand is something
                    107:         that we handle specially, such as a SYMBOL_REF.  */
                    108: 
                    109:       if (GET_CODE (XEXP (x, 1)) == CONST_INT)
                    110:        return plus_constant (XEXP (x, 0), c + INTVAL (XEXP (x, 1)));
1.1       root      111:       else if (CONSTANT_P (XEXP (x, 0)))
                    112:        return gen_rtx (PLUS, mode,
                    113:                        plus_constant (XEXP (x, 0), c),
                    114:                        XEXP (x, 1));
                    115:       else if (CONSTANT_P (XEXP (x, 1)))
                    116:        return gen_rtx (PLUS, mode,
                    117:                        XEXP (x, 0),
                    118:                        plus_constant (XEXP (x, 1), c));
                    119:     }
                    120: 
                    121:   if (c != 0)
1.1.1.4   root      122:     x = gen_rtx (PLUS, mode, x, GEN_INT (c));
1.1       root      123: 
                    124:   if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF)
                    125:     return x;
                    126:   else if (all_constant)
                    127:     return gen_rtx (CONST, mode, x);
                    128:   else
                    129:     return x;
                    130: }
                    131: 
1.1.1.4   root      132: /* This is the same as `plus_constant', except that it handles LO_SUM.
                    133: 
                    134:    This function should be used via the `plus_constant_for_output' macro.  */
1.1       root      135: 
                    136: rtx
1.1.1.4   root      137: plus_constant_for_output_wide (x, c)
1.1       root      138:      register rtx x;
1.1.1.4   root      139:      register HOST_WIDE_INT c;
1.1       root      140: {
                    141:   register RTX_CODE code = GET_CODE (x);
                    142:   register enum machine_mode mode = GET_MODE (x);
                    143:   int all_constant = 0;
                    144: 
                    145:   if (GET_CODE (x) == LO_SUM)
                    146:     return gen_rtx (LO_SUM, mode, XEXP (x, 0),
                    147:                    plus_constant_for_output (XEXP (x, 1), c));
                    148: 
                    149:   else
                    150:     return plus_constant (x, c);
                    151: }
                    152: 
                    153: /* If X is a sum, return a new sum like X but lacking any constant terms.
                    154:    Add all the removed constant terms into *CONSTPTR.
                    155:    X itself is not altered.  The result != X if and only if
                    156:    it is not isomorphic to X.  */
                    157: 
                    158: rtx
                    159: eliminate_constant_term (x, constptr)
                    160:      rtx x;
1.1.1.2   root      161:      rtx *constptr;
1.1       root      162: {
                    163:   register rtx x0, x1;
1.1.1.2   root      164:   rtx tem;
1.1       root      165: 
                    166:   if (GET_CODE (x) != PLUS)
                    167:     return x;
                    168: 
                    169:   /* First handle constants appearing at this level explicitly.  */
1.1.1.2   root      170:   if (GET_CODE (XEXP (x, 1)) == CONST_INT
                    171:       && 0 != (tem = simplify_binary_operation (PLUS, GET_MODE (x), *constptr,
                    172:                                                XEXP (x, 1)))
                    173:       && GET_CODE (tem) == CONST_INT)
1.1       root      174:     {
1.1.1.2   root      175:       *constptr = tem;
1.1       root      176:       return eliminate_constant_term (XEXP (x, 0), constptr);
                    177:     }
                    178: 
1.1.1.2   root      179:   tem = const0_rtx;
                    180:   x0 = eliminate_constant_term (XEXP (x, 0), &tem);
                    181:   x1 = eliminate_constant_term (XEXP (x, 1), &tem);
                    182:   if ((x1 != XEXP (x, 1) || x0 != XEXP (x, 0))
                    183:       && 0 != (tem = simplify_binary_operation (PLUS, GET_MODE (x),
                    184:                                                *constptr, tem))
                    185:       && GET_CODE (tem) == CONST_INT)
1.1       root      186:     {
1.1.1.2   root      187:       *constptr = tem;
1.1       root      188:       return gen_rtx (PLUS, GET_MODE (x), x0, x1);
                    189:     }
1.1.1.2   root      190: 
1.1       root      191:   return x;
                    192: }
                    193: 
                    194: /* Returns the insn that next references REG after INSN, or 0
                    195:    if REG is clobbered before next referenced or we cannot find
                    196:    an insn that references REG in a straight-line piece of code.  */
                    197: 
                    198: rtx
                    199: find_next_ref (reg, insn)
                    200:      rtx reg;
                    201:      rtx insn;
                    202: {
                    203:   rtx next;
                    204: 
                    205:   for (insn = NEXT_INSN (insn); insn; insn = next)
                    206:     {
                    207:       next = NEXT_INSN (insn);
                    208:       if (GET_CODE (insn) == NOTE)
                    209:        continue;
                    210:       if (GET_CODE (insn) == CODE_LABEL
                    211:          || GET_CODE (insn) == BARRIER)
                    212:        return 0;
                    213:       if (GET_CODE (insn) == INSN
                    214:          || GET_CODE (insn) == JUMP_INSN
                    215:          || GET_CODE (insn) == CALL_INSN)
                    216:        {
                    217:          if (reg_set_p (reg, insn))
                    218:            return 0;
                    219:          if (reg_mentioned_p (reg, PATTERN (insn)))
                    220:            return insn;
                    221:          if (GET_CODE (insn) == JUMP_INSN)
                    222:            {
                    223:              if (simplejump_p (insn))
                    224:                next = JUMP_LABEL (insn);
                    225:              else
                    226:                return 0;
                    227:            }
                    228:          if (GET_CODE (insn) == CALL_INSN
                    229:              && REGNO (reg) < FIRST_PSEUDO_REGISTER
                    230:              && call_used_regs[REGNO (reg)])
                    231:            return 0;
                    232:        }
                    233:       else
                    234:        abort ();
                    235:     }
                    236:   return 0;
                    237: }
                    238: 
                    239: /* Return an rtx for the size in bytes of the value of EXP.  */
                    240: 
                    241: rtx
                    242: expr_size (exp)
                    243:      tree exp;
                    244: {
1.1.1.6   root      245:   tree size = size_in_bytes (TREE_TYPE (exp));
                    246: 
                    247:   if (TREE_CODE (size) != INTEGER_CST
                    248:       && contains_placeholder_p (size))
                    249:     size = build (WITH_RECORD_EXPR, sizetype, size, exp);
                    250: 
                    251:   return expand_expr (size, NULL_RTX, TYPE_MODE (sizetype), 0);
1.1       root      252: }
                    253: 
                    254: /* Return a copy of X in which all memory references
                    255:    and all constants that involve symbol refs
                    256:    have been replaced with new temporary registers.
                    257:    Also emit code to load the memory locations and constants
                    258:    into those registers.
                    259: 
                    260:    If X contains no such constants or memory references,
                    261:    X itself (not a copy) is returned.
                    262: 
                    263:    If a constant is found in the address that is not a legitimate constant
                    264:    in an insn, it is left alone in the hope that it might be valid in the
                    265:    address.
                    266: 
                    267:    X may contain no arithmetic except addition, subtraction and multiplication.
                    268:    Values returned by expand_expr with 1 for sum_ok fit this constraint.  */
                    269: 
                    270: static rtx
                    271: break_out_memory_refs (x)
                    272:      register rtx x;
                    273: {
                    274:   if (GET_CODE (x) == MEM
1.1.1.5   root      275:       || (CONSTANT_P (x) && CONSTANT_ADDRESS_P (x)
1.1       root      276:          && GET_MODE (x) != VOIDmode))
1.1.1.7 ! root      277:     x = force_reg (GET_MODE (x), x);
1.1       root      278:   else if (GET_CODE (x) == PLUS || GET_CODE (x) == MINUS
                    279:           || GET_CODE (x) == MULT)
                    280:     {
                    281:       register rtx op0 = break_out_memory_refs (XEXP (x, 0));
                    282:       register rtx op1 = break_out_memory_refs (XEXP (x, 1));
1.1.1.7 ! root      283: 
1.1       root      284:       if (op0 != XEXP (x, 0) || op1 != XEXP (x, 1))
                    285:        x = gen_rtx (GET_CODE (x), Pmode, op0, op1);
                    286:     }
1.1.1.7 ! root      287: 
1.1       root      288:   return x;
                    289: }
                    290: 
                    291: /* Given a memory address or facsimile X, construct a new address,
                    292:    currently equivalent, that is stable: future stores won't change it.
                    293: 
                    294:    X must be composed of constants, register and memory references
                    295:    combined with addition, subtraction and multiplication:
                    296:    in other words, just what you can get from expand_expr if sum_ok is 1.
                    297: 
                    298:    Works by making copies of all regs and memory locations used
                    299:    by X and combining them the same way X does.
                    300:    You could also stabilize the reference to this address
                    301:    by copying the address to a register with copy_to_reg;
                    302:    but then you wouldn't get indexed addressing in the reference.  */
                    303: 
                    304: rtx
                    305: copy_all_regs (x)
                    306:      register rtx x;
                    307: {
                    308:   if (GET_CODE (x) == REG)
                    309:     {
1.1.1.6   root      310:       if (REGNO (x) != FRAME_POINTER_REGNUM
                    311: #if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
                    312:          && REGNO (x) != HARD_FRAME_POINTER_REGNUM
                    313: #endif
                    314:          )
1.1       root      315:        x = copy_to_reg (x);
                    316:     }
                    317:   else if (GET_CODE (x) == MEM)
                    318:     x = copy_to_reg (x);
                    319:   else if (GET_CODE (x) == PLUS || GET_CODE (x) == MINUS
                    320:           || GET_CODE (x) == MULT)
                    321:     {
                    322:       register rtx op0 = copy_all_regs (XEXP (x, 0));
                    323:       register rtx op1 = copy_all_regs (XEXP (x, 1));
                    324:       if (op0 != XEXP (x, 0) || op1 != XEXP (x, 1))
                    325:        x = gen_rtx (GET_CODE (x), Pmode, op0, op1);
                    326:     }
                    327:   return x;
                    328: }
                    329: 
                    330: /* Return something equivalent to X but valid as a memory address
                    331:    for something of mode MODE.  When X is not itself valid, this
                    332:    works by copying X or subexpressions of it into registers.  */
                    333: 
                    334: rtx
                    335: memory_address (mode, x)
                    336:      enum machine_mode mode;
                    337:      register rtx x;
                    338: {
1.1.1.7 ! root      339:   register rtx oldx = x;
1.1       root      340: 
                    341:   /* By passing constant addresses thru registers
                    342:      we get a chance to cse them.  */
1.1.1.5   root      343:   if (! cse_not_expected && CONSTANT_P (x) && CONSTANT_ADDRESS_P (x))
1.1.1.7 ! root      344:     x = force_reg (Pmode, x);
1.1       root      345: 
                    346:   /* Accept a QUEUED that refers to a REG
                    347:      even though that isn't a valid address.
                    348:      On attempting to put this in an insn we will call protect_from_queue
                    349:      which will turn it into a REG, which is valid.  */
1.1.1.7 ! root      350:   else if (GET_CODE (x) == QUEUED
1.1       root      351:       && GET_CODE (QUEUED_VAR (x)) == REG)
1.1.1.7 ! root      352:     ;
1.1       root      353: 
                    354:   /* We get better cse by rejecting indirect addressing at this stage.
                    355:      Let the combiner create indirect addresses where appropriate.
                    356:      For now, generate the code so that the subexpressions useful to share
                    357:      are visible.  But not if cse won't be done!  */
1.1.1.7 ! root      358:   else
        !           359:     {
        !           360:       if (! cse_not_expected && GET_CODE (x) != REG)
        !           361:        x = break_out_memory_refs (x);
1.1       root      362: 
1.1.1.7 ! root      363:       /* At this point, any valid address is accepted.  */
        !           364:       GO_IF_LEGITIMATE_ADDRESS (mode, x, win);
1.1       root      365: 
1.1.1.7 ! root      366:       /* If it was valid before but breaking out memory refs invalidated it,
        !           367:         use it the old way.  */
        !           368:       if (memory_address_p (mode, oldx))
        !           369:        goto win2;
        !           370: 
        !           371:       /* Perform machine-dependent transformations on X
        !           372:         in certain cases.  This is not necessary since the code
        !           373:         below can handle all possible cases, but machine-dependent
        !           374:         transformations can make better code.  */
        !           375:       LEGITIMIZE_ADDRESS (x, oldx, mode, win);
        !           376: 
        !           377:       /* PLUS and MULT can appear in special ways
        !           378:         as the result of attempts to make an address usable for indexing.
        !           379:         Usually they are dealt with by calling force_operand, below.
        !           380:         But a sum containing constant terms is special
        !           381:         if removing them makes the sum a valid address:
        !           382:         then we generate that address in a register
        !           383:         and index off of it.  We do this because it often makes
        !           384:         shorter code, and because the addresses thus generated
        !           385:         in registers often become common subexpressions.  */
        !           386:       if (GET_CODE (x) == PLUS)
        !           387:        {
        !           388:          rtx constant_term = const0_rtx;
        !           389:          rtx y = eliminate_constant_term (x, &constant_term);
        !           390:          if (constant_term == const0_rtx
        !           391:              || ! memory_address_p (mode, y))
        !           392:            x = force_operand (x, NULL_RTX);
        !           393:          else
        !           394:            {
        !           395:              y = gen_rtx (PLUS, GET_MODE (x), copy_to_reg (y), constant_term);
        !           396:              if (! memory_address_p (mode, y))
        !           397:                x = force_operand (x, NULL_RTX);
        !           398:              else
        !           399:                x = y;
        !           400:            }
        !           401:        }
        !           402: 
        !           403:       if (GET_CODE (x) == MULT || GET_CODE (x) == MINUS)
        !           404:        x = force_operand (x, NULL_RTX);
        !           405: 
        !           406:       /* If we have a register that's an invalid address,
        !           407:         it must be a hard reg of the wrong class.  Copy it to a pseudo.  */
        !           408:       else if (GET_CODE (x) == REG)
        !           409:        x = copy_to_reg (x);
        !           410: 
        !           411:       /* Last resort: copy the value to a register, since
        !           412:         the register is a valid address.  */
1.1       root      413:       else
1.1.1.7 ! root      414:        x = force_reg (Pmode, x);
        !           415: 
        !           416:       goto done;
        !           417: 
        !           418:     win2:
        !           419:       x = oldx;
        !           420:     win:
        !           421:       if (flag_force_addr && ! cse_not_expected && GET_CODE (x) != REG
        !           422:          /* Don't copy an addr via a reg if it is one of our stack slots.  */
        !           423:          && ! (GET_CODE (x) == PLUS
        !           424:                && (XEXP (x, 0) == virtual_stack_vars_rtx
        !           425:                    || XEXP (x, 0) == virtual_incoming_args_rtx)))
        !           426:        {
        !           427:          if (general_operand (x, Pmode))
        !           428:            x = force_reg (Pmode, x);
        !           429:          else
        !           430:            x = force_operand (x, NULL_RTX);
        !           431:        }
1.1       root      432:     }
1.1.1.7 ! root      433: 
        !           434:  done:
        !           435: 
        !           436:   /* If we didn't change the address, we are done.  Otherwise, mark
        !           437:      a reg as a pointer if we have REG or REG + CONST_INT.  */
        !           438:   if (oldx == x)
        !           439:     return x;
        !           440:   else if (GET_CODE (x) == REG)
        !           441:     mark_reg_pointer (x);
        !           442:   else if (GET_CODE (x) == PLUS
        !           443:           && GET_CODE (XEXP (x, 0)) == REG
        !           444:           && GET_CODE (XEXP (x, 1)) == CONST_INT)
        !           445:     mark_reg_pointer (XEXP (x, 0));
        !           446: 
        !           447:   /* OLDX may have been the address on a temporary.  Update the address
        !           448:      to indicate that X is now used.  */
        !           449:   update_temp_slot_address (oldx, x);
        !           450: 
1.1       root      451:   return x;
                    452: }
                    453: 
                    454: /* Like `memory_address' but pretend `flag_force_addr' is 0.  */
                    455: 
                    456: rtx
                    457: memory_address_noforce (mode, x)
                    458:      enum machine_mode mode;
                    459:      rtx x;
                    460: {
                    461:   int ambient_force_addr = flag_force_addr;
                    462:   rtx val;
                    463: 
                    464:   flag_force_addr = 0;
                    465:   val = memory_address (mode, x);
                    466:   flag_force_addr = ambient_force_addr;
                    467:   return val;
                    468: }
                    469: 
                    470: /* Convert a mem ref into one with a valid memory address.
                    471:    Pass through anything else unchanged.  */
                    472: 
                    473: rtx
                    474: validize_mem (ref)
                    475:      rtx ref;
                    476: {
                    477:   if (GET_CODE (ref) != MEM)
                    478:     return ref;
                    479:   if (memory_address_p (GET_MODE (ref), XEXP (ref, 0)))
                    480:     return ref;
                    481:   /* Don't alter REF itself, since that is probably a stack slot.  */
                    482:   return change_address (ref, GET_MODE (ref), XEXP (ref, 0));
                    483: }
                    484: 
                    485: /* Return a modified copy of X with its memory address copied
                    486:    into a temporary register to protect it from side effects.
                    487:    If X is not a MEM, it is returned unchanged (and not copied).
                    488:    Perhaps even if it is a MEM, if there is no need to change it.  */
                    489: 
                    490: rtx
                    491: stabilize (x)
                    492:      rtx x;
                    493: {
                    494:   register rtx addr;
                    495:   if (GET_CODE (x) != MEM)
                    496:     return x;
                    497:   addr = XEXP (x, 0);
                    498:   if (rtx_unstable_p (addr))
                    499:     {
                    500:       rtx temp = copy_all_regs (addr);
                    501:       rtx mem;
                    502:       if (GET_CODE (temp) != REG)
                    503:        temp = copy_to_reg (temp);
                    504:       mem = gen_rtx (MEM, GET_MODE (x), temp);
1.1.1.2   root      505: 
                    506:       /* Mark returned memref with in_struct if it's in an array or
                    507:         structure.  Copy const and volatile from original memref.  */
                    508: 
                    509:       MEM_IN_STRUCT_P (mem) = MEM_IN_STRUCT_P (x) || GET_CODE (addr) == PLUS;
                    510:       RTX_UNCHANGING_P (mem) = RTX_UNCHANGING_P (x);
                    511:       MEM_VOLATILE_P (mem) = MEM_VOLATILE_P (x);
1.1       root      512:       return mem;
                    513:     }
                    514:   return x;
                    515: }
                    516: 
                    517: /* Copy the value or contents of X to a new temp reg and return that reg.  */
                    518: 
                    519: rtx
                    520: copy_to_reg (x)
                    521:      rtx x;
                    522: {
                    523:   register rtx temp = gen_reg_rtx (GET_MODE (x));
                    524:  
                    525:   /* If not an operand, must be an address with PLUS and MULT so
                    526:      do the computation.  */ 
                    527:   if (! general_operand (x, VOIDmode))
                    528:     x = force_operand (x, temp);
                    529:   
                    530:   if (x != temp)
                    531:     emit_move_insn (temp, x);
                    532: 
                    533:   return temp;
                    534: }
                    535: 
                    536: /* Like copy_to_reg but always give the new register mode Pmode
                    537:    in case X is a constant.  */
                    538: 
                    539: rtx
                    540: copy_addr_to_reg (x)
                    541:      rtx x;
                    542: {
                    543:   return copy_to_mode_reg (Pmode, x);
                    544: }
                    545: 
                    546: /* Like copy_to_reg but always give the new register mode MODE
                    547:    in case X is a constant.  */
                    548: 
                    549: rtx
                    550: copy_to_mode_reg (mode, x)
                    551:      enum machine_mode mode;
                    552:      rtx x;
                    553: {
                    554:   register rtx temp = gen_reg_rtx (mode);
                    555:   
                    556:   /* If not an operand, must be an address with PLUS and MULT so
                    557:      do the computation.  */ 
                    558:   if (! general_operand (x, VOIDmode))
                    559:     x = force_operand (x, temp);
                    560: 
                    561:   if (GET_MODE (x) != mode && GET_MODE (x) != VOIDmode)
                    562:     abort ();
                    563:   if (x != temp)
                    564:     emit_move_insn (temp, x);
                    565:   return temp;
                    566: }
                    567: 
                    568: /* Load X into a register if it is not already one.
                    569:    Use mode MODE for the register.
                    570:    X should be valid for mode MODE, but it may be a constant which
                    571:    is valid for all integer modes; that's why caller must specify MODE.
                    572: 
                    573:    The caller must not alter the value in the register we return,
                    574:    since we mark it as a "constant" register.  */
                    575: 
                    576: rtx
                    577: force_reg (mode, x)
                    578:      enum machine_mode mode;
                    579:      rtx x;
                    580: {
1.1.1.7 ! root      581:   register rtx temp, insn, set;
1.1       root      582: 
                    583:   if (GET_CODE (x) == REG)
                    584:     return x;
                    585:   temp = gen_reg_rtx (mode);
                    586:   insn = emit_move_insn (temp, x);
1.1.1.7 ! root      587: 
1.1       root      588:   /* Let optimizers know that TEMP's value never changes
1.1.1.7 ! root      589:      and that X can be substituted for it.  Don't get confused
        !           590:      if INSN set something else (such as a SUBREG of TEMP).  */
        !           591:   if (CONSTANT_P (x)
        !           592:       && (set = single_set (insn)) != 0
        !           593:       && SET_DEST (set) == temp)
1.1       root      594:     {
1.1.1.4   root      595:       rtx note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
1.1       root      596: 
                    597:       if (note)
                    598:        XEXP (note, 0) = x;
                    599:       else
                    600:        REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL, x, REG_NOTES (insn));
                    601:     }
                    602:   return temp;
                    603: }
                    604: 
                    605: /* If X is a memory ref, copy its contents to a new temp reg and return
                    606:    that reg.  Otherwise, return X.  */
                    607: 
                    608: rtx
                    609: force_not_mem (x)
                    610:      rtx x;
                    611: {
                    612:   register rtx temp;
                    613:   if (GET_CODE (x) != MEM || GET_MODE (x) == BLKmode)
                    614:     return x;
                    615:   temp = gen_reg_rtx (GET_MODE (x));
                    616:   emit_move_insn (temp, x);
                    617:   return temp;
                    618: }
                    619: 
                    620: /* Copy X to TARGET (if it's nonzero and a reg)
                    621:    or to a new temp reg and return that reg.
1.1.1.2   root      622:    MODE is the mode to use for X in case it is a constant.  */
1.1       root      623: 
                    624: rtx
1.1.1.2   root      625: copy_to_suggested_reg (x, target, mode)
1.1       root      626:      rtx x, target;
1.1.1.2   root      627:      enum machine_mode mode;
1.1       root      628: {
                    629:   register rtx temp;
                    630: 
                    631:   if (target && GET_CODE (target) == REG)
                    632:     temp = target;
                    633:   else
1.1.1.2   root      634:     temp = gen_reg_rtx (mode);
1.1       root      635: 
                    636:   emit_move_insn (temp, x);
                    637:   return temp;
                    638: }
                    639: 
1.1.1.7 ! root      640: /* Return the mode to use to store a scalar of TYPE and MODE.
        !           641:    PUNSIGNEDP points to the signedness of the type and may be adjusted
        !           642:    to show what signedness to use on extension operations.
        !           643: 
        !           644:    FOR_CALL is non-zero if this call is promoting args for a call.  */
        !           645: 
        !           646: enum machine_mode
        !           647: promote_mode (type, mode, punsignedp, for_call)
        !           648:      tree type;
        !           649:      enum machine_mode mode;
        !           650:      int *punsignedp;
        !           651:      int for_call;
        !           652: {
        !           653:   enum tree_code code = TREE_CODE (type);
        !           654:   int unsignedp = *punsignedp;
        !           655: 
        !           656: #ifdef PROMOTE_FOR_CALL_ONLY
        !           657:   if (! for_call)
        !           658:     return mode;
        !           659: #endif
        !           660: 
        !           661:   switch (code)
        !           662:     {
        !           663: #ifdef PROMOTE_MODE
        !           664:     case INTEGER_TYPE:   case ENUMERAL_TYPE:   case BOOLEAN_TYPE:
        !           665:     case CHAR_TYPE:      case REAL_TYPE:       case OFFSET_TYPE:
        !           666:       PROMOTE_MODE (mode, unsignedp, type);
        !           667:       break;
        !           668: #endif
        !           669: 
        !           670:     case POINTER_TYPE:
        !           671:       break;
        !           672:     }
        !           673: 
        !           674:   *punsignedp = unsignedp;
        !           675:   return mode;
        !           676: }
        !           677: 
1.1       root      678: /* Adjust the stack pointer by ADJUST (an rtx for a number of bytes).
                    679:    This pops when ADJUST is positive.  ADJUST need not be constant.  */
                    680: 
                    681: void
                    682: adjust_stack (adjust)
                    683:      rtx adjust;
                    684: {
                    685:   rtx temp;
                    686:   adjust = protect_from_queue (adjust, 0);
                    687: 
                    688:   if (adjust == const0_rtx)
                    689:     return;
                    690: 
                    691:   temp = expand_binop (Pmode,
                    692: #ifdef STACK_GROWS_DOWNWARD
                    693:                       add_optab,
                    694: #else
                    695:                       sub_optab,
                    696: #endif
                    697:                       stack_pointer_rtx, adjust, stack_pointer_rtx, 0,
                    698:                       OPTAB_LIB_WIDEN);
                    699: 
                    700:   if (temp != stack_pointer_rtx)
                    701:     emit_move_insn (stack_pointer_rtx, temp);
                    702: }
                    703: 
                    704: /* Adjust the stack pointer by minus ADJUST (an rtx for a number of bytes).
                    705:    This pushes when ADJUST is positive.  ADJUST need not be constant.  */
                    706: 
                    707: void
                    708: anti_adjust_stack (adjust)
                    709:      rtx adjust;
                    710: {
                    711:   rtx temp;
                    712:   adjust = protect_from_queue (adjust, 0);
                    713: 
                    714:   if (adjust == const0_rtx)
                    715:     return;
                    716: 
                    717:   temp = expand_binop (Pmode,
                    718: #ifdef STACK_GROWS_DOWNWARD
                    719:                       sub_optab,
                    720: #else
                    721:                       add_optab,
                    722: #endif
                    723:                       stack_pointer_rtx, adjust, stack_pointer_rtx, 0,
                    724:                       OPTAB_LIB_WIDEN);
                    725: 
                    726:   if (temp != stack_pointer_rtx)
                    727:     emit_move_insn (stack_pointer_rtx, temp);
                    728: }
                    729: 
                    730: /* Round the size of a block to be pushed up to the boundary required
                    731:    by this machine.  SIZE is the desired size, which need not be constant.  */
                    732: 
                    733: rtx
                    734: round_push (size)
                    735:      rtx size;
                    736: {
                    737: #ifdef STACK_BOUNDARY
                    738:   int align = STACK_BOUNDARY / BITS_PER_UNIT;
                    739:   if (align == 1)
                    740:     return size;
                    741:   if (GET_CODE (size) == CONST_INT)
                    742:     {
                    743:       int new = (INTVAL (size) + align - 1) / align * align;
                    744:       if (INTVAL (size) != new)
1.1.1.4   root      745:        size = GEN_INT (new);
1.1       root      746:     }
                    747:   else
                    748:     {
1.1.1.7 ! root      749:       /* CEIL_DIV_EXPR needs to worry about the addition overflowing,
        !           750:         but we know it can't.  So add ourselves and then do TRUNC_DIV_EXPR. */
        !           751:       size = expand_binop (Pmode, add_optab, size, GEN_INT (align - 1),
        !           752:                           NULL_RTX, 1, OPTAB_LIB_WIDEN);
        !           753:       size = expand_divmod (0, TRUNC_DIV_EXPR, Pmode, size, GEN_INT (align),
1.1.1.4   root      754:                            NULL_RTX, 1);
                    755:       size = expand_mult (Pmode, size, GEN_INT (align), NULL_RTX, 1);
1.1       root      756:     }
                    757: #endif /* STACK_BOUNDARY */
                    758:   return size;
                    759: }
                    760: 
1.1.1.3   root      761: /* Save the stack pointer for the purpose in SAVE_LEVEL.  PSAVE is a pointer
                    762:    to a previously-created save area.  If no save area has been allocated,
                    763:    this function will allocate one.  If a save area is specified, it
                    764:    must be of the proper mode.
                    765: 
                    766:    The insns are emitted after insn AFTER, if nonzero, otherwise the insns
                    767:    are emitted at the current position.  */
                    768: 
                    769: void
                    770: emit_stack_save (save_level, psave, after)
                    771:      enum save_level save_level;
                    772:      rtx *psave;
                    773:      rtx after;
                    774: {
                    775:   rtx sa = *psave;
                    776:   /* The default is that we use a move insn and save in a Pmode object.  */
                    777:   rtx (*fcn) () = gen_move_insn;
                    778:   enum machine_mode mode = Pmode;
                    779: 
                    780:   /* See if this machine has anything special to do for this kind of save.  */
                    781:   switch (save_level)
                    782:     {
                    783: #ifdef HAVE_save_stack_block
                    784:     case SAVE_BLOCK:
                    785:       if (HAVE_save_stack_block)
                    786:        {
                    787:          fcn = gen_save_stack_block;
                    788:          mode = insn_operand_mode[CODE_FOR_save_stack_block][0];
                    789:        }
                    790:       break;
                    791: #endif
                    792: #ifdef HAVE_save_stack_function
                    793:     case SAVE_FUNCTION:
                    794:       if (HAVE_save_stack_function)
                    795:        {
                    796:          fcn = gen_save_stack_function;
                    797:          mode = insn_operand_mode[CODE_FOR_save_stack_function][0];
                    798:        }
                    799:       break;
                    800: #endif
                    801: #ifdef HAVE_save_stack_nonlocal
                    802:     case SAVE_NONLOCAL:
                    803:       if (HAVE_save_stack_nonlocal)
                    804:        {
                    805:          fcn = gen_save_stack_nonlocal;
1.1.1.6   root      806:          mode = insn_operand_mode[(int) CODE_FOR_save_stack_nonlocal][0];
1.1.1.3   root      807:        }
                    808:       break;
                    809: #endif
                    810:     }
                    811: 
                    812:   /* If there is no save area and we have to allocate one, do so.  Otherwise
                    813:      verify the save area is the proper mode.  */
                    814: 
                    815:   if (sa == 0)
                    816:     {
                    817:       if (mode != VOIDmode)
                    818:        {
                    819:          if (save_level == SAVE_NONLOCAL)
                    820:            *psave = sa = assign_stack_local (mode, GET_MODE_SIZE (mode), 0);
                    821:          else
                    822:            *psave = sa = gen_reg_rtx (mode);
                    823:        }
                    824:     }
                    825:   else
                    826:     {
                    827:       if (mode == VOIDmode || GET_MODE (sa) != mode)
                    828:        abort ();
                    829:     }
                    830: 
                    831:   if (after)
                    832:     {
                    833:       rtx seq;
                    834: 
                    835:       start_sequence ();
1.1.1.5   root      836:       /* We must validize inside the sequence, to ensure that any instructions
                    837:         created by the validize call also get moved to the right place.  */
                    838:       if (sa != 0)
                    839:        sa = validize_mem (sa);
1.1.1.3   root      840:       emit_insn (fcn (sa, stack_pointer_rtx));
                    841:       seq = gen_sequence ();
                    842:       end_sequence ();
                    843:       emit_insn_after (seq, after);
                    844:     }
                    845:   else
1.1.1.5   root      846:     {
                    847:       if (sa != 0)
                    848:        sa = validize_mem (sa);
                    849:       emit_insn (fcn (sa, stack_pointer_rtx));
                    850:     }
1.1.1.3   root      851: }
                    852: 
                    853: /* Restore the stack pointer for the purpose in SAVE_LEVEL.  SA is the save
                    854:    area made by emit_stack_save.  If it is zero, we have nothing to do. 
                    855: 
                    856:    Put any emitted insns after insn AFTER, if nonzero, otherwise at 
                    857:    current position.  */
                    858: 
                    859: void
                    860: emit_stack_restore (save_level, sa, after)
                    861:      enum save_level save_level;
                    862:      rtx after;
                    863:      rtx sa;
                    864: {
                    865:   /* The default is that we use a move insn.  */
                    866:   rtx (*fcn) () = gen_move_insn;
                    867: 
                    868:   /* See if this machine has anything special to do for this kind of save.  */
                    869:   switch (save_level)
                    870:     {
                    871: #ifdef HAVE_restore_stack_block
                    872:     case SAVE_BLOCK:
                    873:       if (HAVE_restore_stack_block)
                    874:        fcn = gen_restore_stack_block;
                    875:       break;
                    876: #endif
                    877: #ifdef HAVE_restore_stack_function
                    878:     case SAVE_FUNCTION:
                    879:       if (HAVE_restore_stack_function)
                    880:        fcn = gen_restore_stack_function;
                    881:       break;
                    882: #endif
                    883: #ifdef HAVE_restore_stack_nonlocal
                    884: 
                    885:     case SAVE_NONLOCAL:
                    886:       if (HAVE_restore_stack_nonlocal)
                    887:        fcn = gen_restore_stack_nonlocal;
                    888:       break;
                    889: #endif
                    890:     }
                    891: 
                    892:   if (sa != 0)
                    893:     sa = validize_mem (sa);
                    894: 
                    895:   if (after)
                    896:     {
                    897:       rtx seq;
                    898: 
                    899:       start_sequence ();
                    900:       emit_insn (fcn (stack_pointer_rtx, sa));
                    901:       seq = gen_sequence ();
                    902:       end_sequence ();
                    903:       emit_insn_after (seq, after);
                    904:     }
                    905:   else
                    906:     emit_insn (fcn (stack_pointer_rtx, sa));
                    907: }
                    908: 
1.1       root      909: /* Return an rtx representing the address of an area of memory dynamically
                    910:    pushed on the stack.  This region of memory is always aligned to
                    911:    a multiple of BIGGEST_ALIGNMENT.
                    912: 
                    913:    Any required stack pointer alignment is preserved.
                    914: 
                    915:    SIZE is an rtx representing the size of the area.
1.1.1.3   root      916:    TARGET is a place in which the address can be placed.
                    917: 
                    918:    KNOWN_ALIGN is the alignment (in bits) that we know SIZE has.  */
1.1       root      919: 
                    920: rtx
1.1.1.3   root      921: allocate_dynamic_stack_space (size, target, known_align)
1.1       root      922:      rtx size;
                    923:      rtx target;
1.1.1.3   root      924:      int known_align;
1.1       root      925: {
1.1.1.7 ! root      926:   /* If we're asking for zero bytes, it doesn't matter what we point
        !           927:      to since we can't derefference it.  But return a reasonable
        !           928:      address anyway.  */
        !           929:   if (size == const0_rtx)
        !           930:     return virtual_stack_dynamic_rtx;
        !           931: 
        !           932:   /* Otherwise, show we're calling alloca or equivalent.  */
        !           933:   current_function_calls_alloca = 1;
        !           934: 
1.1       root      935:   /* Ensure the size is in the proper mode.  */
                    936:   if (GET_MODE (size) != VOIDmode && GET_MODE (size) != Pmode)
                    937:     size = convert_to_mode (Pmode, size, 1);
                    938: 
                    939:   /* We will need to ensure that the address we return is aligned to
                    940:      BIGGEST_ALIGNMENT.  If STACK_DYNAMIC_OFFSET is defined, we don't
                    941:      always know its final value at this point in the compilation (it 
                    942:      might depend on the size of the outgoing parameter lists, for
                    943:      example), so we must align the value to be returned in that case.
                    944:      (Note that STACK_DYNAMIC_OFFSET will have a default non-zero value if
                    945:      STACK_POINTER_OFFSET or ACCUMULATE_OUTGOING_ARGS are defined).
                    946:      We must also do an alignment operation on the returned value if
                    947:      the stack pointer alignment is less strict that BIGGEST_ALIGNMENT.
                    948: 
                    949:      If we have to align, we must leave space in SIZE for the hole
                    950:      that might result from the alignment operation.  */
                    951: 
                    952: #if defined (STACK_DYNAMIC_OFFSET) || defined(STACK_POINTER_OFFSET) || defined (ALLOCATE_OUTGOING_ARGS)
                    953: #define MUST_ALIGN
                    954: #endif
                    955: 
                    956: #if ! defined (MUST_ALIGN) && (!defined(STACK_BOUNDARY) || STACK_BOUNDARY < BIGGEST_ALIGNMENT)
                    957: #define MUST_ALIGN
                    958: #endif
                    959: 
                    960: #ifdef MUST_ALIGN
                    961: 
1.1.1.4   root      962: #if 0 /* It turns out we must always make extra space, if MUST_ALIGN
                    963:         because we must always round the address up at the end,
                    964:         because we don't know whether the dynamic offset
                    965:         will mess up the desired alignment.  */
                    966:   /* If we have to round the address up regardless of known_align,
                    967:      make extra space regardless, also.  */
1.1.1.3   root      968:   if (known_align % BIGGEST_ALIGNMENT != 0)
1.1.1.4   root      969: #endif
1.1.1.3   root      970:     {
                    971:       if (GET_CODE (size) == CONST_INT)
1.1.1.4   root      972:        size = GEN_INT (INTVAL (size)
                    973:                        + (BIGGEST_ALIGNMENT / BITS_PER_UNIT - 1));
1.1.1.3   root      974:       else
                    975:        size = expand_binop (Pmode, add_optab, size,
1.1.1.4   root      976:                             GEN_INT (BIGGEST_ALIGNMENT / BITS_PER_UNIT - 1),
                    977:                             NULL_RTX, 1, OPTAB_LIB_WIDEN);
1.1.1.3   root      978:     }
1.1.1.4   root      979: 
1.1       root      980: #endif
                    981: 
                    982: #ifdef SETJMP_VIA_SAVE_AREA
                    983:   /* If setjmp restores regs from a save area in the stack frame,
                    984:      avoid clobbering the reg save area.  Note that the offset of
                    985:      virtual_incoming_args_rtx includes the preallocated stack args space.
                    986:      It would be no problem to clobber that, but it's on the wrong side
                    987:      of the old save area.  */
                    988:   {
                    989:     rtx dynamic_offset
                    990:       = expand_binop (Pmode, sub_optab, virtual_stack_dynamic_rtx,
1.1.1.4   root      991:                      stack_pointer_rtx, NULL_RTX, 1, OPTAB_LIB_WIDEN);
1.1       root      992:     size = expand_binop (Pmode, add_optab, size, dynamic_offset,
1.1.1.4   root      993:                         NULL_RTX, 1, OPTAB_LIB_WIDEN);
1.1       root      994:   }
                    995: #endif /* SETJMP_VIA_SAVE_AREA */
                    996: 
                    997:   /* Round the size to a multiple of the required stack alignment.
                    998:      Since the stack if presumed to be rounded before this allocation,
                    999:      this will maintain the required alignment.
                   1000: 
                   1001:      If the stack grows downward, we could save an insn by subtracting
                   1002:      SIZE from the stack pointer and then aligning the stack pointer.
                   1003:      The problem with this is that the stack pointer may be unaligned
                   1004:      between the execution of the subtraction and alignment insns and
                   1005:      some machines do not allow this.  Even on those that do, some
                   1006:      signal handlers malfunction if a signal should occur between those
                   1007:      insns.  Since this is an extremely rare event, we have no reliable
                   1008:      way of knowing which systems have this problem.  So we avoid even
                   1009:      momentarily mis-aligning the stack.  */
                   1010: 
1.1.1.3   root     1011: #ifdef STACK_BOUNDARY
1.1.1.4   root     1012:   /* If we added a variable amount to SIZE,
                   1013:      we can no longer assume it is aligned.  */
                   1014: #if !defined (SETJMP_VIA_SAVE_AREA) && !defined (MUST_ALIGN)
1.1.1.3   root     1015:   if (known_align % STACK_BOUNDARY != 0)
1.1.1.4   root     1016: #endif
1.1.1.3   root     1017:     size = round_push (size);
                   1018: #endif
1.1       root     1019: 
                   1020:   do_pending_stack_adjust ();
                   1021: 
1.1.1.3   root     1022:   /* Don't use a TARGET that isn't a pseudo.  */
                   1023:   if (target == 0 || GET_CODE (target) != REG
                   1024:       || REGNO (target) < FIRST_PSEUDO_REGISTER)
1.1       root     1025:     target = gen_reg_rtx (Pmode);
                   1026: 
1.1.1.3   root     1027:   mark_reg_pointer (target);
                   1028: 
1.1       root     1029: #ifndef STACK_GROWS_DOWNWARD
                   1030:   emit_move_insn (target, virtual_stack_dynamic_rtx);
                   1031: #endif
                   1032: 
                   1033:   /* Perform the required allocation from the stack.  Some systems do
                   1034:      this differently than simply incrementing/decrementing from the
                   1035:      stack pointer.  */
                   1036: #ifdef HAVE_allocate_stack
                   1037:   if (HAVE_allocate_stack)
                   1038:     {
                   1039:       enum machine_mode mode
                   1040:        = insn_operand_mode[(int) CODE_FOR_allocate_stack][0];
                   1041: 
                   1042:       if (insn_operand_predicate[(int) CODE_FOR_allocate_stack][0]
                   1043:          && ! ((*insn_operand_predicate[(int) CODE_FOR_allocate_stack][0])
                   1044:                (size, mode)))
                   1045:        size = copy_to_mode_reg (mode, size);
                   1046: 
                   1047:       emit_insn (gen_allocate_stack (size));
                   1048:     }
                   1049:   else
                   1050: #endif
                   1051:     anti_adjust_stack (size);
                   1052: 
                   1053: #ifdef STACK_GROWS_DOWNWARD
                   1054:   emit_move_insn (target, virtual_stack_dynamic_rtx);
                   1055: #endif
                   1056: 
                   1057: #ifdef MUST_ALIGN
1.1.1.4   root     1058: #if 0  /* Even if we know the stack pointer has enough alignment,
                   1059:          there's no way to tell whether virtual_stack_dynamic_rtx shares that
                   1060:          alignment, so we still need to round the address up.  */
1.1.1.3   root     1061:   if (known_align % BIGGEST_ALIGNMENT != 0)
1.1.1.4   root     1062: #endif
1.1.1.3   root     1063:     {
1.1.1.7 ! root     1064:       /* CEIL_DIV_EXPR needs to worry about the addition overflowing,
        !          1065:         but we know it can't.  So add ourselves and then do TRUNC_DIV_EXPR. */
        !          1066:       target = expand_binop (Pmode, add_optab, target,
        !          1067:                             GEN_INT (BIGGEST_ALIGNMENT / BITS_PER_UNIT - 1),
        !          1068:                             NULL_RTX, 1, OPTAB_LIB_WIDEN);
        !          1069:       target = expand_divmod (0, TRUNC_DIV_EXPR, Pmode, target,
1.1.1.4   root     1070:                              GEN_INT (BIGGEST_ALIGNMENT / BITS_PER_UNIT),
                   1071:                              NULL_RTX, 1);
1.1.1.3   root     1072:       target = expand_mult (Pmode, target,
1.1.1.4   root     1073:                            GEN_INT (BIGGEST_ALIGNMENT / BITS_PER_UNIT),
                   1074:                            NULL_RTX, 1);
1.1.1.3   root     1075:     }
1.1       root     1076: #endif
                   1077:   
                   1078:   /* Some systems require a particular insn to refer to the stack
                   1079:      to make the pages exist.  */
                   1080: #ifdef HAVE_probe
                   1081:   if (HAVE_probe)
                   1082:     emit_insn (gen_probe ());
                   1083: #endif
                   1084: 
1.1.1.7 ! root     1085:   /* Record the new stack level for nonlocal gotos.  */
        !          1086:   if (nonlocal_goto_handler_slot != 0)
        !          1087:     emit_stack_save (SAVE_NONLOCAL, &nonlocal_goto_stack_level, NULL_RTX);
        !          1088: 
1.1       root     1089:   return target;
                   1090: }
                   1091: 
                   1092: /* Return an rtx representing the register or memory location
                   1093:    in which a scalar value of data type VALTYPE
                   1094:    was returned by a function call to function FUNC.
                   1095:    FUNC is a FUNCTION_DECL node if the precise function is known,
                   1096:    otherwise 0.  */
                   1097: 
                   1098: rtx
                   1099: hard_function_value (valtype, func)
                   1100:      tree valtype;
                   1101:      tree func;
                   1102: {
                   1103:   return FUNCTION_VALUE (valtype, func);
                   1104: }
                   1105: 
                   1106: /* Return an rtx representing the register or memory location
                   1107:    in which a scalar value of mode MODE was returned by a library call.  */
                   1108: 
                   1109: rtx
                   1110: hard_libcall_value (mode)
                   1111:      enum machine_mode mode;
                   1112: {
                   1113:   return LIBCALL_VALUE (mode);
                   1114: }
1.1.1.5   root     1115: 
                   1116: /* Look up the tree code for a given rtx code
                   1117:    to provide the arithmetic operation for REAL_ARITHMETIC.
                   1118:    The function returns an int because the caller may not know
                   1119:    what `enum tree_code' means.  */
                   1120: 
                   1121: int
                   1122: rtx_to_tree_code (code)
                   1123:      enum rtx_code code;
                   1124: {
                   1125:   enum tree_code tcode;
                   1126: 
                   1127:   switch (code)
                   1128:     {
                   1129:     case PLUS:
                   1130:       tcode = PLUS_EXPR;
                   1131:       break;
                   1132:     case MINUS:
                   1133:       tcode = MINUS_EXPR;
                   1134:       break;
                   1135:     case MULT:
                   1136:       tcode = MULT_EXPR;
                   1137:       break;
                   1138:     case DIV:
                   1139:       tcode = RDIV_EXPR;
                   1140:       break;
                   1141:     case SMIN:
                   1142:       tcode = MIN_EXPR;
                   1143:       break;
                   1144:     case SMAX:
                   1145:       tcode = MAX_EXPR;
                   1146:       break;
                   1147:     default:
                   1148:       tcode = LAST_AND_UNUSED_TREE_CODE;
                   1149:       break;
                   1150:     }
                   1151:   return ((int) tcode);
                   1152: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.