Annotation of GNUtools/cc/optabs.c, revision 1.1.1.1

1.1       root        1: /* Expand the basic unary and binary arithmetic operations, for GNU compiler.
                      2:    Copyright (C) 1987, 1988, 1992, 1993 Free Software Foundation, Inc.
                      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 "insn-flags.h"
                     26: #include "insn-codes.h"
                     27: #include "expr.h"
                     28: #include "insn-config.h"
                     29: #include "recog.h"
                     30: #include "reload.h"
                     31: #include <ctype.h>
                     32: 
                     33: /* Each optab contains info on how this target machine
                     34:    can perform a particular operation
                     35:    for all sizes and kinds of operands.
                     36: 
                     37:    The operation to be performed is often specified
                     38:    by passing one of these optabs as an argument.
                     39: 
                     40:    See expr.h for documentation of these optabs.  */
                     41: 
                     42: optab add_optab;
                     43: optab sub_optab;
                     44: optab smul_optab;
                     45: optab smul_widen_optab;
                     46: optab umul_widen_optab;
                     47: optab sdiv_optab;
                     48: optab sdivmod_optab;
                     49: optab udiv_optab;
                     50: optab udivmod_optab;
                     51: optab smod_optab;
                     52: optab umod_optab;
                     53: optab flodiv_optab;
                     54: optab ftrunc_optab;
                     55: optab and_optab;
                     56: optab ior_optab;
                     57: optab xor_optab;
                     58: optab ashl_optab;
                     59: optab lshr_optab;
                     60: optab lshl_optab;
                     61: optab ashr_optab;
                     62: optab rotl_optab;
                     63: optab rotr_optab;
                     64: optab smin_optab;
                     65: optab smax_optab;
                     66: optab umin_optab;
                     67: optab umax_optab;
                     68: 
                     69: optab mov_optab;
                     70: optab movstrict_optab;
                     71: 
                     72: optab neg_optab;
                     73: optab abs_optab;
                     74: optab one_cmpl_optab;
                     75: optab ffs_optab;
                     76: optab sqrt_optab;
                     77: optab sin_optab;
                     78: optab cos_optab;
                     79: 
                     80: optab cmp_optab;
                     81: optab ucmp_optab;  /* Used only for libcalls for unsigned comparisons.  */
                     82: optab tst_optab;
                     83: 
                     84: optab strlen_optab;
                     85: 
                     86: /* Tables of patterns for extending one integer mode to another.  */
                     87: enum insn_code extendtab[MAX_MACHINE_MODE][MAX_MACHINE_MODE][2];
                     88: 
                     89: /* Tables of patterns for converting between fixed and floating point. */
                     90: enum insn_code fixtab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
                     91: enum insn_code fixtrunctab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
                     92: enum insn_code floattab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
                     93: 
                     94: /* Contains the optab used for each rtx code.  */
                     95: optab code_to_optab[NUM_RTX_CODE + 1];
                     96: 
                     97: /* SYMBOL_REF rtx's for the library functions that are called
                     98:    implicitly and not via optabs.  */
                     99: 
                    100: rtx extendsfdf2_libfunc;
                    101: rtx extendsfxf2_libfunc;
                    102: rtx extendsftf2_libfunc;
                    103: rtx extenddfxf2_libfunc;
                    104: rtx extenddftf2_libfunc;
                    105: 
                    106: rtx truncdfsf2_libfunc;
                    107: rtx truncxfsf2_libfunc;
                    108: rtx trunctfsf2_libfunc;
                    109: rtx truncxfdf2_libfunc;
                    110: rtx trunctfdf2_libfunc;
                    111: 
                    112: rtx memcpy_libfunc;
                    113: rtx bcopy_libfunc;
                    114: rtx memcmp_libfunc;
                    115: rtx bcmp_libfunc;
                    116: rtx memset_libfunc;
                    117: rtx bzero_libfunc;
                    118: 
                    119: rtx eqsf2_libfunc;
                    120: rtx nesf2_libfunc;
                    121: rtx gtsf2_libfunc;
                    122: rtx gesf2_libfunc;
                    123: rtx ltsf2_libfunc;
                    124: rtx lesf2_libfunc;
                    125: 
                    126: rtx eqdf2_libfunc;
                    127: rtx nedf2_libfunc;
                    128: rtx gtdf2_libfunc;
                    129: rtx gedf2_libfunc;
                    130: rtx ltdf2_libfunc;
                    131: rtx ledf2_libfunc;
                    132: 
                    133: rtx eqxf2_libfunc;
                    134: rtx nexf2_libfunc;
                    135: rtx gtxf2_libfunc;
                    136: rtx gexf2_libfunc;
                    137: rtx ltxf2_libfunc;
                    138: rtx lexf2_libfunc;
                    139: 
                    140: rtx eqtf2_libfunc;
                    141: rtx netf2_libfunc;
                    142: rtx gttf2_libfunc;
                    143: rtx getf2_libfunc;
                    144: rtx lttf2_libfunc;
                    145: rtx letf2_libfunc;
                    146: 
                    147: rtx floatsisf_libfunc;
                    148: rtx floatdisf_libfunc;
                    149: rtx floattisf_libfunc;
                    150: 
                    151: rtx floatsidf_libfunc;
                    152: rtx floatdidf_libfunc;
                    153: rtx floattidf_libfunc;
                    154: 
                    155: rtx floatsixf_libfunc;
                    156: rtx floatdixf_libfunc;
                    157: rtx floattixf_libfunc;
                    158: 
                    159: rtx floatsitf_libfunc;
                    160: rtx floatditf_libfunc;
                    161: rtx floattitf_libfunc;
                    162: 
                    163: rtx fixsfsi_libfunc;
                    164: rtx fixsfdi_libfunc;
                    165: rtx fixsfti_libfunc;
                    166: 
                    167: rtx fixdfsi_libfunc;
                    168: rtx fixdfdi_libfunc;
                    169: rtx fixdfti_libfunc;
                    170: 
                    171: rtx fixxfsi_libfunc;
                    172: rtx fixxfdi_libfunc;
                    173: rtx fixxfti_libfunc;
                    174: 
                    175: rtx fixtfsi_libfunc;
                    176: rtx fixtfdi_libfunc;
                    177: rtx fixtfti_libfunc;
                    178: 
                    179: rtx fixunssfsi_libfunc;
                    180: rtx fixunssfdi_libfunc;
                    181: rtx fixunssfti_libfunc;
                    182: 
                    183: rtx fixunsdfsi_libfunc;
                    184: rtx fixunsdfdi_libfunc;
                    185: rtx fixunsdfti_libfunc;
                    186: 
                    187: rtx fixunsxfsi_libfunc;
                    188: rtx fixunsxfdi_libfunc;
                    189: rtx fixunsxfti_libfunc;
                    190: 
                    191: rtx fixunstfsi_libfunc;
                    192: rtx fixunstfdi_libfunc;
                    193: rtx fixunstfti_libfunc;
                    194: 
                    195: /* from emit-rtl.c */
                    196: extern rtx gen_highpart ();
                    197: 
                    198: /* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
                    199:    gives the gen_function to make a branch to test that condition.  */
                    200: 
                    201: rtxfun bcc_gen_fctn[NUM_RTX_CODE];
                    202: 
                    203: /* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
                    204:    gives the insn code to make a store-condition insn
                    205:    to test that condition.  */
                    206: 
                    207: enum insn_code setcc_gen_code[NUM_RTX_CODE];
                    208: 
                    209: static int add_equal_note      PROTO((rtx, rtx, enum rtx_code, rtx, rtx));
                    210: static rtx widen_operand       PROTO((rtx, enum machine_mode, enum machine_mode, int, int));
                    211: static void emit_float_lib_cmp PROTO((rtx, rtx, enum rtx_code));
                    212: static enum insn_code can_fix_p        PROTO((enum machine_mode, enum machine_mode,
                    213:                                       int, int *));
                    214: static enum insn_code can_float_p PROTO((enum machine_mode, enum machine_mode,
                    215:                                         int));
                    216: static rtx ftruncify   PROTO((rtx));
                    217: static optab init_optab        PROTO((enum rtx_code));
                    218: static void init_libfuncs PROTO((optab, int, int, char *, int));
                    219: static void init_integral_libfuncs PROTO((optab, char *, int));
                    220: static void init_floating_libfuncs PROTO((optab, char *, int));
                    221: static void init_complex_libfuncs PROTO((optab, char *, int));
                    222: 
                    223: /* Add a REG_EQUAL note to the last insn in SEQ.  TARGET is being set to
                    224:    the result of operation CODE applied to OP0 (and OP1 if it is a binary
                    225:    operation).
                    226: 
                    227:    If the last insn does not set TARGET, don't do anything, but return 1.
                    228: 
                    229:    If a previous insn sets TARGET and TARGET is one of OP0 or OP1,
                    230:    don't add the REG_EQUAL note but return 0.  Our caller can then try
                    231:    again, ensuring that TARGET is not one of the operands.  */
                    232: 
                    233: static int
                    234: add_equal_note (seq, target, code, op0, op1)
                    235:      rtx seq;
                    236:      rtx target;
                    237:      enum rtx_code code;
                    238:      rtx op0, op1;
                    239: {
                    240:   rtx set;
                    241:   int i;
                    242:   rtx note;
                    243: 
                    244:   if ((GET_RTX_CLASS (code) != '1' && GET_RTX_CLASS (code) != '2'
                    245:        && GET_RTX_CLASS (code) != 'c' && GET_RTX_CLASS (code) != '<')
                    246:       || GET_CODE (seq) != SEQUENCE
                    247:       || (set = single_set (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1))) == 0
                    248:       || GET_CODE (target) == ZERO_EXTRACT
                    249:       || (! rtx_equal_p (SET_DEST (set), target)
                    250:          /* For a STRICT_LOW_PART, the REG_NOTE applies to what is inside the
                    251:             SUBREG.  */
                    252:          && (GET_CODE (SET_DEST (set)) != STRICT_LOW_PART
                    253:              || ! rtx_equal_p (SUBREG_REG (XEXP (SET_DEST (set), 0)),
                    254:                                target))))
                    255:     return 1;
                    256: 
                    257:   /* If TARGET is in OP0 or OP1, check if anything in SEQ sets TARGET
                    258:      besides the last insn.  */
                    259:   if (reg_overlap_mentioned_p (target, op0)
                    260:       || (op1 && reg_overlap_mentioned_p (target, op1)))
                    261:     for (i = XVECLEN (seq, 0) - 2; i >= 0; i--)
                    262:       if (reg_set_p (target, XVECEXP (seq, 0, i)))
                    263:        return 0;
                    264: 
                    265:   if (GET_RTX_CLASS (code) == '1')
                    266:     note = gen_rtx (code, GET_MODE (target), copy_rtx (op0));
                    267:   else
                    268:     note = gen_rtx (code, GET_MODE (target), copy_rtx (op0), copy_rtx (op1));
                    269: 
                    270:   REG_NOTES (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1))
                    271:     = gen_rtx (EXPR_LIST, REG_EQUAL, note,
                    272:               REG_NOTES (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1)));
                    273: 
                    274:   return 1;
                    275: }
                    276: 
                    277: /* Widen OP to MODE and return the rtx for the widened operand.  UNSIGNEDP
                    278:    says whether OP is signed or unsigned.  NO_EXTEND is nonzero if we need
                    279:    not actually do a sign-extend or zero-extend, but can leave the 
                    280:    higher-order bits of the result rtx undefined, for example, in the case
                    281:    of logical operations, but not right shifts.  */
                    282: 
                    283: static rtx
                    284: widen_operand (op, mode, oldmode, unsignedp, no_extend)
                    285:      rtx op;
                    286:      enum machine_mode mode, oldmode;
                    287:      int unsignedp;
                    288:      int no_extend;
                    289: {
                    290:   rtx result;
                    291: 
                    292:   /* If we must extend do so.  If OP is either a constant or a SUBREG
                    293:      for a promoted object, also extend since it will be more efficient to
                    294:      do so.  */
                    295:   if (! no_extend
                    296:       || GET_MODE (op) == VOIDmode
                    297:       || (GET_CODE (op) == SUBREG && SUBREG_PROMOTED_VAR_P (op)))
                    298:     return convert_modes (mode, oldmode, op, unsignedp);
                    299: 
                    300:   /* If MODE is no wider than a single word, we return a paradoxical
                    301:      SUBREG.  */
                    302:   if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
                    303:     return gen_rtx (SUBREG, mode, force_reg (GET_MODE (op), op), 0);
                    304: 
                    305:   /* Otherwise, get an object of MODE, clobber it, and set the low-order
                    306:      part to OP.  */
                    307: 
                    308:   result = gen_reg_rtx (mode);
                    309:   emit_insn (gen_rtx (CLOBBER, VOIDmode, result));
                    310:   emit_move_insn (gen_lowpart (GET_MODE (op), result), op);
                    311:   return result;
                    312: }
                    313: 
                    314: /* Generate code to perform an operation specified by BINOPTAB
                    315:    on operands OP0 and OP1, with result having machine-mode MODE.
                    316: 
                    317:    UNSIGNEDP is for the case where we have to widen the operands
                    318:    to perform the operation.  It says to use zero-extension.
                    319: 
                    320:    If TARGET is nonzero, the value
                    321:    is generated there, if it is convenient to do so.
                    322:    In all cases an rtx is returned for the locus of the value;
                    323:    this may or may not be TARGET.  */
                    324: 
                    325: rtx
                    326: expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
                    327:      enum machine_mode mode;
                    328:      optab binoptab;
                    329:      rtx op0, op1;
                    330:      rtx target;
                    331:      int unsignedp;
                    332:      enum optab_methods methods;
                    333: {
                    334:   enum mode_class class;
                    335:   enum machine_mode wider_mode;
                    336:   register rtx temp;
                    337:   int commutative_op = 0;
                    338:   int shift_op = (binoptab->code ==  ASHIFT
                    339:                  || binoptab->code == ASHIFTRT
                    340:                  || binoptab->code == LSHIFT
                    341:                  || binoptab->code == LSHIFTRT
                    342:                  || binoptab->code == ROTATE
                    343:                  || binoptab->code == ROTATERT);
                    344:   rtx entry_last = get_last_insn ();
                    345:   rtx last;
                    346: 
                    347:   class = GET_MODE_CLASS (mode);
                    348: 
                    349:   op0 = protect_from_queue (op0, 0);
                    350:   op1 = protect_from_queue (op1, 0);
                    351:   if (target)
                    352:     target = protect_from_queue (target, 1);
                    353: 
                    354:   if (flag_force_mem)
                    355:     {
                    356:       op0 = force_not_mem (op0);
                    357:       op1 = force_not_mem (op1);
                    358:     }
                    359: 
                    360:   /* If subtracting an integer constant, convert this into an addition of
                    361:      the negated constant.  */
                    362: 
                    363:   if (binoptab == sub_optab && GET_CODE (op1) == CONST_INT)
                    364:     {
                    365:       op1 = negate_rtx (mode, op1);
                    366:       binoptab = add_optab;
                    367:     }
                    368: 
                    369:   /* If we are inside an appropriately-short loop and one operand is an
                    370:      expensive constant, force it into a register.  */
                    371:   if (CONSTANT_P (op0) && preserve_subexpressions_p ()
                    372:       && rtx_cost (op0, binoptab->code) > 2)
                    373:     op0 = force_reg (mode, op0);
                    374: 
                    375:   if (CONSTANT_P (op1) && preserve_subexpressions_p ()
                    376:       && rtx_cost (op1, binoptab->code) > 2)
                    377:     op1 = force_reg (shift_op ? word_mode : mode, op1);
                    378: 
                    379:   /* Record where to delete back to if we backtrack.  */
                    380:   last = get_last_insn ();
                    381: 
                    382:   /* If operation is commutative,
                    383:      try to make the first operand a register.
                    384:      Even better, try to make it the same as the target.
                    385:      Also try to make the last operand a constant.  */
                    386:   if (GET_RTX_CLASS (binoptab->code) == 'c'
                    387:       || binoptab == smul_widen_optab
                    388:       || binoptab == umul_widen_optab)
                    389:     {
                    390:       commutative_op = 1;
                    391: 
                    392:       if (((target == 0 || GET_CODE (target) == REG)
                    393:           ? ((GET_CODE (op1) == REG
                    394:               && GET_CODE (op0) != REG)
                    395:              || target == op1)
                    396:           : rtx_equal_p (op1, target))
                    397:          || GET_CODE (op0) == CONST_INT)
                    398:        {
                    399:          temp = op1;
                    400:          op1 = op0;
                    401:          op0 = temp;
                    402:        }
                    403:     }
                    404: 
                    405:   /* If we can do it with a three-operand insn, do so.  */
                    406: 
                    407:   if (methods != OPTAB_MUST_WIDEN
                    408:       && binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
                    409:     {
                    410:       int icode = (int) binoptab->handlers[(int) mode].insn_code;
                    411:       enum machine_mode mode0 = insn_operand_mode[icode][1];
                    412:       enum machine_mode mode1 = insn_operand_mode[icode][2];
                    413:       rtx pat;
                    414:       rtx xop0 = op0, xop1 = op1;
                    415: 
                    416:       if (target)
                    417:        temp = target;
                    418:       else
                    419:        temp = gen_reg_rtx (mode);
                    420: 
                    421:       /* If it is a commutative operator and the modes would match
                    422:         if we would swap the operands, we can save the conversions. */
                    423:       if (commutative_op)
                    424:        {
                    425:          if (GET_MODE (op0) != mode0 && GET_MODE (op1) != mode1
                    426:              && GET_MODE (op0) == mode1 && GET_MODE (op1) == mode0)
                    427:            {
                    428:              register rtx tmp;
                    429: 
                    430:              tmp = op0; op0 = op1; op1 = tmp;
                    431:              tmp = xop0; xop0 = xop1; xop1 = tmp;
                    432:            }
                    433:        }
                    434: 
                    435:       /* In case the insn wants input operands in modes different from
                    436:         the result, convert the operands.  */
                    437: 
                    438:       if (GET_MODE (op0) != VOIDmode
                    439:          && GET_MODE (op0) != mode0)
                    440:        xop0 = convert_to_mode (mode0, xop0, unsignedp);
                    441: 
                    442:       if (GET_MODE (xop1) != VOIDmode
                    443:          && GET_MODE (xop1) != mode1)
                    444:        xop1 = convert_to_mode (mode1, xop1, unsignedp);
                    445: 
                    446:       /* Now, if insn's predicates don't allow our operands, put them into
                    447:         pseudo regs.  */
                    448: 
                    449:       if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))
                    450:        xop0 = copy_to_mode_reg (mode0, xop0);
                    451: 
                    452:       if (! (*insn_operand_predicate[icode][2]) (xop1, mode1))
                    453:        xop1 = copy_to_mode_reg (mode1, xop1);
                    454: 
                    455:       if (! (*insn_operand_predicate[icode][0]) (temp, mode))
                    456:        temp = gen_reg_rtx (mode);
                    457: 
                    458:       pat = GEN_FCN (icode) (temp, xop0, xop1);
                    459:       if (pat)
                    460:        {
                    461:          /* If PAT is a multi-insn sequence, try to add an appropriate
                    462:             REG_EQUAL note to it.  If we can't because TEMP conflicts with an
                    463:             operand, call ourselves again, this time without a target.  */
                    464:          if (GET_CODE (pat) == SEQUENCE
                    465:              && ! add_equal_note (pat, temp, binoptab->code, xop0, xop1))
                    466:            {
                    467:              delete_insns_since (last);
                    468:              return expand_binop (mode, binoptab, op0, op1, NULL_RTX,
                    469:                                   unsignedp, methods);
                    470:            }
                    471: 
                    472:          emit_insn (pat);
                    473:          return temp;
                    474:        }
                    475:       else
                    476:        delete_insns_since (last);
                    477:     }
                    478: 
                    479:   /* If this is a multiply, see if we can do a widening operation that
                    480:      takes operands of this mode and makes a wider mode.  */
                    481: 
                    482:   if (binoptab == smul_optab && GET_MODE_WIDER_MODE (mode) != VOIDmode
                    483:       && (((unsignedp ? umul_widen_optab : smul_widen_optab)
                    484:           ->handlers[(int) GET_MODE_WIDER_MODE (mode)].insn_code)
                    485:          != CODE_FOR_nothing))
                    486:     {
                    487:       temp = expand_binop (GET_MODE_WIDER_MODE (mode),
                    488:                           unsignedp ? umul_widen_optab : smul_widen_optab,
                    489:                           op0, op1, 0, unsignedp, OPTAB_DIRECT);
                    490: 
                    491:       if (GET_MODE_CLASS (mode) == MODE_INT)
                    492:        return gen_lowpart (mode, temp);
                    493:       else
                    494:        return convert_to_mode (mode, temp, unsignedp);
                    495:     }
                    496: 
                    497:   /* Look for a wider mode of the same class for which we think we
                    498:      can open-code the operation.  Check for a widening multiply at the
                    499:      wider mode as well.  */
                    500: 
                    501:   if ((class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
                    502:       && methods != OPTAB_DIRECT && methods != OPTAB_LIB)
                    503:     for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
                    504:         wider_mode = GET_MODE_WIDER_MODE (wider_mode))
                    505:       {
                    506:        if (binoptab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing
                    507:            || (binoptab == smul_optab
                    508:                && GET_MODE_WIDER_MODE (wider_mode) != VOIDmode
                    509:                && (((unsignedp ? umul_widen_optab : smul_widen_optab)
                    510:                     ->handlers[(int) GET_MODE_WIDER_MODE (wider_mode)].insn_code)
                    511:                    != CODE_FOR_nothing)))
                    512:          {
                    513:            rtx xop0 = op0, xop1 = op1;
                    514:            int no_extend = 0;
                    515: 
                    516:            /* For certain integer operations, we need not actually extend
                    517:               the narrow operands, as long as we will truncate
                    518:               the results to the same narrowness.   */
                    519: 
                    520:            if ((binoptab == ior_optab || binoptab == and_optab
                    521:                 || binoptab == xor_optab
                    522:                 || binoptab == add_optab || binoptab == sub_optab
                    523:                 || binoptab == smul_optab
                    524:                 || binoptab == ashl_optab || binoptab == lshl_optab)
                    525:                && class == MODE_INT)
                    526:              no_extend = 1;
                    527: 
                    528:            xop0 = widen_operand (xop0, wider_mode, mode, unsignedp, no_extend);
                    529: 
                    530:            /* The second operand of a shift must always be extended.  */
                    531:            xop1 = widen_operand (xop1, wider_mode, mode, unsignedp,
                    532:                                  no_extend && binoptab != ashl_optab
                    533:                                  && binoptab != lshl_optab);
                    534: 
                    535:            temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX,
                    536:                                 unsignedp, OPTAB_DIRECT);
                    537:            if (temp)
                    538:              {
                    539:                if (class != MODE_INT)
                    540:                  {
                    541:                    if (target == 0)
                    542:                      target = gen_reg_rtx (mode);
                    543:                    convert_move (target, temp, 0);
                    544:                    return target;
                    545:                  }
                    546:                else
                    547:                  return gen_lowpart (mode, temp);
                    548:              }
                    549:            else
                    550:              delete_insns_since (last);
                    551:          }
                    552:       }
                    553: 
                    554:   /* These can be done a word at a time.  */
                    555:   if ((binoptab == and_optab || binoptab == ior_optab || binoptab == xor_optab)
                    556:       && class == MODE_INT
                    557:       && GET_MODE_SIZE (mode) > UNITS_PER_WORD
                    558:       && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
                    559:     {
                    560:       int i;
                    561:       rtx insns;
                    562:       rtx equiv_value;
                    563: 
                    564:       /* If TARGET is the same as one of the operands, the REG_EQUAL note
                    565:         won't be accurate, so use a new target.  */
                    566:       if (target == 0 || target == op0 || target == op1)
                    567:        target = gen_reg_rtx (mode);
                    568: 
                    569:       start_sequence ();
                    570: 
                    571:       /* Do the actual arithmetic.  */
                    572:       for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)
                    573:        {
                    574:          rtx target_piece = operand_subword (target, i, 1, mode);
                    575:          rtx x = expand_binop (word_mode, binoptab,
                    576:                                operand_subword_force (op0, i, mode),
                    577:                                operand_subword_force (op1, i, mode),
                    578:                                target_piece, unsignedp, methods);
                    579:          if (target_piece != x)
                    580:            emit_move_insn (target_piece, x);
                    581:        }
                    582: 
                    583:       insns = get_insns ();
                    584:       end_sequence ();
                    585: 
                    586:       if (binoptab->code != UNKNOWN)
                    587:        equiv_value
                    588:          = gen_rtx (binoptab->code, mode, copy_rtx (op0), copy_rtx (op1));
                    589:       else
                    590:        equiv_value = 0;
                    591: 
                    592:       emit_no_conflict_block (insns, target, op0, op1, equiv_value);
                    593:       return target;
                    594:     }
                    595: 
                    596:   /* Synthesize double word shifts from single word shifts.  */
                    597:   if ((binoptab == lshl_optab || binoptab == lshr_optab
                    598:        || binoptab == ashl_optab || binoptab == ashr_optab)
                    599:       && class == MODE_INT
                    600:       && GET_CODE (op1) == CONST_INT
                    601:       && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
                    602:       && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
                    603:       && ashl_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
                    604:       && lshr_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
                    605:     {
                    606:       rtx insns, equiv_value;
                    607:       rtx into_target, outof_target;
                    608:       rtx into_input, outof_input;
                    609:       int shift_count, left_shift, outof_word;
                    610: 
                    611:       /* If TARGET is the same as one of the operands, the REG_EQUAL note
                    612:         won't be accurate, so use a new target.  */
                    613:       if (target == 0 || target == op0 || target == op1)
                    614:        target = gen_reg_rtx (mode);
                    615: 
                    616:       start_sequence ();
                    617: 
                    618:       shift_count = INTVAL (op1);
                    619: 
                    620:       /* OUTOF_* is the word we are shifting bits away from, and
                    621:         INTO_* is the word that we are shifting bits towards, thus
                    622:         they differ depending on the direction of the shift and
                    623:         WORDS_BIG_ENDIAN.  */
                    624: 
                    625:       left_shift = (binoptab == ashl_optab || binoptab == lshl_optab);
                    626:       outof_word = left_shift ^ ! WORDS_BIG_ENDIAN;
                    627: 
                    628:       outof_target = operand_subword (target, outof_word, 1, mode);
                    629:       into_target = operand_subword (target, 1 - outof_word, 1, mode);
                    630: 
                    631:       outof_input = operand_subword_force (op0, outof_word, mode);
                    632:       into_input = operand_subword_force (op0, 1 - outof_word, mode);
                    633: 
                    634:       if (shift_count >= BITS_PER_WORD)
                    635:        {
                    636:          emit_move_insn (into_target,
                    637:                          expand_binop (word_mode, binoptab,
                    638:                                        outof_input,
                    639:                                        GEN_INT (shift_count - BITS_PER_WORD),
                    640:                                        into_target, unsignedp, methods));
                    641: 
                    642:          /* For a signed right shift, we must fill the word we are shifting
                    643:             out of with copies of the sign bit.  Otherwise it is zeroed.  */
                    644:          if (binoptab != ashr_optab)
                    645:            emit_move_insn (outof_target, CONST0_RTX (word_mode));
                    646:          else
                    647:            emit_move_insn (outof_target,
                    648:                            expand_binop (word_mode, binoptab,
                    649:                                          outof_input,
                    650:                                          GEN_INT (BITS_PER_WORD - 1),
                    651:                                          outof_target, unsignedp, methods));
                    652:        }
                    653:       else
                    654:        {
                    655:          rtx carries, into_temp;
                    656:          optab reverse_unsigned_shift, unsigned_shift;
                    657: 
                    658:          /* For a shift of less then BITS_PER_WORD, to compute the carry,
                    659:             we must do a logical shift in the opposite direction of the
                    660:             desired shift.  */
                    661: 
                    662:          /* We use ashl_optab instead of lshl_optab, because ashl is
                    663:             guaranteed to exist, but lshl may or may not exist.  */
                    664: 
                    665:          reverse_unsigned_shift = (left_shift ? lshr_optab : ashl_optab);
                    666: 
                    667:          /* For a shift of less than BITS_PER_WORD, to compute the word
                    668:             shifted towards, we need to unsigned shift the orig value of
                    669:             that word.  */
                    670: 
                    671:          unsigned_shift = (left_shift ? ashl_optab : lshr_optab);
                    672: 
                    673:          carries = expand_binop (word_mode, reverse_unsigned_shift,
                    674:                                  outof_input,
                    675:                                  GEN_INT (BITS_PER_WORD - shift_count),
                    676:                                  0, unsignedp, methods);
                    677: 
                    678:          emit_move_insn (outof_target,
                    679:                          expand_binop (word_mode, binoptab,
                    680:                                        outof_input,
                    681:                                        op1, outof_target, unsignedp, methods));
                    682:          into_temp = expand_binop (word_mode, unsigned_shift,
                    683:                                    into_input,
                    684:                                    op1, 0, unsignedp, methods);
                    685: 
                    686:          emit_move_insn (into_target,
                    687:                          expand_binop (word_mode, ior_optab,
                    688:                                        carries, into_temp,
                    689:                                        into_target, unsignedp, methods));
                    690:        }
                    691: 
                    692:       insns = get_insns ();
                    693:       end_sequence ();
                    694: 
                    695:       if (binoptab->code != UNKNOWN)
                    696:        equiv_value = gen_rtx (binoptab->code, mode, op0, op1);
                    697:       else
                    698:        equiv_value = 0;
                    699: 
                    700:       if (shift_count > BITS_PER_WORD)
                    701:        emit_no_conflict_block (insns, target, op0, op1, equiv_value); 
                    702:       else
                    703:        emit_insns (insns); 
                    704: 
                    705:       return target;
                    706:     }
                    707: 
                    708:   /* Synthesize double word rotates from single word shifts.  */
                    709:   if ((binoptab == rotl_optab || binoptab == rotr_optab)
                    710:       && class == MODE_INT
                    711:       && GET_CODE (op1) == CONST_INT
                    712:       && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
                    713:       && ashl_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
                    714:       && lshr_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
                    715:     {
                    716:       rtx insns, equiv_value;
                    717:       rtx into_target, outof_target;
                    718:       rtx into_input, outof_input;
                    719:       int shift_count, left_shift, outof_word;
                    720: 
                    721:       /* If TARGET is the same as one of the operands, the REG_EQUAL note
                    722:         won't be accurate, so use a new target.  */
                    723:       if (target == 0 || target == op0 || target == op1)
                    724:        target = gen_reg_rtx (mode);
                    725: 
                    726:       start_sequence ();
                    727: 
                    728:       shift_count = INTVAL (op1);
                    729: 
                    730:       /* OUTOF_* is the word we are shifting bits away from, and
                    731:         INTO_* is the word that we are shifting bits towards, thus
                    732:         they differ depending on the direction of the shift and
                    733:         WORDS_BIG_ENDIAN.  */
                    734: 
                    735:       left_shift = (binoptab == rotl_optab);
                    736:       outof_word = left_shift ^ ! WORDS_BIG_ENDIAN;
                    737: 
                    738:       outof_target = operand_subword (target, outof_word, 1, mode);
                    739:       into_target = operand_subword (target, 1 - outof_word, 1, mode);
                    740: 
                    741:       outof_input = operand_subword_force (op0, outof_word, mode);
                    742:       into_input = operand_subword_force (op0, 1 - outof_word, mode);
                    743: 
                    744:       if (shift_count == BITS_PER_WORD)
                    745:        {
                    746:          /* This is just a word swap.  */
                    747:          emit_move_insn (outof_target, into_input);
                    748:          emit_move_insn (into_target, outof_input);
                    749:        }
                    750:       else
                    751:        {
                    752:          rtx into_temp1, into_temp2, outof_temp1, outof_temp2;
                    753:          rtx first_shift_count, second_shift_count;
                    754:          optab reverse_unsigned_shift, unsigned_shift;
                    755: 
                    756:          reverse_unsigned_shift = (left_shift ^ (shift_count < BITS_PER_WORD)
                    757:                                    ? lshr_optab : ashl_optab);
                    758: 
                    759:          unsigned_shift = (left_shift ^ (shift_count < BITS_PER_WORD)
                    760:                            ? ashl_optab : lshr_optab);
                    761: 
                    762:          if (shift_count > BITS_PER_WORD)
                    763:            {
                    764:              first_shift_count = GEN_INT (shift_count - BITS_PER_WORD);
                    765:              second_shift_count = GEN_INT (2*BITS_PER_WORD - shift_count);
                    766:            }
                    767:          else
                    768:            {
                    769:              first_shift_count = GEN_INT (BITS_PER_WORD - shift_count);
                    770:              second_shift_count = GEN_INT (shift_count);
                    771:            }
                    772: 
                    773:          into_temp1 = expand_binop (word_mode, unsigned_shift,
                    774:                                     outof_input, first_shift_count,
                    775:                                     0, unsignedp, methods);
                    776:          into_temp2 = expand_binop (word_mode, reverse_unsigned_shift,
                    777:                                     into_input, second_shift_count,
                    778:                                     into_target, unsignedp, methods);
                    779:          emit_move_insn (into_target,
                    780:                          expand_binop (word_mode, ior_optab,
                    781:                                        into_temp1, into_temp2,
                    782:                                        into_target, unsignedp, methods));
                    783: 
                    784:          outof_temp1 = expand_binop (word_mode, unsigned_shift,
                    785:                                      into_input, first_shift_count,
                    786:                                      0, unsignedp, methods);
                    787:          outof_temp2 = expand_binop (word_mode, reverse_unsigned_shift,
                    788:                                      outof_input, second_shift_count,
                    789:                                      outof_target, unsignedp, methods);
                    790:          emit_move_insn (outof_target,
                    791:                          expand_binop (word_mode, ior_optab,
                    792:                                        outof_temp1, outof_temp2,
                    793:                                        outof_target, unsignedp, methods));
                    794:        }
                    795: 
                    796:       insns = get_insns ();
                    797:       end_sequence ();
                    798: 
                    799:       if (binoptab->code != UNKNOWN)
                    800:        equiv_value = gen_rtx (binoptab->code, mode, op0, op1);
                    801:       else
                    802:        equiv_value = 0;
                    803: 
                    804:       /* We can't make this a no conflict block if this is a word swap,
                    805:         because the word swap case fails if the input and output values
                    806:         are in the same register.  */
                    807:       if (shift_count != BITS_PER_WORD)
                    808:        emit_no_conflict_block (insns, target, op0, op1, equiv_value);
                    809:       else
                    810:        emit_insns (insns);
                    811:       return target;
                    812:     }
                    813: 
                    814:   /* These can be done a word at a time by propagating carries.  */
                    815:   if ((binoptab == add_optab || binoptab == sub_optab)
                    816:       && class == MODE_INT
                    817:       && GET_MODE_SIZE (mode) >= 2 * UNITS_PER_WORD
                    818:       && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
                    819:     {
                    820:       int i;
                    821:       rtx carry_tmp = gen_reg_rtx (word_mode);
                    822:       optab otheroptab = binoptab == add_optab ? sub_optab : add_optab;
                    823:       int nwords = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
                    824:       rtx carry_in, carry_out;
                    825:       rtx xop0, xop1;
                    826: 
                    827:       /* We can handle either a 1 or -1 value for the carry.  If STORE_FLAG
                    828:         value is one of those, use it.  Otherwise, use 1 since it is the
                    829:         one easiest to get.  */
                    830: #if STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1
                    831:       int normalizep = STORE_FLAG_VALUE;
                    832: #else
                    833:       int normalizep = 1;
                    834: #endif
                    835: 
                    836:       /* Prepare the operands.  */
                    837:       xop0 = force_reg (mode, op0);
                    838:       xop1 = force_reg (mode, op1);
                    839: 
                    840:       if (target == 0 || GET_CODE (target) != REG
                    841:          || target == xop0 || target == xop1)
                    842:        target = gen_reg_rtx (mode);
                    843: 
                    844:       /* Indicate for flow that the entire target reg is being set.  */
                    845:       if (GET_CODE (target) == REG)
                    846:        emit_insn (gen_rtx (CLOBBER, VOIDmode, target));
                    847: 
                    848:       /* Do the actual arithmetic.  */
                    849:       for (i = 0; i < nwords; i++)
                    850:        {
                    851:          int index = (WORDS_BIG_ENDIAN ? nwords - i - 1 : i);
                    852:          rtx target_piece = operand_subword (target, index, 1, mode);
                    853:          rtx op0_piece = operand_subword_force (xop0, index, mode);
                    854:          rtx op1_piece = operand_subword_force (xop1, index, mode);
                    855:          rtx x;
                    856: 
                    857:          /* Main add/subtract of the input operands.  */
                    858:          x = expand_binop (word_mode, binoptab,
                    859:                            op0_piece, op1_piece,
                    860:                            target_piece, unsignedp, methods);
                    861:          if (x == 0)
                    862:            break;
                    863: 
                    864:          if (i + 1 < nwords)
                    865:            {
                    866:              /* Store carry from main add/subtract.  */
                    867:              carry_out = gen_reg_rtx (word_mode);
                    868:              carry_out = emit_store_flag (carry_out,
                    869:                                           binoptab == add_optab ? LTU : GTU,
                    870:                                           x, op0_piece,
                    871:                                           word_mode, 1, normalizep);
                    872:              if (!carry_out)
                    873:                break;
                    874:            }
                    875: 
                    876:          if (i > 0)
                    877:            {
                    878:              /* Add/subtract previous carry to main result.  */
                    879:              x = expand_binop (word_mode,
                    880:                                normalizep == 1 ? binoptab : otheroptab,
                    881:                                x, carry_in,
                    882:                                target_piece, 1, methods);
                    883:              if (target_piece != x)
                    884:                emit_move_insn (target_piece, x);
                    885: 
                    886:              if (i + 1 < nwords)
                    887:                {
                    888:                  /* THIS CODE HAS NOT BEEN TESTED.  */
                    889:                  /* Get out carry from adding/subtracting carry in.  */
                    890:                  carry_tmp = emit_store_flag (carry_tmp,
                    891:                                               binoptab == add_optab
                    892:                                                 ? LTU : GTU,
                    893:                                               x, carry_in,
                    894:                                               word_mode, 1, normalizep);
                    895:                  /* Logical-ior the two poss. carry together.  */
                    896:                  carry_out = expand_binop (word_mode, ior_optab,
                    897:                                            carry_out, carry_tmp,
                    898:                                            carry_out, 0, methods);
                    899:                  if (!carry_out)
                    900:                    break;
                    901:                }
                    902:            }
                    903: 
                    904:          carry_in = carry_out;
                    905:        }       
                    906: 
                    907:       if (i == GET_MODE_BITSIZE (mode) / BITS_PER_WORD)
                    908:        {
                    909:          rtx temp;
                    910:          
                    911:          temp = emit_move_insn (target, target);
                    912:          REG_NOTES (temp) = gen_rtx (EXPR_LIST, REG_EQUAL,
                    913:                                      gen_rtx (binoptab->code, mode,
                    914:                                               copy_rtx (xop0),
                    915:                                               copy_rtx (xop1)),
                    916:                                      REG_NOTES (temp));
                    917:          return target;
                    918:        }
                    919:       else
                    920:        delete_insns_since (last);
                    921:     }
                    922: 
                    923:   /* If we want to multiply two two-word values and have normal and widening
                    924:      multiplies of single-word values, we can do this with three smaller
                    925:      multiplications.  Note that we do not make a REG_NO_CONFLICT block here
                    926:      because we are not operating on one word at a time. 
                    927: 
                    928:      The multiplication proceeds as follows:
                    929:                                 _______________________
                    930:                                [__op0_high_|__op0_low__]
                    931:                                 _______________________
                    932:         *                      [__op1_high_|__op1_low__]
                    933:         _______________________________________________
                    934:                                 _______________________
                    935:     (1)                                [__op0_low__*__op1_low__]
                    936:                     _______________________
                    937:     (2a)           [__op0_low__*__op1_high_]
                    938:                     _______________________
                    939:     (2b)           [__op0_high_*__op1_low__]
                    940:          _______________________
                    941:     (3) [__op0_high_*__op1_high_]
                    942: 
                    943: 
                    944:     This gives a 4-word result.  Since we are only interested in the
                    945:     lower 2 words, partial result (3) and the upper words of (2a) and
                    946:     (2b) don't need to be calculated.  Hence (2a) and (2b) can be
                    947:     calculated using non-widening multiplication.
                    948: 
                    949:     (1), however, needs to be calculated with an unsigned widening
                    950:     multiplication.  If this operation is not directly supported we
                    951:     try using a signed widening multiplication and adjust the result.
                    952:     This adjustment works as follows:
                    953: 
                    954:       If both operands are positive then no adjustment is needed.
                    955: 
                    956:       If the operands have different signs, for example op0_low < 0 and
                    957:       op1_low >= 0, the instruction treats the most significant bit of
                    958:       op0_low as a sign bit instead of a bit with significance
                    959:       2**(BITS_PER_WORD-1), i.e. the instruction multiplies op1_low
                    960:       with 2**BITS_PER_WORD - op0_low, and two's complements the
                    961:       result.  Conclusion: We need to add op1_low * 2**BITS_PER_WORD to
                    962:       the result.
                    963: 
                    964:       Similarly, if both operands are negative, we need to add
                    965:       (op0_low + op1_low) * 2**BITS_PER_WORD.
                    966: 
                    967:       We use a trick to adjust quickly.  We logically shift op0_low right
                    968:       (op1_low) BITS_PER_WORD-1 steps to get 0 or 1, and add this to
                    969:       op0_high (op1_high) before it is used to calculate 2b (2a).  If no
                    970:       logical shift exists, we do an arithmetic right shift and subtract
                    971:       the 0 or -1.  */
                    972: 
                    973:   if (binoptab == smul_optab
                    974:       && class == MODE_INT
                    975:       && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
                    976:       && smul_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
                    977:       && add_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
                    978:       && ((umul_widen_optab->handlers[(int) mode].insn_code
                    979:           != CODE_FOR_nothing)
                    980:          || (smul_widen_optab->handlers[(int) mode].insn_code
                    981:              != CODE_FOR_nothing)))
                    982:     {
                    983:       int low = (WORDS_BIG_ENDIAN ? 1 : 0);
                    984:       int high = (WORDS_BIG_ENDIAN ? 0 : 1);
                    985:       rtx op0_high = operand_subword_force (op0, high, mode);
                    986:       rtx op0_low = operand_subword_force (op0, low, mode);
                    987:       rtx op1_high = operand_subword_force (op1, high, mode);
                    988:       rtx op1_low = operand_subword_force (op1, low, mode);
                    989:       rtx product = 0;
                    990:       rtx op0_xhigh;
                    991:       rtx op1_xhigh;
                    992: 
                    993:       /* If the target is the same as one of the inputs, don't use it.  This
                    994:         prevents problems with the REG_EQUAL note.  */
                    995:       if (target == op0 || target == op1)
                    996:        target = 0;
                    997: 
                    998:       /* Multiply the two lower words to get a double-word product.
                    999:         If unsigned widening multiplication is available, use that;
                   1000:         otherwise use the signed form and compensate.  */
                   1001: 
                   1002:       if (umul_widen_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
                   1003:        {
                   1004:          product = expand_binop (mode, umul_widen_optab, op0_low, op1_low,
                   1005:                                  target, 1, OPTAB_DIRECT);
                   1006: 
                   1007:          /* If we didn't succeed, delete everything we did so far.  */
                   1008:          if (product == 0)
                   1009:            delete_insns_since (last);
                   1010:          else
                   1011:            op0_xhigh = op0_high, op1_xhigh = op1_high;
                   1012:        }
                   1013: 
                   1014:       if (product == 0
                   1015:          && smul_widen_optab->handlers[(int) mode].insn_code
                   1016:               != CODE_FOR_nothing)
                   1017:        {
                   1018:          rtx wordm1 = GEN_INT (BITS_PER_WORD - 1);
                   1019:          product = expand_binop (mode, smul_widen_optab, op0_low, op1_low,
                   1020:                                  target, 1, OPTAB_DIRECT);
                   1021:          op0_xhigh = expand_binop (word_mode, lshr_optab, op0_low, wordm1,
                   1022:                                    NULL_RTX, 1, OPTAB_DIRECT);
                   1023:          if (op0_xhigh)
                   1024:            op0_xhigh = expand_binop (word_mode, add_optab, op0_high,
                   1025:                                      op0_xhigh, op0_xhigh, 0, OPTAB_DIRECT);
                   1026:          else
                   1027:            {
                   1028:              op0_xhigh = expand_binop (word_mode, ashr_optab, op0_low, wordm1,
                   1029:                                        NULL_RTX, 0, OPTAB_DIRECT);
                   1030:              if (op0_xhigh)
                   1031:                op0_xhigh = expand_binop (word_mode, sub_optab, op0_high,
                   1032:                                          op0_xhigh, op0_xhigh, 0,
                   1033:                                          OPTAB_DIRECT);
                   1034:            }
                   1035: 
                   1036:          op1_xhigh = expand_binop (word_mode, lshr_optab, op1_low, wordm1,
                   1037:                                    NULL_RTX, 1, OPTAB_DIRECT);
                   1038:          if (op1_xhigh)
                   1039:            op1_xhigh = expand_binop (word_mode, add_optab, op1_high,
                   1040:                                      op1_xhigh, op1_xhigh, 0, OPTAB_DIRECT);
                   1041:          else
                   1042:            {
                   1043:              op1_xhigh = expand_binop (word_mode, ashr_optab, op1_low, wordm1,
                   1044:                                        NULL_RTX, 0, OPTAB_DIRECT);
                   1045:              if (op1_xhigh)
                   1046:                op1_xhigh = expand_binop (word_mode, sub_optab, op1_high,
                   1047:                                          op1_xhigh, op1_xhigh, 0,
                   1048:                                          OPTAB_DIRECT);
                   1049:            }
                   1050:        }
                   1051: 
                   1052:       /* If we have been able to directly compute the product of the
                   1053:         low-order words of the operands and perform any required adjustments
                   1054:         of the operands, we proceed by trying two more multiplications
                   1055:         and then computing the appropriate sum.
                   1056: 
                   1057:         We have checked above that the required addition is provided.
                   1058:         Full-word addition will normally always succeed, especially if
                   1059:         it is provided at all, so we don't worry about its failure.  The
                   1060:         multiplication may well fail, however, so we do handle that.  */
                   1061: 
                   1062:       if (product && op0_xhigh && op1_xhigh)
                   1063:        {
                   1064:          rtx product_piece;
                   1065:          rtx product_high = operand_subword (product, high, 1, mode);
                   1066:          rtx temp = expand_binop (word_mode, binoptab, op0_low, op1_xhigh,
                   1067:                                   NULL_RTX, 0, OPTAB_DIRECT);
                   1068: 
                   1069:          if (temp)
                   1070:            {
                   1071:              product_piece = expand_binop (word_mode, add_optab, temp,
                   1072:                                            product_high, product_high,
                   1073:                                            0, OPTAB_LIB_WIDEN);
                   1074:              if (product_piece != product_high)
                   1075:                emit_move_insn (product_high, product_piece);
                   1076: 
                   1077:              temp = expand_binop (word_mode, binoptab, op1_low, op0_xhigh, 
                   1078:                                   NULL_RTX, 0, OPTAB_DIRECT);
                   1079: 
                   1080:              product_piece = expand_binop (word_mode, add_optab, temp,
                   1081:                                            product_high, product_high,
                   1082:                                            0, OPTAB_LIB_WIDEN);
                   1083:              if (product_piece != product_high)
                   1084:                emit_move_insn (product_high, product_piece);
                   1085: 
                   1086:              temp = emit_move_insn (product, product);
                   1087:              REG_NOTES (temp) = gen_rtx (EXPR_LIST, REG_EQUAL,
                   1088:                                          gen_rtx (MULT, mode, copy_rtx (op0),
                   1089:                                                   copy_rtx (op1)),
                   1090:                                          REG_NOTES (temp));
                   1091: 
                   1092:              return product;
                   1093:            }
                   1094:        }
                   1095: 
                   1096:       /* If we get here, we couldn't do it for some reason even though we
                   1097:         originally thought we could.  Delete anything we've emitted in
                   1098:         trying to do it.  */
                   1099: 
                   1100:       delete_insns_since (last);
                   1101:     }
                   1102: 
                   1103:   /* We need to open-code the complex type operations: '+, -, * and /' */
                   1104: 
                   1105:   /* At this point we allow operations between two similar complex
                   1106:      numbers, and also if one of the operands is not a complex number
                   1107:      but rather of MODE_FLOAT or MODE_INT. However, the caller
                   1108:      must make sure that the MODE of the non-complex operand matches
                   1109:      the SUBMODE of the complex operand.  */
                   1110: 
                   1111:   if (class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT)
                   1112:     {
                   1113:       rtx real0 = (rtx) 0;
                   1114:       rtx imag0 = (rtx) 0;
                   1115:       rtx real1 = (rtx) 0;
                   1116:       rtx imag1 = (rtx) 0;
                   1117:       rtx realr;
                   1118:       rtx imagr;
                   1119:       rtx res;
                   1120:       rtx seq;
                   1121:       rtx equiv_value;
                   1122: 
                   1123:       /* Find the correct mode for the real and imaginary parts */
                   1124:       enum machine_mode submode
                   1125:        = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT,
                   1126:                         class == MODE_COMPLEX_INT ? MODE_INT : MODE_FLOAT,
                   1127:                         0);
                   1128: 
                   1129:       if (submode == BLKmode)
                   1130:        abort ();
                   1131: 
                   1132:       if (! target)
                   1133:        target = gen_reg_rtx (mode);
                   1134: 
                   1135:       start_sequence ();
                   1136: 
                   1137:       realr = gen_realpart  (submode, target);
                   1138:       imagr = gen_imagpart (submode, target);
                   1139: 
                   1140:       if (GET_MODE (op0) == mode)
                   1141:        {
                   1142:          real0 = gen_realpart  (submode, op0);
                   1143:          imag0 = gen_imagpart (submode, op0);
                   1144:        }
                   1145:       else
                   1146:        real0 = op0;
                   1147: 
                   1148:       if (GET_MODE (op1) == mode)
                   1149:        {
                   1150:          real1 = gen_realpart  (submode, op1);
                   1151:          imag1 = gen_imagpart (submode, op1);
                   1152:        }
                   1153:       else
                   1154:        real1 = op1;
                   1155: 
                   1156:       if (! real0 || ! real1 || ! (imag0 || imag1))
                   1157:        abort ();
                   1158: 
                   1159:       switch (binoptab->code)
                   1160:        {
                   1161:        case PLUS:
                   1162:          /* (a+ib) + (c+id) = (a+c) + i(b+d) */
                   1163:        case MINUS:
                   1164:          /* (a+ib) - (c+id) = (a-c) + i(b-d) */
                   1165:          res = expand_binop (submode, binoptab, real0, real1,
                   1166:                              realr, unsignedp, methods);
                   1167:          if (res != realr)
                   1168:            emit_move_insn (realr, res);
                   1169: 
                   1170:          if (imag0 && imag1)
                   1171:            res = expand_binop (submode, binoptab, imag0, imag1,
                   1172:                                imagr, unsignedp, methods);
                   1173:          else if (imag0)
                   1174:            res = imag0;
                   1175:          else if (binoptab->code == MINUS)
                   1176:            res = expand_unop (submode, neg_optab, imag1, imagr, unsignedp);
                   1177:          else
                   1178:            res = imag1;
                   1179: 
                   1180:          if (res != imagr)
                   1181:            emit_move_insn (imagr, res);
                   1182:          break;
                   1183: 
                   1184:        case MULT:
                   1185:          /* (a+ib) * (c+id) = (ac-bd) + i(ad+cb) */
                   1186: 
                   1187:          if (imag0 && imag1)
                   1188:            {
                   1189:              /* Don't fetch these from memory more than once.  */
                   1190:              real0 = force_reg (submode, real0);
                   1191:              real1 = force_reg (submode, real1);
                   1192:              imag0 = force_reg (submode, imag0);
                   1193:              imag1 = force_reg (submode, imag1);
                   1194: 
                   1195:              res = expand_binop (submode, sub_optab,
                   1196:                                  expand_binop (submode, binoptab, real0,
                   1197:                                                real1, 0, unsignedp, methods),
                   1198:                                  expand_binop (submode, binoptab, imag0,
                   1199:                                                imag1, 0, unsignedp, methods),
                   1200:                                  realr, unsignedp, methods);
                   1201: 
                   1202:              if (res != realr)
                   1203:                emit_move_insn (realr, res);
                   1204: 
                   1205:              res = expand_binop (submode, add_optab,
                   1206:                                  expand_binop (submode, binoptab,
                   1207:                                                real0, imag1,
                   1208:                                                0, unsignedp, methods),
                   1209:                                  expand_binop (submode, binoptab,
                   1210:                                                real1, imag0,
                   1211:                                                0, unsignedp, methods),
                   1212:                                  imagr, unsignedp, methods);
                   1213:              if (res != imagr)
                   1214:                emit_move_insn (imagr, res);
                   1215:            }
                   1216:          else
                   1217:            {
                   1218:              /* Don't fetch these from memory more than once.  */
                   1219:              real0 = force_reg (submode, real0);
                   1220:              real1 = force_reg (submode, real1);
                   1221: 
                   1222:              res = expand_binop (submode, binoptab, real0, real1,
                   1223:                                  realr, unsignedp, methods);
                   1224:              if (res != realr)
                   1225:                emit_move_insn (realr, res);
                   1226: 
                   1227:              if (imag0)
                   1228:                res = expand_binop (submode, binoptab,
                   1229:                                    real1, imag0, imagr, unsignedp, methods);
                   1230:              else
                   1231:                res = expand_binop (submode, binoptab,
                   1232:                                    real0, imag1, imagr, unsignedp, methods);
                   1233:              if (res != imagr)
                   1234:                emit_move_insn (imagr, res);
                   1235:            }
                   1236:          break;
                   1237: 
                   1238:        case DIV:
                   1239:          /* (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd)) */
                   1240:          
                   1241:          if (! imag1)
                   1242:            {   /* (a+ib) / (c+i0) = (a/c) + i(b/c) */
                   1243: 
                   1244:              /* Don't fetch these from memory more than once.  */
                   1245:              real1 = force_reg (submode, real1);
                   1246: 
                   1247:              /* Simply divide the real and imaginary parts by `c' */
                   1248:              res = expand_binop (submode, binoptab, real0, real1,
                   1249:                                  realr, unsignedp, methods);
                   1250:              if (res != realr)
                   1251:                emit_move_insn (realr, res);
                   1252: 
                   1253:              res = expand_binop (submode, binoptab, imag0, real1,
                   1254:                                  imagr, unsignedp, methods);
                   1255:              if (res != imagr)
                   1256:                emit_move_insn (imagr, res);
                   1257:            }
                   1258:          else                  /* Divisor is of complex type */
                   1259:            {                   /* X/(a+ib) */
                   1260: 
                   1261:              rtx divisor;
                   1262:              rtx real_t;
                   1263:              rtx imag_t;
                   1264:              
                   1265:              optab mulopt = unsignedp ? umul_widen_optab : smul_optab;
                   1266: 
                   1267:              /* Don't fetch these from memory more than once.  */
                   1268:              real0 = force_reg (submode, real0);
                   1269:              real1 = force_reg (submode, real1);
                   1270:              if (imag0)
                   1271:                imag0 = force_reg (submode, imag0);
                   1272:              imag1 = force_reg (submode, imag1);
                   1273: 
                   1274:              /* Divisor: c*c + d*d */
                   1275:              divisor = expand_binop (submode, add_optab,
                   1276:                                      expand_binop (submode, mulopt,
                   1277:                                                    real1, real1,
                   1278:                                                    0, unsignedp, methods),
                   1279:                                      expand_binop (submode, mulopt,
                   1280:                                                    imag1, imag1,
                   1281:                                                    0, unsignedp, methods),
                   1282:                                      0, unsignedp, methods);
                   1283: 
                   1284:              if (! imag0)      /* ((a)(c-id))/divisor */
                   1285:                {       /* (a+i0) / (c+id) = (ac/(cc+dd)) + i(-ad/(cc+dd)) */
                   1286:                  /* Calculate the dividend */
                   1287:                  real_t = expand_binop (submode, mulopt, real0, real1,
                   1288:                                         0, unsignedp, methods);
                   1289:                  
                   1290:                  imag_t
                   1291:                    = expand_unop (submode, neg_optab,
                   1292:                                   expand_binop (submode, mulopt, real0, imag1,
                   1293:                                                 0, unsignedp, methods),
                   1294:                                   0, unsignedp);
                   1295:                }
                   1296:              else              /* ((a+ib)(c-id))/divider */
                   1297:                {
                   1298:                  /* Calculate the dividend */
                   1299:                  real_t = expand_binop (submode, add_optab,
                   1300:                                         expand_binop (submode, mulopt,
                   1301:                                                       real0, real1,
                   1302:                                                       0, unsignedp, methods),
                   1303:                                         expand_binop (submode, mulopt,
                   1304:                                                       imag0, imag1,
                   1305:                                                       0, unsignedp, methods),
                   1306:                                         0, unsignedp, methods);
                   1307:                  
                   1308:                  imag_t = expand_binop (submode, sub_optab,
                   1309:                                         expand_binop (submode, mulopt,
                   1310:                                                       imag0, real1,
                   1311:                                                       0, unsignedp, methods),
                   1312:                                         expand_binop (submode, mulopt,
                   1313:                                                       real0, imag1,
                   1314:                                                       0, unsignedp, methods),
                   1315:                                         0, unsignedp, methods);
                   1316: 
                   1317:                }
                   1318: 
                   1319:              res = expand_binop (submode, binoptab, real_t, divisor,
                   1320:                                  realr, unsignedp, methods);
                   1321:              if (res != realr)
                   1322:                emit_move_insn (realr, res);
                   1323: 
                   1324:              res = expand_binop (submode, binoptab, imag_t, divisor,
                   1325:                                  imagr, unsignedp, methods);
                   1326:              if (res != imagr)
                   1327:                emit_move_insn (imagr, res);
                   1328:            }
                   1329:          break;
                   1330:          
                   1331:        default:
                   1332:          abort ();
                   1333:        }
                   1334: 
                   1335:       seq = get_insns ();
                   1336:       end_sequence ();
                   1337: 
                   1338:       if (binoptab->code != UNKNOWN)
                   1339:        equiv_value
                   1340:          = gen_rtx (binoptab->code, mode, copy_rtx (op0), copy_rtx (op1));
                   1341:       else
                   1342:        equiv_value = 0;
                   1343:        
                   1344:       emit_no_conflict_block (seq, target, op0, op1, equiv_value);
                   1345:       
                   1346:       return target;
                   1347:     }
                   1348: 
                   1349:   /* It can't be open-coded in this mode.
                   1350:      Use a library call if one is available and caller says that's ok.  */
                   1351: 
                   1352:   if (binoptab->handlers[(int) mode].libfunc
                   1353:       && (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN))
                   1354:     {
                   1355:       rtx insns;
                   1356:       rtx funexp = binoptab->handlers[(int) mode].libfunc;
                   1357:       rtx op1x = op1;
                   1358:       enum machine_mode op1_mode = mode;
                   1359:       rtx value;
                   1360: 
                   1361:       start_sequence ();
                   1362: 
                   1363:       if (shift_op)
                   1364:        {
                   1365:          op1_mode = word_mode;
                   1366:          /* Specify unsigned here,
                   1367:             since negative shift counts are meaningless.  */
                   1368:          op1x = convert_to_mode (word_mode, op1, 1);
                   1369:        }
                   1370: 
                   1371:       /* Pass 1 for NO_QUEUE so we don't lose any increments
                   1372:         if the libcall is cse'd or moved.  */
                   1373:       value = emit_library_call_value (binoptab->handlers[(int) mode].libfunc,
                   1374:                                       NULL_RTX, 1, mode, 2,
                   1375:                                       op0, mode, op1x, op1_mode);
                   1376: 
                   1377:       insns = get_insns ();
                   1378:       end_sequence ();
                   1379: 
                   1380:       target = gen_reg_rtx (mode);
                   1381:       emit_libcall_block (insns, target, value,
                   1382:                          gen_rtx (binoptab->code, mode, op0, op1));
                   1383: 
                   1384:       return target;
                   1385:     }
                   1386: 
                   1387:   delete_insns_since (last);
                   1388: 
                   1389:   /* It can't be done in this mode.  Can we do it in a wider mode?  */
                   1390: 
                   1391:   if (! (methods == OPTAB_WIDEN || methods == OPTAB_LIB_WIDEN
                   1392:         || methods == OPTAB_MUST_WIDEN))
                   1393:     {
                   1394:       /* Caller says, don't even try.  */
                   1395:       delete_insns_since (entry_last);
                   1396:       return 0;
                   1397:     }
                   1398: 
                   1399:   /* Compute the value of METHODS to pass to recursive calls.
                   1400:      Don't allow widening to be tried recursively.  */
                   1401: 
                   1402:   methods = (methods == OPTAB_LIB_WIDEN ? OPTAB_LIB : OPTAB_DIRECT);
                   1403: 
                   1404:   /* Look for a wider mode of the same class for which it appears we can do
                   1405:      the operation.  */
                   1406: 
                   1407:   if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
                   1408:     {
                   1409:       for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
                   1410:           wider_mode = GET_MODE_WIDER_MODE (wider_mode))
                   1411:        {
                   1412:          if ((binoptab->handlers[(int) wider_mode].insn_code
                   1413:               != CODE_FOR_nothing)
                   1414:              || (methods == OPTAB_LIB
                   1415:                  && binoptab->handlers[(int) wider_mode].libfunc))
                   1416:            {
                   1417:              rtx xop0 = op0, xop1 = op1;
                   1418:              int no_extend = 0;
                   1419: 
                   1420:              /* For certain integer operations, we need not actually extend
                   1421:                 the narrow operands, as long as we will truncate
                   1422:                 the results to the same narrowness.  */
                   1423: 
                   1424:              if ((binoptab == ior_optab || binoptab == and_optab
                   1425:                   || binoptab == xor_optab
                   1426:                   || binoptab == add_optab || binoptab == sub_optab
                   1427:                   || binoptab == smul_optab
                   1428:                   || binoptab == ashl_optab || binoptab == lshl_optab)
                   1429:                  && class == MODE_INT)
                   1430:                no_extend = 1;
                   1431: 
                   1432:              xop0 = widen_operand (xop0, wider_mode, mode,
                   1433:                                    unsignedp, no_extend);
                   1434: 
                   1435:              /* The second operand of a shift must always be extended.  */
                   1436:              xop1 = widen_operand (xop1, wider_mode, mode, unsignedp,
                   1437:                                    no_extend && binoptab != ashl_optab
                   1438:                                    && binoptab != lshl_optab);
                   1439: 
                   1440:              temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX,
                   1441:                                   unsignedp, methods);
                   1442:              if (temp)
                   1443:                {
                   1444:                  if (class != MODE_INT)
                   1445:                    {
                   1446:                      if (target == 0)
                   1447:                        target = gen_reg_rtx (mode);
                   1448:                      convert_move (target, temp, 0);
                   1449:                      return target;
                   1450:                    }
                   1451:                  else
                   1452:                    return gen_lowpart (mode, temp);
                   1453:                }
                   1454:              else
                   1455:                delete_insns_since (last);
                   1456:            }
                   1457:        }
                   1458:     }
                   1459: 
                   1460:   delete_insns_since (entry_last);
                   1461:   return 0;
                   1462: }
                   1463: 
                   1464: /* Expand a binary operator which has both signed and unsigned forms.
                   1465:    UOPTAB is the optab for unsigned operations, and SOPTAB is for
                   1466:    signed operations.
                   1467: 
                   1468:    If we widen unsigned operands, we may use a signed wider operation instead
                   1469:    of an unsigned wider operation, since the result would be the same.  */
                   1470: 
                   1471: rtx
                   1472: sign_expand_binop (mode, uoptab, soptab, op0, op1, target, unsignedp, methods)
                   1473:     enum machine_mode mode;
                   1474:     optab uoptab, soptab;
                   1475:     rtx op0, op1, target;
                   1476:     int unsignedp;
                   1477:     enum optab_methods methods;
                   1478: {
                   1479:   register rtx temp;
                   1480:   optab direct_optab = unsignedp ? uoptab : soptab;
                   1481:   struct optab wide_soptab;
                   1482: 
                   1483:   /* Do it without widening, if possible.  */
                   1484:   temp = expand_binop (mode, direct_optab, op0, op1, target,
                   1485:                       unsignedp, OPTAB_DIRECT);
                   1486:   if (temp || methods == OPTAB_DIRECT)
                   1487:     return temp;
                   1488: 
                   1489:   /* Try widening to a signed int.  Make a fake signed optab that
                   1490:      hides any signed insn for direct use.  */
                   1491:   wide_soptab = *soptab;
                   1492:   wide_soptab.handlers[(int) mode].insn_code = CODE_FOR_nothing;
                   1493:   wide_soptab.handlers[(int) mode].libfunc = 0;
                   1494: 
                   1495:   temp = expand_binop (mode, &wide_soptab, op0, op1, target,
                   1496:                       unsignedp, OPTAB_WIDEN);
                   1497: 
                   1498:   /* For unsigned operands, try widening to an unsigned int.  */
                   1499:   if (temp == 0 && unsignedp)
                   1500:     temp = expand_binop (mode, uoptab, op0, op1, target,
                   1501:                         unsignedp, OPTAB_WIDEN);
                   1502:   if (temp || methods == OPTAB_WIDEN)
                   1503:     return temp;
                   1504: 
                   1505:   /* Use the right width lib call if that exists.  */
                   1506:   temp = expand_binop (mode, direct_optab, op0, op1, target, unsignedp, OPTAB_LIB);
                   1507:   if (temp || methods == OPTAB_LIB)
                   1508:     return temp;
                   1509: 
                   1510:   /* Must widen and use a lib call, use either signed or unsigned.  */
                   1511:   temp = expand_binop (mode, &wide_soptab, op0, op1, target,
                   1512:                       unsignedp, methods);
                   1513:   if (temp != 0)
                   1514:     return temp;
                   1515:   if (unsignedp)
                   1516:     return expand_binop (mode, uoptab, op0, op1, target,
                   1517:                         unsignedp, methods);
                   1518:   return 0;
                   1519: }
                   1520: 
                   1521: /* Generate code to perform an operation specified by BINOPTAB
                   1522:    on operands OP0 and OP1, with two results to TARG1 and TARG2.
                   1523:    We assume that the order of the operands for the instruction
                   1524:    is TARG0, OP0, OP1, TARG1, which would fit a pattern like
                   1525:    [(set TARG0 (operate OP0 OP1)) (set TARG1 (operate ...))].
                   1526: 
                   1527:    Either TARG0 or TARG1 may be zero, but what that means is that
                   1528:    that result is not actually wanted.  We will generate it into
                   1529:    a dummy pseudo-reg and discard it.  They may not both be zero.
                   1530: 
                   1531:    Returns 1 if this operation can be performed; 0 if not.  */
                   1532: 
                   1533: int
                   1534: expand_twoval_binop (binoptab, op0, op1, targ0, targ1, unsignedp)
                   1535:      optab binoptab;
                   1536:      rtx op0, op1;
                   1537:      rtx targ0, targ1;
                   1538:      int unsignedp;
                   1539: {
                   1540:   enum machine_mode mode = GET_MODE (targ0 ? targ0 : targ1);
                   1541:   enum mode_class class;
                   1542:   enum machine_mode wider_mode;
                   1543:   rtx entry_last = get_last_insn ();
                   1544:   rtx last;
                   1545: 
                   1546:   class = GET_MODE_CLASS (mode);
                   1547: 
                   1548:   op0 = protect_from_queue (op0, 0);
                   1549:   op1 = protect_from_queue (op1, 0);
                   1550: 
                   1551:   if (flag_force_mem)
                   1552:     {
                   1553:       op0 = force_not_mem (op0);
                   1554:       op1 = force_not_mem (op1);
                   1555:     }
                   1556: 
                   1557:   /* If we are inside an appropriately-short loop and one operand is an
                   1558:      expensive constant, force it into a register.  */
                   1559:   if (CONSTANT_P (op0) && preserve_subexpressions_p ()
                   1560:       && rtx_cost (op0, binoptab->code) > 2)
                   1561:     op0 = force_reg (mode, op0);
                   1562: 
                   1563:   if (CONSTANT_P (op1) && preserve_subexpressions_p ()
                   1564:       && rtx_cost (op1, binoptab->code) > 2)
                   1565:     op1 = force_reg (mode, op1);
                   1566: 
                   1567:   if (targ0)
                   1568:     targ0 = protect_from_queue (targ0, 1);
                   1569:   else
                   1570:     targ0 = gen_reg_rtx (mode);
                   1571:   if (targ1)
                   1572:     targ1 = protect_from_queue (targ1, 1);
                   1573:   else
                   1574:     targ1 = gen_reg_rtx (mode);
                   1575: 
                   1576:   /* Record where to go back to if we fail.  */
                   1577:   last = get_last_insn ();
                   1578: 
                   1579:   if (binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
                   1580:     {
                   1581:       int icode = (int) binoptab->handlers[(int) mode].insn_code;
                   1582:       enum machine_mode mode0 = insn_operand_mode[icode][1];
                   1583:       enum machine_mode mode1 = insn_operand_mode[icode][2];
                   1584:       rtx pat;
                   1585:       rtx xop0 = op0, xop1 = op1;
                   1586: 
                   1587:       /* In case this insn wants input operands in modes different from the
                   1588:         result, convert the operands.  */
                   1589:       if (GET_MODE (op0) != VOIDmode && GET_MODE (op0) != mode0)
                   1590:        xop0 = convert_to_mode (mode0, xop0, unsignedp);
                   1591: 
                   1592:       if (GET_MODE (op1) != VOIDmode && GET_MODE (op1) != mode1)
                   1593:        xop1 = convert_to_mode (mode1, xop1, unsignedp);
                   1594: 
                   1595:       /* Now, if insn doesn't accept these operands, put them into pseudos.  */
                   1596:       if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))
                   1597:        xop0 = copy_to_mode_reg (mode0, xop0);
                   1598: 
                   1599:       if (! (*insn_operand_predicate[icode][2]) (xop1, mode1))
                   1600:        xop1 = copy_to_mode_reg (mode1, xop1);
                   1601: 
                   1602:       /* We could handle this, but we should always be called with a pseudo
                   1603:         for our targets and all insns should take them as outputs.  */
                   1604:       if (! (*insn_operand_predicate[icode][0]) (targ0, mode)
                   1605:          || ! (*insn_operand_predicate[icode][3]) (targ1, mode))
                   1606:        abort ();
                   1607:        
                   1608:       pat = GEN_FCN (icode) (targ0, xop0, xop1, targ1);
                   1609:       if (pat)
                   1610:        {
                   1611:          emit_insn (pat);
                   1612:          return 1;
                   1613:        }
                   1614:       else
                   1615:        delete_insns_since (last);
                   1616:     }
                   1617: 
                   1618:   /* It can't be done in this mode.  Can we do it in a wider mode?  */
                   1619: 
                   1620:   if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
                   1621:     {
                   1622:       for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
                   1623:           wider_mode = GET_MODE_WIDER_MODE (wider_mode))
                   1624:        {
                   1625:          if (binoptab->handlers[(int) wider_mode].insn_code
                   1626:              != CODE_FOR_nothing)
                   1627:            {
                   1628:              register rtx t0 = gen_reg_rtx (wider_mode);
                   1629:              register rtx t1 = gen_reg_rtx (wider_mode);
                   1630: 
                   1631:              if (expand_twoval_binop (binoptab,
                   1632:                                       convert_modes (wider_mode, mode, op0,
                   1633:                                                      unsignedp),
                   1634:                                       convert_modes (wider_mode, mode, op1,
                   1635:                                                      unsignedp),
                   1636:                                       t0, t1, unsignedp))
                   1637:                {
                   1638:                  convert_move (targ0, t0, unsignedp);
                   1639:                  convert_move (targ1, t1, unsignedp);
                   1640:                  return 1;
                   1641:                }
                   1642:              else
                   1643:                delete_insns_since (last);
                   1644:            }
                   1645:        }
                   1646:     }
                   1647: 
                   1648:   delete_insns_since (entry_last);
                   1649:   return 0;
                   1650: }
                   1651: 
                   1652: /* Generate code to perform an operation specified by UNOPTAB
                   1653:    on operand OP0, with result having machine-mode MODE.
                   1654: 
                   1655:    UNSIGNEDP is for the case where we have to widen the operands
                   1656:    to perform the operation.  It says to use zero-extension.
                   1657: 
                   1658:    If TARGET is nonzero, the value
                   1659:    is generated there, if it is convenient to do so.
                   1660:    In all cases an rtx is returned for the locus of the value;
                   1661:    this may or may not be TARGET.  */
                   1662: 
                   1663: rtx
                   1664: expand_unop (mode, unoptab, op0, target, unsignedp)
                   1665:      enum machine_mode mode;
                   1666:      optab unoptab;
                   1667:      rtx op0;
                   1668:      rtx target;
                   1669:      int unsignedp;
                   1670: {
                   1671:   enum mode_class class;
                   1672:   enum machine_mode wider_mode;
                   1673:   register rtx temp;
                   1674:   rtx last = get_last_insn ();
                   1675:   rtx pat;
                   1676: 
                   1677:   class = GET_MODE_CLASS (mode);
                   1678: 
                   1679:   op0 = protect_from_queue (op0, 0);
                   1680: 
                   1681:   if (flag_force_mem)
                   1682:     {
                   1683:       op0 = force_not_mem (op0);
                   1684:     }
                   1685: 
                   1686:   if (target)
                   1687:     target = protect_from_queue (target, 1);
                   1688: 
                   1689:   if (unoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
                   1690:     {
                   1691:       int icode = (int) unoptab->handlers[(int) mode].insn_code;
                   1692:       enum machine_mode mode0 = insn_operand_mode[icode][1];
                   1693:       rtx xop0 = op0;
                   1694: 
                   1695:       if (target)
                   1696:        temp = target;
                   1697:       else
                   1698:        temp = gen_reg_rtx (mode);
                   1699: 
                   1700:       if (GET_MODE (xop0) != VOIDmode
                   1701:          && GET_MODE (xop0) != mode0)
                   1702:        xop0 = convert_to_mode (mode0, xop0, unsignedp);
                   1703: 
                   1704:       /* Now, if insn doesn't accept our operand, put it into a pseudo.  */
                   1705: 
                   1706:       if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))
                   1707:        xop0 = copy_to_mode_reg (mode0, xop0);
                   1708: 
                   1709:       if (! (*insn_operand_predicate[icode][0]) (temp, mode))
                   1710:        temp = gen_reg_rtx (mode);
                   1711: 
                   1712:       pat = GEN_FCN (icode) (temp, xop0);
                   1713:       if (pat)
                   1714:        {
                   1715:          if (GET_CODE (pat) == SEQUENCE
                   1716:              && ! add_equal_note (pat, temp, unoptab->code, xop0, NULL_RTX))
                   1717:            {
                   1718:              delete_insns_since (last);
                   1719:              return expand_unop (mode, unoptab, op0, NULL_RTX, unsignedp);
                   1720:            }
                   1721: 
                   1722:          emit_insn (pat);
                   1723:          
                   1724:          return temp;
                   1725:        }
                   1726:       else
                   1727:        delete_insns_since (last);
                   1728:     }
                   1729: 
                   1730:   /* It can't be done in this mode.  Can we open-code it in a wider mode?  */
                   1731: 
                   1732:   if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
                   1733:     for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
                   1734:         wider_mode = GET_MODE_WIDER_MODE (wider_mode))
                   1735:       {
                   1736:        if (unoptab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing)
                   1737:          {
                   1738:            rtx xop0 = op0;
                   1739: 
                   1740:            /* For certain operations, we need not actually extend
                   1741:               the narrow operand, as long as we will truncate the
                   1742:               results to the same narrowness.  */
                   1743: 
                   1744:            xop0 = widen_operand (xop0, wider_mode, mode, unsignedp,
                   1745:                                  (unoptab == neg_optab
                   1746:                                   || unoptab == one_cmpl_optab)
                   1747:                                  && class == MODE_INT);
                   1748:              
                   1749:            temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
                   1750:                                unsignedp);
                   1751: 
                   1752:            if (temp)
                   1753:              {
                   1754:                if (class != MODE_INT)
                   1755:                  {
                   1756:                    if (target == 0)
                   1757:                      target = gen_reg_rtx (mode);
                   1758:                    convert_move (target, temp, 0);
                   1759:                    return target;
                   1760:                  }
                   1761:                else
                   1762:                  return gen_lowpart (mode, temp);
                   1763:              }
                   1764:            else
                   1765:              delete_insns_since (last);
                   1766:          }
                   1767:       }
                   1768: 
                   1769:   /* These can be done a word at a time.  */
                   1770:   if (unoptab == one_cmpl_optab
                   1771:       && class == MODE_INT
                   1772:       && GET_MODE_SIZE (mode) > UNITS_PER_WORD
                   1773:       && unoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
                   1774:     {
                   1775:       int i;
                   1776:       rtx insns;
                   1777: 
                   1778:       if (target == 0 || target == op0)
                   1779:        target = gen_reg_rtx (mode);
                   1780: 
                   1781:       start_sequence ();
                   1782: 
                   1783:       /* Do the actual arithmetic.  */
                   1784:       for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)
                   1785:        {
                   1786:          rtx target_piece = operand_subword (target, i, 1, mode);
                   1787:          rtx x = expand_unop (word_mode, unoptab,
                   1788:                               operand_subword_force (op0, i, mode),
                   1789:                               target_piece, unsignedp);
                   1790:          if (target_piece != x)
                   1791:            emit_move_insn (target_piece, x);
                   1792:        }
                   1793: 
                   1794:       insns = get_insns ();
                   1795:       end_sequence ();
                   1796: 
                   1797:       emit_no_conflict_block (insns, target, op0, NULL_RTX,
                   1798:                              gen_rtx (unoptab->code, mode, copy_rtx (op0)));
                   1799:       return target;
                   1800:     }
                   1801: 
                   1802:   /* Open-code the complex negation operation.  */
                   1803:   else if (unoptab == neg_optab
                   1804:           && (class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT))
                   1805:     {
                   1806:       rtx target_piece;
                   1807:       rtx x;
                   1808:       rtx seq;
                   1809: 
                   1810:       /* Find the correct mode for the real and imaginary parts */
                   1811:       enum machine_mode submode
                   1812:        = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT,
                   1813:                         class == MODE_COMPLEX_INT ? MODE_INT : MODE_FLOAT,
                   1814:                         0);
                   1815: 
                   1816:       if (submode == BLKmode)
                   1817:        abort ();
                   1818: 
                   1819:       if (target == 0)
                   1820:        target = gen_reg_rtx (mode);
                   1821:       
                   1822:       start_sequence ();
                   1823: 
                   1824:       target_piece = gen_imagpart (submode, target);
                   1825:       x = expand_unop (submode, unoptab,
                   1826:                       gen_imagpart (submode, op0),
                   1827:                       target_piece, unsignedp);
                   1828:       if (target_piece != x)
                   1829:        emit_move_insn (target_piece, x);
                   1830: 
                   1831:       target_piece = gen_realpart (submode, target);
                   1832:       x = expand_unop (submode, unoptab,
                   1833:                       gen_realpart (submode, op0),
                   1834:                       target_piece, unsignedp);
                   1835:       if (target_piece != x)
                   1836:        emit_move_insn (target_piece, x);
                   1837: 
                   1838:       seq = get_insns ();
                   1839:       end_sequence ();
                   1840: 
                   1841:       emit_no_conflict_block (seq, target, op0, 0,
                   1842:                              gen_rtx (unoptab->code, mode, copy_rtx (op0)));
                   1843:       return target;
                   1844:     }
                   1845: 
                   1846:   /* Now try a library call in this mode.  */
                   1847:   if (unoptab->handlers[(int) mode].libfunc)
                   1848:     {
                   1849:       rtx insns;
                   1850:       rtx funexp = unoptab->handlers[(int) mode].libfunc;
                   1851:       rtx value;
                   1852: 
                   1853:       start_sequence ();
                   1854: 
                   1855:       /* Pass 1 for NO_QUEUE so we don't lose any increments
                   1856:         if the libcall is cse'd or moved.  */
                   1857:       value = emit_library_call_value (unoptab->handlers[(int) mode].libfunc,
                   1858:                                       NULL_RTX, 1, mode, 1, op0, mode);
                   1859:       insns = get_insns ();
                   1860:       end_sequence ();
                   1861: 
                   1862:       target = gen_reg_rtx (mode);
                   1863:       emit_libcall_block (insns, target, value,
                   1864:                          gen_rtx (unoptab->code, mode, op0));
                   1865: 
                   1866:       return target;
                   1867:     }
                   1868: 
                   1869:   /* It can't be done in this mode.  Can we do it in a wider mode?  */
                   1870: 
                   1871:   if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
                   1872:     {
                   1873:       for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
                   1874:           wider_mode = GET_MODE_WIDER_MODE (wider_mode))
                   1875:        {
                   1876:          if ((unoptab->handlers[(int) wider_mode].insn_code
                   1877:               != CODE_FOR_nothing)
                   1878:              || unoptab->handlers[(int) wider_mode].libfunc)
                   1879:            {
                   1880:              rtx xop0 = op0;
                   1881: 
                   1882:              /* For certain operations, we need not actually extend
                   1883:                 the narrow operand, as long as we will truncate the
                   1884:                 results to the same narrowness.  */
                   1885: 
                   1886:              xop0 = widen_operand (xop0, wider_mode, mode, unsignedp,
                   1887:                                    (unoptab == neg_optab
                   1888:                                     || unoptab == one_cmpl_optab)
                   1889:                                    && class == MODE_INT);
                   1890:              
                   1891:              temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
                   1892:                                  unsignedp);
                   1893: 
                   1894:              if (temp)
                   1895:                {
                   1896:                  if (class != MODE_INT)
                   1897:                    {
                   1898:                      if (target == 0)
                   1899:                        target = gen_reg_rtx (mode);
                   1900:                      convert_move (target, temp, 0);
                   1901:                      return target;
                   1902:                    }
                   1903:                  else
                   1904:                    return gen_lowpart (mode, temp);
                   1905:                }
                   1906:              else
                   1907:                delete_insns_since (last);
                   1908:            }
                   1909:        }
                   1910:     }
                   1911: 
                   1912:   return 0;
                   1913: }
                   1914: 
                   1915: /* Emit code to compute the absolute value of OP0, with result to
                   1916:    TARGET if convenient.  (TARGET may be 0.)  The return value says
                   1917:    where the result actually is to be found.
                   1918: 
                   1919:    MODE is the mode of the operand; the mode of the result is
                   1920:    different but can be deduced from MODE.
                   1921: 
                   1922:    UNSIGNEDP is relevant for complex integer modes.  */
                   1923: 
                   1924: rtx
                   1925: expand_complex_abs (mode, op0, target, unsignedp)
                   1926:      enum machine_mode mode;
                   1927:      rtx op0;
                   1928:      rtx target;
                   1929:      int unsignedp;
                   1930: {
                   1931:   enum mode_class class = GET_MODE_CLASS (mode);
                   1932:   enum machine_mode wider_mode;
                   1933:   register rtx temp;
                   1934:   rtx entry_last = get_last_insn ();
                   1935:   rtx last;
                   1936:   rtx pat;
                   1937: 
                   1938:   /* Find the correct mode for the real and imaginary parts.  */
                   1939:   enum machine_mode submode
                   1940:     = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT,
                   1941:                     class == MODE_COMPLEX_INT ? MODE_INT : MODE_FLOAT,
                   1942:                     0);
                   1943: 
                   1944:   if (submode == BLKmode)
                   1945:     abort ();
                   1946: 
                   1947:   op0 = protect_from_queue (op0, 0);
                   1948: 
                   1949:   if (flag_force_mem)
                   1950:     {
                   1951:       op0 = force_not_mem (op0);
                   1952:     }
                   1953: 
                   1954:   last = get_last_insn ();
                   1955: 
                   1956:   if (target)
                   1957:     target = protect_from_queue (target, 1);
                   1958: 
                   1959:   if (abs_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
                   1960:     {
                   1961:       int icode = (int) abs_optab->handlers[(int) mode].insn_code;
                   1962:       enum machine_mode mode0 = insn_operand_mode[icode][1];
                   1963:       rtx xop0 = op0;
                   1964: 
                   1965:       if (target)
                   1966:        temp = target;
                   1967:       else
                   1968:        temp = gen_reg_rtx (submode);
                   1969: 
                   1970:       if (GET_MODE (xop0) != VOIDmode
                   1971:          && GET_MODE (xop0) != mode0)
                   1972:        xop0 = convert_to_mode (mode0, xop0, unsignedp);
                   1973: 
                   1974:       /* Now, if insn doesn't accept our operand, put it into a pseudo.  */
                   1975: 
                   1976:       if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))
                   1977:        xop0 = copy_to_mode_reg (mode0, xop0);
                   1978: 
                   1979:       if (! (*insn_operand_predicate[icode][0]) (temp, submode))
                   1980:        temp = gen_reg_rtx (submode);
                   1981: 
                   1982:       pat = GEN_FCN (icode) (temp, xop0);
                   1983:       if (pat)
                   1984:        {
                   1985:          if (GET_CODE (pat) == SEQUENCE
                   1986:              && ! add_equal_note (pat, temp, abs_optab->code, xop0, NULL_RTX))
                   1987:            {
                   1988:              delete_insns_since (last);
                   1989:              return expand_unop (mode, abs_optab, op0, NULL_RTX, unsignedp);
                   1990:            }
                   1991: 
                   1992:          emit_insn (pat);
                   1993:          
                   1994:          return temp;
                   1995:        }
                   1996:       else
                   1997:        delete_insns_since (last);
                   1998:     }
                   1999: 
                   2000:   /* It can't be done in this mode.  Can we open-code it in a wider mode?  */
                   2001: 
                   2002:   for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
                   2003:        wider_mode = GET_MODE_WIDER_MODE (wider_mode))
                   2004:     {
                   2005:       if (abs_optab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing)
                   2006:        {
                   2007:          rtx xop0 = op0;
                   2008: 
                   2009:          xop0 = convert_modes (wider_mode, mode, xop0, unsignedp);
                   2010:          temp = expand_complex_abs (wider_mode, xop0, NULL_RTX, unsignedp);
                   2011: 
                   2012:          if (temp)
                   2013:            {
                   2014:              if (class != MODE_COMPLEX_INT)
                   2015:                {
                   2016:                  if (target == 0)
                   2017:                    target = gen_reg_rtx (submode);
                   2018:                  convert_move (target, temp, 0);
                   2019:                  return target;
                   2020:                }
                   2021:              else
                   2022:                return gen_lowpart (submode, temp);
                   2023:            }
                   2024:          else
                   2025:            delete_insns_since (last);
                   2026:        }
                   2027:     }
                   2028: 
                   2029:   /* Open-code the complex absolute-value operation
                   2030:      if we can open-code sqrt.  Otherwise it's not worth while.  */
                   2031:   if (sqrt_optab->handlers[(int) submode].insn_code != CODE_FOR_nothing)
                   2032:     {
                   2033:       rtx real, imag, total;
                   2034: 
                   2035:       real = gen_realpart (submode, op0);
                   2036:       imag = gen_imagpart (submode, op0);
                   2037: 
                   2038:       /* Square both parts.  */
                   2039:       real = expand_mult (submode, real, real, NULL_RTX, 0);
                   2040:       imag = expand_mult (submode, imag, imag, NULL_RTX, 0);
                   2041: 
                   2042:       /* Sum the parts.  */
                   2043:       total = expand_binop (submode, add_optab, real, imag, 0,
                   2044:                            0, OPTAB_LIB_WIDEN);
                   2045: 
                   2046:       /* Get sqrt in TARGET.  Set TARGET to where the result is.  */
                   2047:       target = expand_unop (submode, sqrt_optab, total, target, 0);
                   2048:       if (target == 0)
                   2049:        delete_insns_since (last);
                   2050:       else
                   2051:        return target;
                   2052:     }
                   2053: 
                   2054:   /* Now try a library call in this mode.  */
                   2055:   if (abs_optab->handlers[(int) mode].libfunc)
                   2056:     {
                   2057:       rtx insns;
                   2058:       rtx funexp = abs_optab->handlers[(int) mode].libfunc;
                   2059:       rtx value;
                   2060: 
                   2061:       start_sequence ();
                   2062: 
                   2063:       /* Pass 1 for NO_QUEUE so we don't lose any increments
                   2064:         if the libcall is cse'd or moved.  */
                   2065:       value = emit_library_call_value (abs_optab->handlers[(int) mode].libfunc,
                   2066:                                       NULL_RTX, 1, submode, 1, op0, mode);
                   2067:       insns = get_insns ();
                   2068:       end_sequence ();
                   2069: 
                   2070:       target = gen_reg_rtx (submode);
                   2071:       emit_libcall_block (insns, target, value,
                   2072:                          gen_rtx (abs_optab->code, mode, op0));
                   2073: 
                   2074:       return target;
                   2075:     }
                   2076: 
                   2077:   /* It can't be done in this mode.  Can we do it in a wider mode?  */
                   2078: 
                   2079:   for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
                   2080:        wider_mode = GET_MODE_WIDER_MODE (wider_mode))
                   2081:     {
                   2082:       if ((abs_optab->handlers[(int) wider_mode].insn_code
                   2083:           != CODE_FOR_nothing)
                   2084:          || abs_optab->handlers[(int) wider_mode].libfunc)
                   2085:        {
                   2086:          rtx xop0 = op0;
                   2087: 
                   2088:          xop0 = convert_modes (wider_mode, mode, xop0, unsignedp);
                   2089: 
                   2090:          temp = expand_complex_abs (wider_mode, xop0, NULL_RTX, unsignedp);
                   2091: 
                   2092:          if (temp)
                   2093:            {
                   2094:              if (class != MODE_COMPLEX_INT)
                   2095:                {
                   2096:                  if (target == 0)
                   2097:                    target = gen_reg_rtx (submode);
                   2098:                  convert_move (target, temp, 0);
                   2099:                  return target;
                   2100:                }
                   2101:              else
                   2102:                return gen_lowpart (submode, temp);
                   2103:            }
                   2104:          else
                   2105:            delete_insns_since (last);
                   2106:        }
                   2107:     }
                   2108: 
                   2109:   delete_insns_since (entry_last);
                   2110:   return 0;
                   2111: }
                   2112: 
                   2113: /* Generate an instruction whose insn-code is INSN_CODE,
                   2114:    with two operands: an output TARGET and an input OP0.
                   2115:    TARGET *must* be nonzero, and the output is always stored there.
                   2116:    CODE is an rtx code such that (CODE OP0) is an rtx that describes
                   2117:    the value that is stored into TARGET.  */
                   2118: 
                   2119: void
                   2120: emit_unop_insn (icode, target, op0, code)
                   2121:      int icode;
                   2122:      rtx target;
                   2123:      rtx op0;
                   2124:      enum rtx_code code;
                   2125: {
                   2126:   register rtx temp;
                   2127:   enum machine_mode mode0 = insn_operand_mode[icode][1];
                   2128:   rtx pat;
                   2129: 
                   2130:   temp = target = protect_from_queue (target, 1);
                   2131: 
                   2132:   op0 = protect_from_queue (op0, 0);
                   2133: 
                   2134:   if (flag_force_mem)
                   2135:     op0 = force_not_mem (op0);
                   2136: 
                   2137:   /* Now, if insn does not accept our operands, put them into pseudos.  */
                   2138: 
                   2139:   if (! (*insn_operand_predicate[icode][1]) (op0, mode0))
                   2140:     op0 = copy_to_mode_reg (mode0, op0);
                   2141: 
                   2142:   if (! (*insn_operand_predicate[icode][0]) (temp, GET_MODE (temp))
                   2143:       || (flag_force_mem && GET_CODE (temp) == MEM))
                   2144:     temp = gen_reg_rtx (GET_MODE (temp));
                   2145: 
                   2146:   pat = GEN_FCN (icode) (temp, op0);
                   2147: 
                   2148:   if (GET_CODE (pat) == SEQUENCE && code != UNKNOWN)
                   2149:     add_equal_note (pat, temp, code, op0, NULL_RTX);
                   2150:   
                   2151:   emit_insn (pat);
                   2152: 
                   2153:   if (temp != target)
                   2154:     emit_move_insn (target, temp);
                   2155: }
                   2156: 
                   2157: /* Emit code to perform a series of operations on a multi-word quantity, one
                   2158:    word at a time.
                   2159: 
                   2160:    Such a block is preceded by a CLOBBER of the output, consists of multiple
                   2161:    insns, each setting one word of the output, and followed by a SET copying
                   2162:    the output to itself.
                   2163: 
                   2164:    Each of the insns setting words of the output receives a REG_NO_CONFLICT
                   2165:    note indicating that it doesn't conflict with the (also multi-word)
                   2166:    inputs.  The entire block is surrounded by REG_LIBCALL and REG_RETVAL
                   2167:    notes.
                   2168: 
                   2169:    INSNS is a block of code generated to perform the operation, not including
                   2170:    the CLOBBER and final copy.  All insns that compute intermediate values
                   2171:    are first emitted, followed by the block as described above.  Only
                   2172:    INSNs are allowed in the block; no library calls or jumps may be
                   2173:    present.
                   2174: 
                   2175:    TARGET, OP0, and OP1 are the output and inputs of the operations,
                   2176:    respectively.  OP1 may be zero for a unary operation.
                   2177: 
                   2178:    EQUIV, if non-zero, is an expression to be placed into a REG_EQUAL note
                   2179:    on the last insn.
                   2180: 
                   2181:    If TARGET is not a register, INSNS is simply emitted with no special
                   2182:    processing.
                   2183: 
                   2184:    The final insn emitted is returned.  */
                   2185: 
                   2186: rtx
                   2187: emit_no_conflict_block (insns, target, op0, op1, equiv)
                   2188:      rtx insns;
                   2189:      rtx target;
                   2190:      rtx op0, op1;
                   2191:      rtx equiv;
                   2192: {
                   2193:   rtx prev, next, first, last, insn;
                   2194: 
                   2195:   if (GET_CODE (target) != REG || reload_in_progress)
                   2196:     return emit_insns (insns);
                   2197: 
                   2198:   /* First emit all insns that do not store into words of the output and remove
                   2199:      these from the list.  */
                   2200:   for (insn = insns; insn; insn = next)
                   2201:     {
                   2202:       rtx set = 0;
                   2203:       int i;
                   2204: 
                   2205:       next = NEXT_INSN (insn);
                   2206: 
                   2207:       if (GET_CODE (insn) != INSN)
                   2208:        abort ();
                   2209: 
                   2210:       if (GET_CODE (PATTERN (insn)) == SET)
                   2211:        set = PATTERN (insn);
                   2212:       else if (GET_CODE (PATTERN (insn)) == PARALLEL)
                   2213:        {
                   2214:          for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
                   2215:            if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET)
                   2216:              {
                   2217:                set = XVECEXP (PATTERN (insn), 0, i);
                   2218:                break;
                   2219:              }
                   2220:        }
                   2221: 
                   2222:       if (set == 0)
                   2223:        abort ();
                   2224: 
                   2225:       if (! reg_overlap_mentioned_p (target, SET_DEST (set)))
                   2226:        {
                   2227:          if (PREV_INSN (insn))
                   2228:            NEXT_INSN (PREV_INSN (insn)) = next;
                   2229:          else
                   2230:            insns = next;
                   2231: 
                   2232:          if (next)
                   2233:            PREV_INSN (next) = PREV_INSN (insn);
                   2234: 
                   2235:          add_insn (insn);
                   2236:        }
                   2237:     }
                   2238: 
                   2239:   prev = get_last_insn ();
                   2240: 
                   2241:   /* Now write the CLOBBER of the output, followed by the setting of each
                   2242:      of the words, followed by the final copy.  */
                   2243:   if (target != op0 && target != op1)
                   2244:     emit_insn (gen_rtx (CLOBBER, VOIDmode, target));
                   2245: 
                   2246:   for (insn = insns; insn; insn = next)
                   2247:     {
                   2248:       next = NEXT_INSN (insn);
                   2249:       add_insn (insn);
                   2250: 
                   2251:       if (op1 && GET_CODE (op1) == REG)
                   2252:        REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_NO_CONFLICT, op1,
                   2253:                                    REG_NOTES (insn));
                   2254: 
                   2255:       if (op0 && GET_CODE (op0) == REG)
                   2256:        REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_NO_CONFLICT, op0,
                   2257:                                    REG_NOTES (insn));
                   2258:     }
                   2259: 
                   2260:   if (mov_optab->handlers[(int) GET_MODE (target)].insn_code
                   2261:       != CODE_FOR_nothing)
                   2262:     {
                   2263:       last = emit_move_insn (target, target);
                   2264:       if (equiv)
                   2265:        REG_NOTES (last)
                   2266:          = gen_rtx (EXPR_LIST, REG_EQUAL, equiv, REG_NOTES (last));
                   2267:     }
                   2268:   else
                   2269:     last = get_last_insn ();
                   2270: 
                   2271:   if (prev == 0)
                   2272:     first = get_insns ();
                   2273:   else
                   2274:     first = NEXT_INSN (prev);
                   2275: 
                   2276:   /* Encapsulate the block so it gets manipulated as a unit.  */
                   2277:   REG_NOTES (first) = gen_rtx (INSN_LIST, REG_LIBCALL, last,
                   2278:                               REG_NOTES (first));
                   2279:   REG_NOTES (last) = gen_rtx (INSN_LIST, REG_RETVAL, first, REG_NOTES (last));
                   2280: 
                   2281:   return last;
                   2282: }
                   2283: 
                   2284: /* Emit code to make a call to a constant function or a library call.
                   2285: 
                   2286:    INSNS is a list containing all insns emitted in the call.
                   2287:    These insns leave the result in RESULT.  Our block is to copy RESULT
                   2288:    to TARGET, which is logically equivalent to EQUIV.
                   2289: 
                   2290:    We first emit any insns that set a pseudo on the assumption that these are
                   2291:    loading constants into registers; doing so allows them to be safely cse'ed
                   2292:    between blocks.  Then we emit all the other insns in the block, followed by
                   2293:    an insn to move RESULT to TARGET.  This last insn will have a REQ_EQUAL
                   2294:    note with an operand of EQUIV.
                   2295: 
                   2296:    Moving assignments to pseudos outside of the block is done to improve
                   2297:    the generated code, but is not required to generate correct code,
                   2298:    hence being unable to move an assignment is not grounds for not making
                   2299:    a libcall block.  There are two reasons why it is safe to leave these
                   2300:    insns inside the block: First, we know that these pseudos cannot be
                   2301:    used in generated RTL outside the block since they are created for
                   2302:    temporary purposes within the block.  Second, CSE will not record the
                   2303:    values of anything set inside a libcall block, so we know they must
                   2304:    be dead at the end of the block.
                   2305: 
                   2306:    Except for the first group of insns (the ones setting pseudos), the
                   2307:    block is delimited by REG_RETVAL and REG_LIBCALL notes.  */
                   2308: 
                   2309: void
                   2310: emit_libcall_block (insns, target, result, equiv)
                   2311:      rtx insns;
                   2312:      rtx target;
                   2313:      rtx result;
                   2314:      rtx equiv;
                   2315: {
                   2316:   rtx prev, next, first, last, insn;
                   2317: 
                   2318:   /* First emit all insns that set pseudos.  Remove them from the list as
                   2319:      we go.  Avoid insns that set pseudos which were referenced in previous
                   2320:      insns.  These can be generated by move_by_pieces, for example,
                   2321:      to update an address.  Similarly, avoid insns that reference things
                   2322:      set in previous insns.  */
                   2323: 
                   2324:   for (insn = insns; insn; insn = next)
                   2325:     {
                   2326:       rtx set = single_set (insn);
                   2327: 
                   2328:       next = NEXT_INSN (insn);
                   2329: 
                   2330:       if (set != 0 && GET_CODE (SET_DEST (set)) == REG
                   2331:          && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER
                   2332:          && (insn == insns
                   2333:              || (! reg_mentioned_p (SET_DEST (set), PATTERN (insns))
                   2334:                  && ! reg_used_between_p (SET_DEST (set), insns, insn)
                   2335:                  && ! modified_in_p (SET_SRC (set), insns)
                   2336:                  && ! modified_between_p (SET_SRC (set), insns, insn))))
                   2337:        {
                   2338:          if (PREV_INSN (insn))
                   2339:            NEXT_INSN (PREV_INSN (insn)) = next;
                   2340:          else
                   2341:            insns = next;
                   2342: 
                   2343:          if (next)
                   2344:            PREV_INSN (next) = PREV_INSN (insn);
                   2345: 
                   2346:          add_insn (insn);
                   2347:        }
                   2348:     }
                   2349: 
                   2350:   prev = get_last_insn ();
                   2351: 
                   2352:   /* Write the remaining insns followed by the final copy.  */
                   2353: 
                   2354:   for (insn = insns; insn; insn = next)
                   2355:     {
                   2356:       next = NEXT_INSN (insn);
                   2357: 
                   2358:       add_insn (insn);
                   2359:     }
                   2360: 
                   2361:   last = emit_move_insn (target, result);
                   2362:   REG_NOTES (last) = gen_rtx (EXPR_LIST,
                   2363:                              REG_EQUAL, copy_rtx (equiv), REG_NOTES (last));
                   2364: 
                   2365:   if (prev == 0)
                   2366:     first = get_insns ();
                   2367:   else
                   2368:     first = NEXT_INSN (prev);
                   2369: 
                   2370:   /* Encapsulate the block so it gets manipulated as a unit.  */
                   2371:   REG_NOTES (first) = gen_rtx (INSN_LIST, REG_LIBCALL, last,
                   2372:                               REG_NOTES (first));
                   2373:   REG_NOTES (last) = gen_rtx (INSN_LIST, REG_RETVAL, first, REG_NOTES (last));
                   2374: }
                   2375: 
                   2376: /* Generate code to store zero in X.  */
                   2377: 
                   2378: void
                   2379: emit_clr_insn (x)
                   2380:      rtx x;
                   2381: {
                   2382:   emit_move_insn (x, const0_rtx);
                   2383: }
                   2384: 
                   2385: /* Generate code to store 1 in X
                   2386:    assuming it contains zero beforehand.  */
                   2387: 
                   2388: void
                   2389: emit_0_to_1_insn (x)
                   2390:      rtx x;
                   2391: {
                   2392:   emit_move_insn (x, const1_rtx);
                   2393: }
                   2394: 
                   2395: /* Generate code to compare X with Y
                   2396:    so that the condition codes are set.
                   2397: 
                   2398:    MODE is the mode of the inputs (in case they are const_int).
                   2399:    UNSIGNEDP nonzero says that X and Y are unsigned;
                   2400:    this matters if they need to be widened.
                   2401: 
                   2402:    If they have mode BLKmode, then SIZE specifies the size of both X and Y,
                   2403:    and ALIGN specifies the known shared alignment of X and Y.
                   2404: 
                   2405:    COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).
                   2406:    It is ignored for fixed-point and block comparisons;
                   2407:    it is used only for floating-point comparisons.  */
                   2408: 
                   2409: void
                   2410: emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align)
                   2411:      rtx x, y;
                   2412:      enum rtx_code comparison;
                   2413:      rtx size;
                   2414:      enum machine_mode mode;
                   2415:      int unsignedp;
                   2416:      int align;
                   2417: {
                   2418:   enum mode_class class;
                   2419:   enum machine_mode wider_mode;
                   2420: 
                   2421:   class = GET_MODE_CLASS (mode);
                   2422: 
                   2423:   /* They could both be VOIDmode if both args are immediate constants,
                   2424:      but we should fold that at an earlier stage.
                   2425:      With no special code here, this will call abort,
                   2426:      reminding the programmer to implement such folding.  */
                   2427: 
                   2428:   if (mode != BLKmode && flag_force_mem)
                   2429:     {
                   2430:       x = force_not_mem (x);
                   2431:       y = force_not_mem (y);
                   2432:     }
                   2433: 
                   2434:   /* If we are inside an appropriately-short loop and one operand is an
                   2435:      expensive constant, force it into a register.  */
                   2436:   if (CONSTANT_P (x) && preserve_subexpressions_p () && rtx_cost (x, COMPARE) > 2)
                   2437:     x = force_reg (mode, x);
                   2438: 
                   2439:   if (CONSTANT_P (y) && preserve_subexpressions_p () && rtx_cost (y, COMPARE) > 2)
                   2440:     y = force_reg (mode, y);
                   2441: 
                   2442:   /* Don't let both operands fail to indicate the mode.  */
                   2443:   if (GET_MODE (x) == VOIDmode && GET_MODE (y) == VOIDmode)
                   2444:     x = force_reg (mode, x);
                   2445: 
                   2446:   /* Handle all BLKmode compares.  */
                   2447: 
                   2448:   if (mode == BLKmode)
                   2449:     {
                   2450:       emit_queue ();
                   2451:       x = protect_from_queue (x, 0);
                   2452:       y = protect_from_queue (y, 0);
                   2453: 
                   2454:       if (size == 0)
                   2455:        abort ();
                   2456: #ifdef HAVE_cmpstrqi
                   2457:       if (HAVE_cmpstrqi
                   2458:          && GET_CODE (size) == CONST_INT
                   2459:          && INTVAL (size) < (1 << GET_MODE_BITSIZE (QImode)))
                   2460:        {
                   2461:          enum machine_mode result_mode
                   2462:            = insn_operand_mode[(int) CODE_FOR_cmpstrqi][0];
                   2463:          rtx result = gen_reg_rtx (result_mode);
                   2464:          emit_insn (gen_cmpstrqi (result, x, y, size, GEN_INT (align)));
                   2465:          emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX,
                   2466:                         result_mode, 0, 0);
                   2467:        }
                   2468:       else
                   2469: #endif
                   2470: #ifdef HAVE_cmpstrhi
                   2471:       if (HAVE_cmpstrhi
                   2472:          && GET_CODE (size) == CONST_INT
                   2473:          && INTVAL (size) < (1 << GET_MODE_BITSIZE (HImode)))
                   2474:        {
                   2475:          enum machine_mode result_mode
                   2476:            = insn_operand_mode[(int) CODE_FOR_cmpstrhi][0];
                   2477:          rtx result = gen_reg_rtx (result_mode);
                   2478:          emit_insn (gen_cmpstrhi (result, x, y, size, GEN_INT (align)));
                   2479:          emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX,
                   2480:                         result_mode, 0, 0);
                   2481:        }
                   2482:       else
                   2483: #endif
                   2484: #ifdef HAVE_cmpstrsi
                   2485:       if (HAVE_cmpstrsi)
                   2486:        {
                   2487:          enum machine_mode result_mode
                   2488:            = insn_operand_mode[(int) CODE_FOR_cmpstrsi][0];
                   2489:          rtx result = gen_reg_rtx (result_mode);
                   2490:          size = protect_from_queue (size, 0);
                   2491:          emit_insn (gen_cmpstrsi (result, x, y,
                   2492:                                   convert_to_mode (SImode, size, 1),
                   2493:                                   GEN_INT (align)));
                   2494:          emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX,
                   2495:                         result_mode, 0, 0);
                   2496:        }
                   2497:       else
                   2498: #endif
                   2499:        {
                   2500: #ifdef TARGET_MEM_FUNCTIONS
                   2501:          emit_library_call (memcmp_libfunc, 0,
                   2502:                             TYPE_MODE (integer_type_node), 3,
                   2503:                             XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
                   2504:                             size, Pmode);
                   2505: #else
                   2506:          emit_library_call (bcmp_libfunc, 0,
                   2507:                             TYPE_MODE (integer_type_node), 3,
                   2508:                             XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
                   2509:                             size, Pmode);
                   2510: #endif
                   2511:          emit_cmp_insn (hard_libcall_value (TYPE_MODE (integer_type_node)),
                   2512:                         const0_rtx, comparison, NULL_RTX,
                   2513:                         TYPE_MODE (integer_type_node), 0, 0);
                   2514:        }
                   2515:       return;
                   2516:     }
                   2517: 
                   2518:   /* Handle some compares against zero.  */
                   2519: 
                   2520:   if (y == CONST0_RTX (mode)
                   2521:       && tst_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
                   2522:     {
                   2523:       int icode = (int) tst_optab->handlers[(int) mode].insn_code;
                   2524: 
                   2525:       emit_queue ();
                   2526:       x = protect_from_queue (x, 0);
                   2527:       y = protect_from_queue (y, 0);
                   2528: 
                   2529:       /* Now, if insn does accept these operands, put them into pseudos.  */
                   2530:       if (! (*insn_operand_predicate[icode][0])
                   2531:          (x, insn_operand_mode[icode][0]))
                   2532:        x = copy_to_mode_reg (insn_operand_mode[icode][0], x);
                   2533: 
                   2534:       emit_insn (GEN_FCN (icode) (x));
                   2535:       return;
                   2536:     }
                   2537: 
                   2538:   /* Handle compares for which there is a directly suitable insn.  */
                   2539: 
                   2540:   if (cmp_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
                   2541:     {
                   2542:       int icode = (int) cmp_optab->handlers[(int) mode].insn_code;
                   2543: 
                   2544:       emit_queue ();
                   2545:       x = protect_from_queue (x, 0);
                   2546:       y = protect_from_queue (y, 0);
                   2547: 
                   2548:       /* Now, if insn doesn't accept these operands, put them into pseudos.  */
                   2549:       if (! (*insn_operand_predicate[icode][0])
                   2550:          (x, insn_operand_mode[icode][0]))
                   2551:        x = copy_to_mode_reg (insn_operand_mode[icode][0], x);
                   2552: 
                   2553:       if (! (*insn_operand_predicate[icode][1])
                   2554:          (y, insn_operand_mode[icode][1]))
                   2555:        y = copy_to_mode_reg (insn_operand_mode[icode][1], y);
                   2556: 
                   2557:       emit_insn (GEN_FCN (icode) (x, y));
                   2558:       return;
                   2559:     }
                   2560: 
                   2561:   /* Try widening if we can find a direct insn that way.  */
                   2562: 
                   2563:   if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
                   2564:     {
                   2565:       for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
                   2566:           wider_mode = GET_MODE_WIDER_MODE (wider_mode))
                   2567:        {
                   2568:          if (cmp_optab->handlers[(int) wider_mode].insn_code
                   2569:              != CODE_FOR_nothing)
                   2570:            {
                   2571:              x = protect_from_queue (x, 0);
                   2572:              y = protect_from_queue (y, 0);
                   2573:              x = convert_modes (wider_mode, mode, x, unsignedp);
                   2574:              y = convert_modes (wider_mode, mode, y, unsignedp);
                   2575:              emit_cmp_insn (x, y, comparison, NULL_RTX,
                   2576:                             wider_mode, unsignedp, align);
                   2577:              return;
                   2578:            }
                   2579:        }
                   2580:     }
                   2581: 
                   2582:   /* Handle a lib call just for the mode we are using.  */
                   2583: 
                   2584:   if (cmp_optab->handlers[(int) mode].libfunc
                   2585:       && class != MODE_FLOAT)
                   2586:     {
                   2587:       rtx libfunc = cmp_optab->handlers[(int) mode].libfunc;
                   2588:       /* If we want unsigned, and this mode has a distinct unsigned
                   2589:         comparison routine, use that.  */
                   2590:       if (unsignedp && ucmp_optab->handlers[(int) mode].libfunc)
                   2591:        libfunc = ucmp_optab->handlers[(int) mode].libfunc;
                   2592: 
                   2593:       emit_library_call (libfunc, 1,
                   2594:                         word_mode, 2, x, mode, y, mode);
                   2595: 
                   2596:       /* Integer comparison returns a result that must be compared against 1,
                   2597:         so that even if we do an unsigned compare afterward,
                   2598:         there is still a value that can represent the result "less than".  */
                   2599: 
                   2600:       emit_cmp_insn (hard_libcall_value (word_mode), const1_rtx,
                   2601:                     comparison, NULL_RTX, word_mode, unsignedp, 0);
                   2602:       return;
                   2603:     }
                   2604: 
                   2605:   if (class == MODE_FLOAT)
                   2606:     emit_float_lib_cmp (x, y, comparison);
                   2607: 
                   2608:   else
                   2609:     abort ();
                   2610: }
                   2611: 
                   2612: /* Nonzero if a compare of mode MODE can be done straightforwardly
                   2613:    (without splitting it into pieces).  */
                   2614: 
                   2615: int
                   2616: can_compare_p (mode)
                   2617:      enum machine_mode mode;
                   2618: {
                   2619:   do
                   2620:     {
                   2621:       if (cmp_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)
                   2622:        return 1;
                   2623:       mode = GET_MODE_WIDER_MODE (mode);
                   2624:     } while (mode != VOIDmode);
                   2625: 
                   2626:   return 0;
                   2627: }
                   2628: 
                   2629: /* Emit a library call comparison between floating point X and Y.
                   2630:    COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).  */
                   2631: 
                   2632: static void
                   2633: emit_float_lib_cmp (x, y, comparison)
                   2634:      rtx x, y;
                   2635:      enum rtx_code comparison;
                   2636: {
                   2637:   enum machine_mode mode = GET_MODE (x);
                   2638:   rtx libfunc;
                   2639: 
                   2640:   if (mode == SFmode)
                   2641:     switch (comparison)
                   2642:       {
                   2643:       case EQ:
                   2644:        libfunc = eqsf2_libfunc;
                   2645:        break;
                   2646: 
                   2647:       case NE:
                   2648:        libfunc = nesf2_libfunc;
                   2649:        break;
                   2650: 
                   2651:       case GT:
                   2652:        libfunc = gtsf2_libfunc;
                   2653:        break;
                   2654: 
                   2655:       case GE:
                   2656:        libfunc = gesf2_libfunc;
                   2657:        break;
                   2658: 
                   2659:       case LT:
                   2660:        libfunc = ltsf2_libfunc;
                   2661:        break;
                   2662: 
                   2663:       case LE:
                   2664:        libfunc = lesf2_libfunc;
                   2665:        break;
                   2666:       }
                   2667:   else if (mode == DFmode)
                   2668:     switch (comparison)
                   2669:       {
                   2670:       case EQ:
                   2671:        libfunc = eqdf2_libfunc;
                   2672:        break;
                   2673: 
                   2674:       case NE:
                   2675:        libfunc = nedf2_libfunc;
                   2676:        break;
                   2677: 
                   2678:       case GT:
                   2679:        libfunc = gtdf2_libfunc;
                   2680:        break;
                   2681: 
                   2682:       case GE:
                   2683:        libfunc = gedf2_libfunc;
                   2684:        break;
                   2685: 
                   2686:       case LT:
                   2687:        libfunc = ltdf2_libfunc;
                   2688:        break;
                   2689: 
                   2690:       case LE:
                   2691:        libfunc = ledf2_libfunc;
                   2692:        break;
                   2693:       }
                   2694:   else if (mode == XFmode)
                   2695:     switch (comparison)
                   2696:       {
                   2697:       case EQ:
                   2698:        libfunc = eqxf2_libfunc;
                   2699:        break;
                   2700: 
                   2701:       case NE:
                   2702:        libfunc = nexf2_libfunc;
                   2703:        break;
                   2704: 
                   2705:       case GT:
                   2706:        libfunc = gtxf2_libfunc;
                   2707:        break;
                   2708: 
                   2709:       case GE:
                   2710:        libfunc = gexf2_libfunc;
                   2711:        break;
                   2712: 
                   2713:       case LT:
                   2714:        libfunc = ltxf2_libfunc;
                   2715:        break;
                   2716: 
                   2717:       case LE:
                   2718:        libfunc = lexf2_libfunc;
                   2719:        break;
                   2720:       }
                   2721:   else if (mode == TFmode)
                   2722:     switch (comparison)
                   2723:       {
                   2724:       case EQ:
                   2725:        libfunc = eqtf2_libfunc;
                   2726:        break;
                   2727: 
                   2728:       case NE:
                   2729:        libfunc = netf2_libfunc;
                   2730:        break;
                   2731: 
                   2732:       case GT:
                   2733:        libfunc = gttf2_libfunc;
                   2734:        break;
                   2735: 
                   2736:       case GE:
                   2737:        libfunc = getf2_libfunc;
                   2738:        break;
                   2739: 
                   2740:       case LT:
                   2741:        libfunc = lttf2_libfunc;
                   2742:        break;
                   2743: 
                   2744:       case LE:
                   2745:        libfunc = letf2_libfunc;
                   2746:        break;
                   2747:       }
                   2748:   else
                   2749:     {
                   2750:       enum machine_mode wider_mode;
                   2751: 
                   2752:       for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
                   2753:           wider_mode = GET_MODE_WIDER_MODE (wider_mode))
                   2754:        {
                   2755:          if ((cmp_optab->handlers[(int) wider_mode].insn_code
                   2756:               != CODE_FOR_nothing)
                   2757:              || (cmp_optab->handlers[(int) wider_mode].libfunc != 0))
                   2758:            {
                   2759:              x = protect_from_queue (x, 0);
                   2760:              y = protect_from_queue (y, 0);
                   2761:              x = convert_to_mode (wider_mode, x, 0);
                   2762:              y = convert_to_mode (wider_mode, y, 0);
                   2763:              emit_float_lib_cmp (x, y, comparison);
                   2764:              return;
                   2765:            }
                   2766:        }
                   2767:       abort ();
                   2768:     }
                   2769: 
                   2770:   emit_library_call (libfunc, 1,
                   2771:                     word_mode, 2, x, mode, y, mode);
                   2772: 
                   2773:   emit_cmp_insn (hard_libcall_value (word_mode), const0_rtx, comparison,
                   2774:                 NULL_RTX, word_mode, 0, 0);
                   2775: }
                   2776: 
                   2777: /* Generate code to indirectly jump to a location given in the rtx LOC.  */
                   2778: 
                   2779: void
                   2780: emit_indirect_jump (loc)
                   2781:      rtx loc;
                   2782: {
                   2783:   if (! ((*insn_operand_predicate[(int)CODE_FOR_indirect_jump][0])
                   2784:         (loc, Pmode)))
                   2785:     loc = copy_to_mode_reg (Pmode, loc);
                   2786: 
                   2787:   emit_jump_insn (gen_indirect_jump (loc));
                   2788:   emit_barrier ();
                   2789: }
                   2790: 
                   2791: /* These three functions generate an insn body and return it
                   2792:    rather than emitting the insn.
                   2793: 
                   2794:    They do not protect from queued increments,
                   2795:    because they may be used 1) in protect_from_queue itself
                   2796:    and 2) in other passes where there is no queue.  */
                   2797: 
                   2798: /* Generate and return an insn body to add Y to X.  */
                   2799: 
                   2800: rtx
                   2801: gen_add2_insn (x, y)
                   2802:      rtx x, y;
                   2803: {
                   2804:   int icode = (int) add_optab->handlers[(int) GET_MODE (x)].insn_code; 
                   2805: 
                   2806:   if (! (*insn_operand_predicate[icode][0]) (x, insn_operand_mode[icode][0])
                   2807:       || ! (*insn_operand_predicate[icode][1]) (x, insn_operand_mode[icode][1])
                   2808:       || ! (*insn_operand_predicate[icode][2]) (y, insn_operand_mode[icode][2]))
                   2809:     abort ();
                   2810: 
                   2811:   return (GEN_FCN (icode) (x, x, y));
                   2812: }
                   2813: 
                   2814: int
                   2815: have_add2_insn (mode)
                   2816:      enum machine_mode mode;
                   2817: {
                   2818:   return add_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing;
                   2819: }
                   2820: 
                   2821: /* Generate and return an insn body to subtract Y from X.  */
                   2822: 
                   2823: rtx
                   2824: gen_sub2_insn (x, y)
                   2825:      rtx x, y;
                   2826: {
                   2827:   int icode = (int) sub_optab->handlers[(int) GET_MODE (x)].insn_code; 
                   2828: 
                   2829:   if (! (*insn_operand_predicate[icode][0]) (x, insn_operand_mode[icode][0])
                   2830:       || ! (*insn_operand_predicate[icode][1]) (x, insn_operand_mode[icode][1])
                   2831:       || ! (*insn_operand_predicate[icode][2]) (y, insn_operand_mode[icode][2]))
                   2832:     abort ();
                   2833: 
                   2834:   return (GEN_FCN (icode) (x, x, y));
                   2835: }
                   2836: 
                   2837: int
                   2838: have_sub2_insn (mode)
                   2839:      enum machine_mode mode;
                   2840: {
                   2841:   return sub_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing;
                   2842: }
                   2843: 
                   2844: /* Generate the body of an instruction to copy Y into X.
                   2845:    It may be a SEQUENCE, if one insn isn't enough.  */
                   2846: 
                   2847: rtx
                   2848: gen_move_insn (x, y)
                   2849:      rtx x, y;
                   2850: {
                   2851:   register enum machine_mode mode = GET_MODE (x);
                   2852:   enum insn_code insn_code;
                   2853:   rtx seq;
                   2854: 
                   2855:   if (mode == VOIDmode)
                   2856:     mode = GET_MODE (y); 
                   2857: 
                   2858:   insn_code = mov_optab->handlers[(int) mode].insn_code;
                   2859: 
                   2860:   /* Handle MODE_CC modes:  If we don't have a special move insn for this mode,
                   2861:      find a mode to do it in.  If we have a movcc, use it.  Otherwise,
                   2862:      find the MODE_INT mode of the same width.  */
                   2863: 
                   2864:   if (GET_MODE_CLASS (mode) == MODE_CC && insn_code == CODE_FOR_nothing)
                   2865:     {
                   2866:       enum machine_mode tmode = VOIDmode;
                   2867:       rtx x1 = x, y1 = y;
                   2868: 
                   2869:       if (mode != CCmode
                   2870:          && mov_optab->handlers[(int) CCmode].insn_code != CODE_FOR_nothing)
                   2871:        tmode = CCmode;
                   2872:       else
                   2873:        for (tmode = QImode; tmode != VOIDmode;
                   2874:             tmode = GET_MODE_WIDER_MODE (tmode))
                   2875:          if (GET_MODE_SIZE (tmode) == GET_MODE_SIZE (mode))
                   2876:            break;
                   2877: 
                   2878:       if (tmode == VOIDmode)
                   2879:        abort ();
                   2880: 
                   2881:       /* Get X and Y in TMODE.  We can't use gen_lowpart here because it
                   2882:         may call change_address which is not appropriate if we were
                   2883:         called when a reload was in progress.  We don't have to worry
                   2884:         about changing the address since the size in bytes is supposed to
                   2885:         be the same.  Copy the MEM to change the mode and move any
                   2886:         substitutions from the old MEM to the new one.  */
                   2887: 
                   2888:       if (reload_in_progress)
                   2889:        {
                   2890:          x = gen_lowpart_common (tmode, x1);
                   2891:          if (x == 0 && GET_CODE (x1) == MEM)
                   2892:            {
                   2893:              x = gen_rtx (MEM, tmode, XEXP (x1, 0));
                   2894:              RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (x1);
                   2895:              MEM_IN_STRUCT_P (x) = MEM_IN_STRUCT_P (x1);
                   2896:              MEM_VOLATILE_P (x) = MEM_VOLATILE_P (x1);
                   2897:              copy_replacements (x1, x);
                   2898:            }
                   2899: 
                   2900:          y = gen_lowpart_common (tmode, y1);
                   2901:          if (y == 0 && GET_CODE (y1) == MEM)
                   2902:            {
                   2903:              y = gen_rtx (MEM, tmode, XEXP (y1, 0));
                   2904:              RTX_UNCHANGING_P (y) = RTX_UNCHANGING_P (y1);
                   2905:              MEM_IN_STRUCT_P (y) = MEM_IN_STRUCT_P (y1);
                   2906:              MEM_VOLATILE_P (y) = MEM_VOLATILE_P (y1);
                   2907:              copy_replacements (y1, y);
                   2908:            }
                   2909:        }
                   2910:       else
                   2911:        {
                   2912:          x = gen_lowpart (tmode, x);
                   2913:          y = gen_lowpart (tmode, y);
                   2914:        }
                   2915:          
                   2916:       insn_code = mov_optab->handlers[(int) tmode].insn_code;
                   2917:       return (GEN_FCN (insn_code) (x, y));
                   2918:     }
                   2919: 
                   2920:   start_sequence ();
                   2921:   emit_move_insn_1 (x, y);
                   2922:   seq = gen_sequence ();
                   2923:   end_sequence ();
                   2924:   return seq;
                   2925: }
                   2926: 
                   2927: /* Return the insn code used to extend FROM_MODE to TO_MODE.
                   2928:    UNSIGNEDP specifies zero-extension instead of sign-extension.  If
                   2929:    no such operation exists, CODE_FOR_nothing will be returned.  */
                   2930: 
                   2931: enum insn_code
                   2932: can_extend_p (to_mode, from_mode, unsignedp)
                   2933:      enum machine_mode to_mode, from_mode;
                   2934:      int unsignedp;
                   2935: {
                   2936:   return extendtab[(int) to_mode][(int) from_mode][unsignedp];
                   2937: }
                   2938: 
                   2939: /* Generate the body of an insn to extend Y (with mode MFROM)
                   2940:    into X (with mode MTO).  Do zero-extension if UNSIGNEDP is nonzero.  */
                   2941: 
                   2942: rtx
                   2943: gen_extend_insn (x, y, mto, mfrom, unsignedp)
                   2944:      rtx x, y;
                   2945:      enum machine_mode mto, mfrom;
                   2946:      int unsignedp;
                   2947: {
                   2948:   return (GEN_FCN (extendtab[(int) mto][(int) mfrom][unsignedp]) (x, y));
                   2949: }
                   2950: 
                   2951: /* can_fix_p and can_float_p say whether the target machine
                   2952:    can directly convert a given fixed point type to
                   2953:    a given floating point type, or vice versa.
                   2954:    The returned value is the CODE_FOR_... value to use,
                   2955:    or CODE_FOR_nothing if these modes cannot be directly converted.
                   2956: 
                   2957:    *TRUNCP_PTR is set to 1 if it is necessary to output
                   2958:    an explicit FTRUNC insn before the fix insn; otherwise 0.  */
                   2959: 
                   2960: static enum insn_code
                   2961: can_fix_p (fixmode, fltmode, unsignedp, truncp_ptr)
                   2962:      enum machine_mode fltmode, fixmode;
                   2963:      int unsignedp;
                   2964:      int *truncp_ptr;
                   2965: {
                   2966:   *truncp_ptr = 0;
                   2967:   if (fixtrunctab[(int) fltmode][(int) fixmode][unsignedp] != CODE_FOR_nothing)
                   2968:     return fixtrunctab[(int) fltmode][(int) fixmode][unsignedp];
                   2969: 
                   2970:   if (ftrunc_optab->handlers[(int) fltmode].insn_code != CODE_FOR_nothing)
                   2971:     {
                   2972:       *truncp_ptr = 1;
                   2973:       return fixtab[(int) fltmode][(int) fixmode][unsignedp];
                   2974:     }
                   2975:   return CODE_FOR_nothing;
                   2976: }
                   2977: 
                   2978: static enum insn_code
                   2979: can_float_p (fltmode, fixmode, unsignedp)
                   2980:      enum machine_mode fixmode, fltmode;
                   2981:      int unsignedp;
                   2982: {
                   2983:   return floattab[(int) fltmode][(int) fixmode][unsignedp];
                   2984: }
                   2985: 
                   2986: /* Generate code to convert FROM to floating point
                   2987:    and store in TO.  FROM must be fixed point and not VOIDmode.
                   2988:    UNSIGNEDP nonzero means regard FROM as unsigned.
                   2989:    Normally this is done by correcting the final value
                   2990:    if it is negative.  */
                   2991: 
                   2992: void
                   2993: expand_float (to, from, unsignedp)
                   2994:      rtx to, from;
                   2995:      int unsignedp;
                   2996: {
                   2997:   enum insn_code icode;
                   2998:   register rtx target = to;
                   2999:   enum machine_mode fmode, imode;
                   3000: 
                   3001:   /* Crash now, because we won't be able to decide which mode to use.  */
                   3002:   if (GET_MODE (from) == VOIDmode)
                   3003:     abort ();
                   3004: 
                   3005:   /* Look for an insn to do the conversion.  Do it in the specified
                   3006:      modes if possible; otherwise convert either input, output or both to
                   3007:      wider mode.  If the integer mode is wider than the mode of FROM,
                   3008:      we can do the conversion signed even if the input is unsigned.  */
                   3009: 
                   3010:   for (imode = GET_MODE (from); imode != VOIDmode;
                   3011:        imode = GET_MODE_WIDER_MODE (imode))
                   3012:     for (fmode = GET_MODE (to); fmode != VOIDmode;
                   3013:         fmode = GET_MODE_WIDER_MODE (fmode))
                   3014:       {
                   3015:        int doing_unsigned = unsignedp;
                   3016: 
                   3017:        icode = can_float_p (fmode, imode, unsignedp);
                   3018:        if (icode == CODE_FOR_nothing && imode != GET_MODE (from) && unsignedp)
                   3019:          icode = can_float_p (fmode, imode, 0), doing_unsigned = 0;
                   3020: 
                   3021:        if (icode != CODE_FOR_nothing)
                   3022:          {
                   3023:            to = protect_from_queue (to, 1);
                   3024:            from = protect_from_queue (from, 0);
                   3025: 
                   3026:            if (imode != GET_MODE (from))
                   3027:              from = convert_to_mode (imode, from, unsignedp);
                   3028: 
                   3029:            if (fmode != GET_MODE (to))
                   3030:              target = gen_reg_rtx (fmode);
                   3031: 
                   3032:            emit_unop_insn (icode, target, from,
                   3033:                            doing_unsigned ? UNSIGNED_FLOAT : FLOAT);
                   3034: 
                   3035:            if (target != to)
                   3036:              convert_move (to, target, 0);
                   3037:            return;
                   3038:          }
                   3039:     }
                   3040: 
                   3041: #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
                   3042: 
                   3043:   /* Unsigned integer, and no way to convert directly.
                   3044:      Convert as signed, then conditionally adjust the result.  */
                   3045:   if (unsignedp)
                   3046:     {
                   3047:       rtx label = gen_label_rtx ();
                   3048:       rtx temp;
                   3049:       REAL_VALUE_TYPE offset;
                   3050: 
                   3051:       emit_queue ();
                   3052: 
                   3053:       to = protect_from_queue (to, 1);
                   3054:       from = protect_from_queue (from, 0);
                   3055: 
                   3056:       if (flag_force_mem)
                   3057:        from = force_not_mem (from);
                   3058: 
                   3059:       /* Look for a usable floating mode FMODE wider than the source and at
                   3060:         least as wide as the target.  Using FMODE will avoid rounding woes
                   3061:         with unsigned values greater than the signed maximum value.  */
                   3062:       for (fmode = GET_MODE (to);  fmode != VOIDmode;
                   3063:           fmode = GET_MODE_WIDER_MODE (fmode))
                   3064:        if (GET_MODE_BITSIZE (GET_MODE (from)) < GET_MODE_BITSIZE (fmode)
                   3065:            && can_float_p (fmode, GET_MODE (from), 0) != CODE_FOR_nothing)
                   3066:          break;
                   3067:       if (fmode == VOIDmode)
                   3068:        {
                   3069:          /* There is no such mode.  Pretend the target is wide enough.
                   3070:             This may cause rounding problems, unfortunately.  */
                   3071:          fmode = GET_MODE (to);
                   3072:        }
                   3073: 
                   3074:       /* If we are about to do some arithmetic to correct for an
                   3075:         unsigned operand, do it in a pseudo-register.  */
                   3076: 
                   3077:       if (GET_MODE (to) != fmode
                   3078:          || GET_CODE (to) != REG || REGNO (to) <= LAST_VIRTUAL_REGISTER)
                   3079:        target = gen_reg_rtx (fmode);
                   3080: 
                   3081:       /* Convert as signed integer to floating.  */
                   3082:       expand_float (target, from, 0);
                   3083: 
                   3084:       /* If FROM is negative (and therefore TO is negative),
                   3085:         correct its value by 2**bitwidth.  */
                   3086: 
                   3087:       do_pending_stack_adjust ();
                   3088:       emit_cmp_insn (from, const0_rtx, GE, NULL_RTX, GET_MODE (from), 0, 0);
                   3089:       emit_jump_insn (gen_bge (label));
                   3090:       /* On SCO 3.2.1, ldexp rejects values outside [0.5, 1).
                   3091:         Rather than setting up a dconst_dot_5, let's hope SCO
                   3092:         fixes the bug.  */
                   3093:       offset = REAL_VALUE_LDEXP (dconst1, GET_MODE_BITSIZE (GET_MODE (from)));
                   3094:       temp = expand_binop (fmode, add_optab, target,
                   3095:                           immed_real_const_1 (offset, fmode),
                   3096:                           target, 0, OPTAB_LIB_WIDEN);
                   3097:       if (temp != target)
                   3098:        emit_move_insn (target, temp);
                   3099:       do_pending_stack_adjust ();
                   3100:       emit_label (label);
                   3101:     }
                   3102:   else
                   3103: #endif
                   3104: 
                   3105:   /* No hardware instruction available; call a library rotine to convert from
                   3106:      SImode, DImode, or TImode into SFmode, DFmode, XFmode, or TFmode.  */
                   3107:     {
                   3108:       rtx libfcn;
                   3109:       rtx insns;
                   3110:       rtx value;
                   3111: 
                   3112:       to = protect_from_queue (to, 1);
                   3113:       from = protect_from_queue (from, 0);
                   3114: 
                   3115:       if (GET_MODE_SIZE (GET_MODE (from)) < GET_MODE_SIZE (SImode))
                   3116:        from = convert_to_mode (SImode, from, unsignedp);
                   3117: 
                   3118:       if (flag_force_mem)
                   3119:        from = force_not_mem (from);
                   3120: 
                   3121:       if (GET_MODE (to) == SFmode)
                   3122:        {
                   3123:          if (GET_MODE (from) == SImode)
                   3124:            libfcn = floatsisf_libfunc;
                   3125:          else if (GET_MODE (from) == DImode)
                   3126:            libfcn = floatdisf_libfunc;
                   3127:          else if (GET_MODE (from) == TImode)
                   3128:            libfcn = floattisf_libfunc;
                   3129:          else
                   3130:            abort ();
                   3131:        }
                   3132:       else if (GET_MODE (to) == DFmode)
                   3133:        {
                   3134:          if (GET_MODE (from) == SImode)
                   3135:            libfcn = floatsidf_libfunc;
                   3136:          else if (GET_MODE (from) == DImode)
                   3137:            libfcn = floatdidf_libfunc;
                   3138:          else if (GET_MODE (from) == TImode)
                   3139:            libfcn = floattidf_libfunc;
                   3140:          else
                   3141:            abort ();
                   3142:        }
                   3143:       else if (GET_MODE (to) == XFmode)
                   3144:        {
                   3145:          if (GET_MODE (from) == SImode)
                   3146:            libfcn = floatsixf_libfunc;
                   3147:          else if (GET_MODE (from) == DImode)
                   3148:            libfcn = floatdixf_libfunc;
                   3149:          else if (GET_MODE (from) == TImode)
                   3150:            libfcn = floattixf_libfunc;
                   3151:          else
                   3152:            abort ();
                   3153:        }
                   3154:       else if (GET_MODE (to) == TFmode)
                   3155:        {
                   3156:          if (GET_MODE (from) == SImode)
                   3157:            libfcn = floatsitf_libfunc;
                   3158:          else if (GET_MODE (from) == DImode)
                   3159:            libfcn = floatditf_libfunc;
                   3160:          else if (GET_MODE (from) == TImode)
                   3161:            libfcn = floattitf_libfunc;
                   3162:          else
                   3163:            abort ();
                   3164:        }
                   3165:       else
                   3166:        abort ();
                   3167: 
                   3168:       start_sequence ();
                   3169: 
                   3170:       value = emit_library_call_value (libfcn, NULL_RTX, 1,
                   3171:                                       GET_MODE (to),
                   3172:                                       1, from, GET_MODE (from));
                   3173:       insns = get_insns ();
                   3174:       end_sequence ();
                   3175: 
                   3176:       emit_libcall_block (insns, target, value,
                   3177:                          gen_rtx (FLOAT, GET_MODE (to), from));
                   3178:     }
                   3179: 
                   3180:   /* Copy result to requested destination
                   3181:      if we have been computing in a temp location.  */
                   3182: 
                   3183:   if (target != to)
                   3184:     {
                   3185:       if (GET_MODE (target) == GET_MODE (to))
                   3186:        emit_move_insn (to, target);
                   3187:       else
                   3188:        convert_move (to, target, 0);
                   3189:     }
                   3190: }
                   3191: 
                   3192: /* expand_fix: generate code to convert FROM to fixed point
                   3193:    and store in TO.  FROM must be floating point.  */
                   3194: 
                   3195: static rtx
                   3196: ftruncify (x)
                   3197:      rtx x;
                   3198: {
                   3199:   rtx temp = gen_reg_rtx (GET_MODE (x));
                   3200:   return expand_unop (GET_MODE (x), ftrunc_optab, x, temp, 0);
                   3201: }
                   3202: 
                   3203: void
                   3204: expand_fix (to, from, unsignedp)
                   3205:      register rtx to, from;
                   3206:      int unsignedp;
                   3207: {
                   3208:   enum insn_code icode;
                   3209:   register rtx target = to;
                   3210:   enum machine_mode fmode, imode;
                   3211:   int must_trunc = 0;
                   3212:   rtx libfcn = 0;
                   3213: 
                   3214:   /* We first try to find a pair of modes, one real and one integer, at
                   3215:      least as wide as FROM and TO, respectively, in which we can open-code
                   3216:      this conversion.  If the integer mode is wider than the mode of TO,
                   3217:      we can do the conversion either signed or unsigned.  */
                   3218: 
                   3219:   for (imode = GET_MODE (to); imode != VOIDmode;
                   3220:        imode = GET_MODE_WIDER_MODE (imode))
                   3221:     for (fmode = GET_MODE (from); fmode != VOIDmode;
                   3222:         fmode = GET_MODE_WIDER_MODE (fmode))
                   3223:       {
                   3224:        int doing_unsigned = unsignedp;
                   3225: 
                   3226:        icode = can_fix_p (imode, fmode, unsignedp, &must_trunc);
                   3227:        if (icode == CODE_FOR_nothing && imode != GET_MODE (to) && unsignedp)
                   3228:          icode = can_fix_p (imode, fmode, 0, &must_trunc), doing_unsigned = 0;
                   3229: 
                   3230:        if (icode != CODE_FOR_nothing)
                   3231:          {
                   3232:            to = protect_from_queue (to, 1);
                   3233:            from = protect_from_queue (from, 0);
                   3234: 
                   3235:            if (fmode != GET_MODE (from))
                   3236:              from = convert_to_mode (fmode, from, 0);
                   3237: 
                   3238:            if (must_trunc)
                   3239:              from = ftruncify (from);
                   3240: 
                   3241:            if (imode != GET_MODE (to))
                   3242:              target = gen_reg_rtx (imode);
                   3243: 
                   3244:            emit_unop_insn (icode, target, from,
                   3245:                            doing_unsigned ? UNSIGNED_FIX : FIX);
                   3246:            if (target != to)
                   3247:              convert_move (to, target, unsignedp);
                   3248:            return;
                   3249:          }
                   3250:       }
                   3251: 
                   3252: #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
                   3253:   /* For an unsigned conversion, there is one more way to do it.
                   3254:      If we have a signed conversion, we generate code that compares
                   3255:      the real value to the largest representable positive number.  If if
                   3256:      is smaller, the conversion is done normally.  Otherwise, subtract
                   3257:      one plus the highest signed number, convert, and add it back.
                   3258: 
                   3259:      We only need to check all real modes, since we know we didn't find
                   3260:      anything with a wider integer mode.  */
                   3261: 
                   3262:   if (unsignedp && GET_MODE_BITSIZE (GET_MODE (to)) <= HOST_BITS_PER_WIDE_INT)
                   3263:     for (fmode = GET_MODE (from); fmode != VOIDmode;
                   3264:         fmode = GET_MODE_WIDER_MODE (fmode))
                   3265:       /* Make sure we won't lose significant bits doing this.  */
                   3266:       if (GET_MODE_BITSIZE (fmode) > GET_MODE_BITSIZE (GET_MODE (to))
                   3267:          && CODE_FOR_nothing != can_fix_p (GET_MODE (to), fmode, 0,
                   3268:                                            &must_trunc))
                   3269:        {
                   3270:          int bitsize;
                   3271:          REAL_VALUE_TYPE offset;
                   3272:          rtx limit, lab1, lab2, insn;
                   3273: 
                   3274:          bitsize = GET_MODE_BITSIZE (GET_MODE (to));
                   3275:          offset = REAL_VALUE_LDEXP (dconst1, bitsize - 1);
                   3276:          limit = immed_real_const_1 (offset, fmode);
                   3277:          lab1 = gen_label_rtx ();
                   3278:          lab2 = gen_label_rtx ();
                   3279: 
                   3280:          emit_queue ();
                   3281:          to = protect_from_queue (to, 1);
                   3282:          from = protect_from_queue (from, 0);
                   3283: 
                   3284:          if (flag_force_mem)
                   3285:            from = force_not_mem (from);
                   3286: 
                   3287:          if (fmode != GET_MODE (from))
                   3288:            from = convert_to_mode (fmode, from, 0);
                   3289: 
                   3290:          /* See if we need to do the subtraction.  */
                   3291:          do_pending_stack_adjust ();
                   3292:          emit_cmp_insn (from, limit, GE, NULL_RTX, GET_MODE (from), 0, 0);
                   3293:          emit_jump_insn (gen_bge (lab1));
                   3294: 
                   3295:          /* If not, do the signed "fix" and branch around fixup code.  */
                   3296:          expand_fix (to, from, 0);
                   3297:          emit_jump_insn (gen_jump (lab2));
                   3298:          emit_barrier ();
                   3299: 
                   3300:          /* Otherwise, subtract 2**(N-1), convert to signed number,
                   3301:             then add 2**(N-1).  Do the addition using XOR since this
                   3302:             will often generate better code.  */
                   3303:          emit_label (lab1);
                   3304:          target = expand_binop (GET_MODE (from), sub_optab, from, limit,
                   3305:                                 NULL_RTX, 0, OPTAB_LIB_WIDEN);
                   3306:          expand_fix (to, target, 0);
                   3307:          target = expand_binop (GET_MODE (to), xor_optab, to,
                   3308:                                 GEN_INT ((HOST_WIDE_INT) 1 << (bitsize - 1)),
                   3309:                                 to, 1, OPTAB_LIB_WIDEN);
                   3310: 
                   3311:          if (target != to)
                   3312:            emit_move_insn (to, target);
                   3313: 
                   3314:          emit_label (lab2);
                   3315: 
                   3316:          /* Make a place for a REG_NOTE and add it.  */
                   3317:          insn = emit_move_insn (to, to);
                   3318:          REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL,
                   3319:                                      gen_rtx (UNSIGNED_FIX, GET_MODE (to),
                   3320:                                               copy_rtx (from)),
                   3321:                                      REG_NOTES (insn));
                   3322: 
                   3323:          return;
                   3324:        }
                   3325: #endif
                   3326: 
                   3327:   /* We can't do it with an insn, so use a library call.  But first ensure
                   3328:      that the mode of TO is at least as wide as SImode, since those are the
                   3329:      only library calls we know about.  */
                   3330: 
                   3331:   if (GET_MODE_SIZE (GET_MODE (to)) < GET_MODE_SIZE (SImode))
                   3332:     {
                   3333:       target = gen_reg_rtx (SImode);
                   3334: 
                   3335:       expand_fix (target, from, unsignedp);
                   3336:     }
                   3337:   else if (GET_MODE (from) == SFmode)
                   3338:     {
                   3339:       if (GET_MODE (to) == SImode)
                   3340:        libfcn = unsignedp ? fixunssfsi_libfunc : fixsfsi_libfunc;
                   3341:       else if (GET_MODE (to) == DImode)
                   3342:        libfcn = unsignedp ? fixunssfdi_libfunc : fixsfdi_libfunc;
                   3343:       else if (GET_MODE (to) == TImode)
                   3344:        libfcn = unsignedp ? fixunssfti_libfunc : fixsfti_libfunc;
                   3345:       else
                   3346:        abort ();
                   3347:     }
                   3348:   else if (GET_MODE (from) == DFmode)
                   3349:     {
                   3350:       if (GET_MODE (to) == SImode)
                   3351:        libfcn = unsignedp ? fixunsdfsi_libfunc : fixdfsi_libfunc;
                   3352:       else if (GET_MODE (to) == DImode)
                   3353:        libfcn = unsignedp ? fixunsdfdi_libfunc : fixdfdi_libfunc;
                   3354:       else if (GET_MODE (to) == TImode)
                   3355:        libfcn = unsignedp ? fixunsdfti_libfunc : fixdfti_libfunc;
                   3356:       else
                   3357:        abort ();
                   3358:     }
                   3359:   else if (GET_MODE (from) == XFmode)
                   3360:     {
                   3361:       if (GET_MODE (to) == SImode)
                   3362:        libfcn = unsignedp ? fixunsxfsi_libfunc : fixxfsi_libfunc;
                   3363:       else if (GET_MODE (to) == DImode)
                   3364:        libfcn = unsignedp ? fixunsxfdi_libfunc : fixxfdi_libfunc;
                   3365:       else if (GET_MODE (to) == TImode)
                   3366:        libfcn = unsignedp ? fixunsxfti_libfunc : fixxfti_libfunc;
                   3367:       else
                   3368:        abort ();
                   3369:     }
                   3370:   else if (GET_MODE (from) == TFmode)
                   3371:     {
                   3372:       if (GET_MODE (to) == SImode)
                   3373:        libfcn = unsignedp ? fixunstfsi_libfunc : fixtfsi_libfunc;
                   3374:       else if (GET_MODE (to) == DImode)
                   3375:        libfcn = unsignedp ? fixunstfdi_libfunc : fixtfdi_libfunc;
                   3376:       else if (GET_MODE (to) == TImode)
                   3377:        libfcn = unsignedp ? fixunstfti_libfunc : fixtfti_libfunc;
                   3378:       else
                   3379:        abort ();
                   3380:     }
                   3381:   else
                   3382:     abort ();
                   3383: 
                   3384:   if (libfcn)
                   3385:     {
                   3386:       rtx insns;
                   3387: 
                   3388:       to = protect_from_queue (to, 1);
                   3389:       from = protect_from_queue (from, 0);
                   3390: 
                   3391:       if (flag_force_mem)
                   3392:        from = force_not_mem (from);
                   3393: 
                   3394:       start_sequence ();
                   3395: 
                   3396:       emit_library_call (libfcn, 1, GET_MODE (to), 1, from, GET_MODE (from));
                   3397:       insns = get_insns ();
                   3398:       end_sequence ();
                   3399: 
                   3400:       emit_libcall_block (insns, target, hard_libcall_value (GET_MODE (to)),
                   3401:                          gen_rtx (unsignedp ? FIX : UNSIGNED_FIX,
                   3402:                                   GET_MODE (to), from));
                   3403:     }
                   3404:       
                   3405:   if (GET_MODE (to) == GET_MODE (target))
                   3406:     emit_move_insn (to, target);
                   3407:   else
                   3408:     convert_move (to, target, 0);
                   3409: }
                   3410: 
                   3411: static optab
                   3412: init_optab (code)
                   3413:      enum rtx_code code;
                   3414: {
                   3415:   int i;
                   3416:   optab op = (optab) xmalloc (sizeof (struct optab));
                   3417:   op->code = code;
                   3418:   for (i = 0; i < NUM_MACHINE_MODES; i++)
                   3419:     {
                   3420:       op->handlers[i].insn_code = CODE_FOR_nothing;
                   3421:       op->handlers[i].libfunc = 0;
                   3422:     }
                   3423: 
                   3424:   if (code != UNKNOWN)
                   3425:     code_to_optab[(int) code] = op;
                   3426: 
                   3427:   return op;
                   3428: }
                   3429: 
                   3430: /* Initialize the libfunc fields of an entire group of entries in some
                   3431:    optab.  Each entry is set equal to a string consisting of a leading
                   3432:    pair of underscores followed by a generic operation name followed by
                   3433:    a mode name (downshifted to lower case) followed by a single character
                   3434:    representing the number of operands for the given operation (which is
                   3435:    usually one of the characters '2', '3', or '4').
                   3436: 
                   3437:    OPTABLE is the table in which libfunc fields are to be initialized.
                   3438:    FIRST_MODE is the first machine mode index in the given optab to
                   3439:      initialize.
                   3440:    LAST_MODE is the last machine mode index in the given optab to
                   3441:      initialize.
                   3442:    OPNAME is the generic (string) name of the operation.
                   3443:    SUFFIX is the character which specifies the number of operands for
                   3444:      the given generic operation.
                   3445: */
                   3446: 
                   3447: static void
                   3448: init_libfuncs (optable, first_mode, last_mode, opname, suffix)
                   3449:     register optab optable;
                   3450:     register int first_mode;
                   3451:     register int last_mode;
                   3452:     register char *opname;
                   3453:     register char suffix;
                   3454: {
                   3455:   register int mode;
                   3456:   register unsigned opname_len = strlen (opname);
                   3457: 
                   3458:   for (mode = first_mode; (int) mode <= (int) last_mode;
                   3459:        mode = (enum machine_mode) ((int) mode + 1))
                   3460:     {
                   3461:       register char *mname = mode_name[(int) mode];
                   3462:       register unsigned mname_len = strlen (mname);
                   3463:       register char *libfunc_name
                   3464:        = (char *) xmalloc (2 + opname_len + mname_len + 1 + 1);
                   3465:       register char *p;
                   3466:       register char *q;
                   3467: 
                   3468:       p = libfunc_name;
                   3469: #ifndef NEXT_LIBGCC_NAMES
                   3470:       *p++ = '_';
                   3471: #endif
                   3472:       *p++ = '_';
                   3473:       for (q = opname; *q; )
                   3474:        *p++ = *q++;
                   3475:       for (q = mname; *q; q++)
                   3476:        *p++ = tolower (*q);
                   3477:       *p++ = suffix;
                   3478:       *p++ = '\0';
                   3479:       optable->handlers[(int) mode].libfunc
                   3480:        = gen_rtx (SYMBOL_REF, Pmode, libfunc_name);
                   3481:     }
                   3482: }
                   3483: 
                   3484: /* Initialize the libfunc fields of an entire group of entries in some
                   3485:    optab which correspond to all integer mode operations.  The parameters
                   3486:    have the same meaning as similarly named ones for the `init_libfuncs'
                   3487:    routine.  (See above).  */
                   3488: 
                   3489: static void
                   3490: init_integral_libfuncs (optable, opname, suffix)
                   3491:     register optab optable;
                   3492:     register char *opname;
                   3493:     register char suffix;
                   3494: {
                   3495:   init_libfuncs (optable, SImode, TImode, opname, suffix);
                   3496: }
                   3497: 
                   3498: /* Initialize the libfunc fields of an entire group of entries in some
                   3499:    optab which correspond to all real mode operations.  The parameters
                   3500:    have the same meaning as similarly named ones for the `init_libfuncs'
                   3501:    routine.  (See above).  */
                   3502: 
                   3503: static void
                   3504: init_floating_libfuncs (optable, opname, suffix)
                   3505:     register optab optable;
                   3506:     register char *opname;
                   3507:     register char suffix;
                   3508: {
                   3509:   init_libfuncs (optable, SFmode, TFmode, opname, suffix);
                   3510: }
                   3511: 
                   3512: /* Initialize the libfunc fields of an entire group of entries in some
                   3513:    optab which correspond to all complex floating modes.  The parameters
                   3514:    have the same meaning as similarly named ones for the `init_libfuncs'
                   3515:    routine.  (See above).  */
                   3516: 
                   3517: static void
                   3518: init_complex_libfuncs (optable, opname, suffix)
                   3519:     register optab optable;
                   3520:     register char *opname;
                   3521:     register char suffix;
                   3522: {
                   3523:   init_libfuncs (optable, SCmode, TCmode, opname, suffix);
                   3524: }
                   3525: 
                   3526: /* Call this once to initialize the contents of the optabs
                   3527:    appropriately for the current target machine.  */
                   3528: 
                   3529: void
                   3530: init_optabs ()
                   3531: {
                   3532:   int i, j;
                   3533:   enum insn_code *p;
                   3534: 
                   3535:   /* Start by initializing all tables to contain CODE_FOR_nothing.  */
                   3536: 
                   3537:   for (p = fixtab[0][0];
                   3538:        p < fixtab[0][0] + sizeof fixtab / sizeof (fixtab[0][0][0]); 
                   3539:        p++)
                   3540:     *p = CODE_FOR_nothing;
                   3541: 
                   3542:   for (p = fixtrunctab[0][0];
                   3543:        p < fixtrunctab[0][0] + sizeof fixtrunctab / sizeof (fixtrunctab[0][0][0]); 
                   3544:        p++)
                   3545:     *p = CODE_FOR_nothing;
                   3546: 
                   3547:   for (p = floattab[0][0];
                   3548:        p < floattab[0][0] + sizeof floattab / sizeof (floattab[0][0][0]); 
                   3549:        p++)
                   3550:     *p = CODE_FOR_nothing;
                   3551: 
                   3552:   for (p = extendtab[0][0];
                   3553:        p < extendtab[0][0] + sizeof extendtab / sizeof extendtab[0][0][0];
                   3554:        p++)
                   3555:     *p = CODE_FOR_nothing;
                   3556: 
                   3557:   for (i = 0; i < NUM_RTX_CODE; i++)
                   3558:     setcc_gen_code[i] = CODE_FOR_nothing;
                   3559: 
                   3560:   add_optab = init_optab (PLUS);
                   3561:   sub_optab = init_optab (MINUS);
                   3562:   smul_optab = init_optab (MULT);
                   3563:   smul_widen_optab = init_optab (UNKNOWN);
                   3564:   umul_widen_optab = init_optab (UNKNOWN);
                   3565:   sdiv_optab = init_optab (DIV);
                   3566:   sdivmod_optab = init_optab (UNKNOWN);
                   3567:   udiv_optab = init_optab (UDIV);
                   3568:   udivmod_optab = init_optab (UNKNOWN);
                   3569:   smod_optab = init_optab (MOD);
                   3570:   umod_optab = init_optab (UMOD);
                   3571:   flodiv_optab = init_optab (DIV);
                   3572:   ftrunc_optab = init_optab (UNKNOWN);
                   3573:   and_optab = init_optab (AND);
                   3574:   ior_optab = init_optab (IOR);
                   3575:   xor_optab = init_optab (XOR);
                   3576:   ashl_optab = init_optab (ASHIFT);
                   3577:   ashr_optab = init_optab (ASHIFTRT);
                   3578:   lshl_optab = init_optab (LSHIFT);
                   3579:   lshr_optab = init_optab (LSHIFTRT);
                   3580:   rotl_optab = init_optab (ROTATE);
                   3581:   rotr_optab = init_optab (ROTATERT);
                   3582:   smin_optab = init_optab (SMIN);
                   3583:   smax_optab = init_optab (SMAX);
                   3584:   umin_optab = init_optab (UMIN);
                   3585:   umax_optab = init_optab (UMAX);
                   3586:   mov_optab = init_optab (UNKNOWN);
                   3587:   movstrict_optab = init_optab (UNKNOWN);
                   3588:   cmp_optab = init_optab (UNKNOWN);
                   3589:   ucmp_optab = init_optab (UNKNOWN);
                   3590:   tst_optab = init_optab (UNKNOWN);
                   3591:   neg_optab = init_optab (NEG);
                   3592:   abs_optab = init_optab (ABS);
                   3593:   one_cmpl_optab = init_optab (NOT);
                   3594:   ffs_optab = init_optab (FFS);
                   3595:   sqrt_optab = init_optab (SQRT);
                   3596:   sin_optab = init_optab (UNKNOWN);
                   3597:   cos_optab = init_optab (UNKNOWN);
                   3598:   strlen_optab = init_optab (UNKNOWN);
                   3599: 
                   3600:   for (i = 0; i < NUM_MACHINE_MODES; i++)
                   3601:     {
                   3602:       movstr_optab[i] = CODE_FOR_nothing;
                   3603: 
                   3604: #ifdef HAVE_SECONDARY_RELOADS
                   3605:       reload_in_optab[i] = reload_out_optab[i] = CODE_FOR_nothing;
                   3606: #endif
                   3607:     }
                   3608: 
                   3609:   /* Fill in the optabs with the insns we support.  */
                   3610:   init_all_optabs ();
                   3611: 
                   3612: #ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC
                   3613:   /* This flag says the same insns that convert to a signed fixnum
                   3614:      also convert validly to an unsigned one.  */
                   3615:   for (i = 0; i < NUM_MACHINE_MODES; i++)
                   3616:     for (j = 0; j < NUM_MACHINE_MODES; j++)
                   3617:       fixtrunctab[i][j][1] = fixtrunctab[i][j][0];
                   3618: #endif
                   3619: 
                   3620: #ifdef EXTRA_CC_MODES
                   3621:   init_mov_optab ();
                   3622: #endif
                   3623: 
                   3624:   /* Initialize the optabs with the names of the library functions.  */
                   3625:   init_integral_libfuncs (add_optab, "add", '3');
                   3626:   init_floating_libfuncs (add_optab, "add", '3');
                   3627:   init_integral_libfuncs (sub_optab, "sub", '3');
                   3628:   init_floating_libfuncs (sub_optab, "sub", '3');
                   3629:   init_integral_libfuncs (smul_optab, "mul", '3');
                   3630:   init_floating_libfuncs (smul_optab, "mul", '3');
                   3631:   init_integral_libfuncs (sdiv_optab, "div", '3');
                   3632:   init_integral_libfuncs (udiv_optab, "udiv", '3');
                   3633:   init_integral_libfuncs (sdivmod_optab, "divmod", '4');
                   3634:   init_integral_libfuncs (udivmod_optab, "udivmod", '4');
                   3635:   init_integral_libfuncs (smod_optab, "mod", '3');
                   3636:   init_integral_libfuncs (umod_optab, "umod", '3');
                   3637:   init_floating_libfuncs (flodiv_optab, "div", '3');
                   3638:   init_floating_libfuncs (ftrunc_optab, "ftrunc", '2');
                   3639:   init_integral_libfuncs (and_optab, "and", '3');
                   3640:   init_integral_libfuncs (ior_optab, "ior", '3');
                   3641:   init_integral_libfuncs (xor_optab, "xor", '3');
                   3642:   init_integral_libfuncs (ashl_optab, "ashl", '3');
                   3643:   init_integral_libfuncs (ashr_optab, "ashr", '3');
                   3644:   init_integral_libfuncs (lshl_optab, "lshl", '3');
                   3645:   init_integral_libfuncs (lshr_optab, "lshr", '3');
                   3646:   init_integral_libfuncs (rotl_optab, "rotl", '3');
                   3647:   init_integral_libfuncs (rotr_optab, "rotr", '3');
                   3648:   init_integral_libfuncs (smin_optab, "min", '3');
                   3649:   init_floating_libfuncs (smin_optab, "min", '3');
                   3650:   init_integral_libfuncs (smax_optab, "max", '3');
                   3651:   init_floating_libfuncs (smax_optab, "max", '3');
                   3652:   init_integral_libfuncs (umin_optab, "umin", '3');
                   3653:   init_integral_libfuncs (umax_optab, "umax", '3');
                   3654:   init_integral_libfuncs (neg_optab, "neg", '2');
                   3655:   init_floating_libfuncs (neg_optab, "neg", '2');
                   3656:   init_integral_libfuncs (one_cmpl_optab, "one_cmpl", '2');
                   3657:   init_integral_libfuncs (ffs_optab, "ffs", '2');
                   3658: 
                   3659:   /* Comparison libcalls for integers MUST come in pairs, signed/unsigned.  */
                   3660:   init_integral_libfuncs (cmp_optab, "cmp", '2');
                   3661:   init_integral_libfuncs (ucmp_optab, "ucmp", '2');
                   3662:   init_floating_libfuncs (cmp_optab, "cmp", '2');
                   3663: 
                   3664: #ifdef MULSI3_LIBCALL
                   3665:   smul_optab->handlers[(int) SImode].libfunc
                   3666:     = gen_rtx (SYMBOL_REF, Pmode, MULSI3_LIBCALL);
                   3667: #endif
                   3668: #ifdef MULDI3_LIBCALL
                   3669:   smul_optab->handlers[(int) DImode].libfunc
                   3670:     = gen_rtx (SYMBOL_REF, Pmode, MULDI3_LIBCALL);
                   3671: #endif
                   3672: #ifdef MULTI3_LIBCALL
                   3673:   smul_optab->handlers[(int) TImode].libfunc
                   3674:     = gen_rtx (SYMBOL_REF, Pmode, MULTI3_LIBCALL);
                   3675: #endif
                   3676: 
                   3677: #ifdef DIVSI3_LIBCALL
                   3678:   sdiv_optab->handlers[(int) SImode].libfunc
                   3679:     = gen_rtx (SYMBOL_REF, Pmode, DIVSI3_LIBCALL);
                   3680: #endif
                   3681: #ifdef DIVDI3_LIBCALL
                   3682:   sdiv_optab->handlers[(int) DImode].libfunc
                   3683:     = gen_rtx (SYMBOL_REF, Pmode, DIVDI3_LIBCALL);
                   3684: #endif
                   3685: #ifdef DIVTI3_LIBCALL
                   3686:   sdiv_optab->handlers[(int) TImode].libfunc
                   3687:     = gen_rtx (SYMBOL_REF, Pmode, DIVTI3_LIBCALL);
                   3688: #endif
                   3689: 
                   3690: #ifdef UDIVSI3_LIBCALL
                   3691:   udiv_optab->handlers[(int) SImode].libfunc
                   3692:     = gen_rtx (SYMBOL_REF, Pmode, UDIVSI3_LIBCALL);
                   3693: #endif
                   3694: #ifdef UDIVDI3_LIBCALL
                   3695:   udiv_optab->handlers[(int) DImode].libfunc
                   3696:     = gen_rtx (SYMBOL_REF, Pmode, UDIVDI3_LIBCALL);
                   3697: #endif
                   3698: #ifdef UDIVTI3_LIBCALL
                   3699:   udiv_optab->handlers[(int) TImode].libfunc
                   3700:     = gen_rtx (SYMBOL_REF, Pmode, UDIVTI3_LIBCALL);
                   3701: #endif
                   3702: 
                   3703: 
                   3704: #ifdef MODSI3_LIBCALL
                   3705:   smod_optab->handlers[(int) SImode].libfunc
                   3706:     = gen_rtx (SYMBOL_REF, Pmode, MODSI3_LIBCALL);
                   3707: #endif
                   3708: #ifdef MODDI3_LIBCALL
                   3709:   smod_optab->handlers[(int) DImode].libfunc
                   3710:     = gen_rtx (SYMBOL_REF, Pmode, MODDI3_LIBCALL);
                   3711: #endif
                   3712: #ifdef MODTI3_LIBCALL
                   3713:   smod_optab->handlers[(int) TImode].libfunc
                   3714:     = gen_rtx (SYMBOL_REF, Pmode, MODTI3_LIBCALL);
                   3715: #endif
                   3716: 
                   3717: 
                   3718: #ifdef UMODSI3_LIBCALL
                   3719:   umod_optab->handlers[(int) SImode].libfunc
                   3720:     = gen_rtx (SYMBOL_REF, Pmode, UMODSI3_LIBCALL);
                   3721: #endif
                   3722: #ifdef UMODDI3_LIBCALL
                   3723:   umod_optab->handlers[(int) DImode].libfunc
                   3724:     = gen_rtx (SYMBOL_REF, Pmode, UMODDI3_LIBCALL);
                   3725: #endif
                   3726: #ifdef UMODTI3_LIBCALL
                   3727:   umod_optab->handlers[(int) TImode].libfunc
                   3728:     = gen_rtx (SYMBOL_REF, Pmode, UMODTI3_LIBCALL);
                   3729: #endif
                   3730: 
                   3731:   /* Use cabs for DC complex abs, since systems generally have cabs.
                   3732:      Don't define any libcall for SCmode, so that cabs will be used.  */
                   3733:   abs_optab->handlers[(int) DCmode].libfunc
                   3734:     = gen_rtx (SYMBOL_REF, Pmode, "cabs");
                   3735: 
                   3736:   /* The ffs function operates on `int'.  */
                   3737: #ifndef INT_TYPE_SIZE
                   3738: #define INT_TYPE_SIZE BITS_PER_WORD
                   3739: #endif
                   3740:   ffs_optab->handlers[(int) mode_for_size (INT_TYPE_SIZE, MODE_INT, 0)] .libfunc
                   3741:     = gen_rtx (SYMBOL_REF, Pmode, "ffs");
                   3742: 
                   3743: #ifndef NEXT_LIBGCC_NAMES
                   3744:   extendsfdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extendsfdf2");
                   3745:   extendsfxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extendsfxf2");
                   3746:   extendsftf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extendsftf2");
                   3747:   extenddfxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extenddfxf2");
                   3748:   extenddftf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extenddftf2");
                   3749: #else NEXT_LIBGCC_NAMES
                   3750:   extendsfdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_extendsfdf2");
                   3751:   extendsfxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_extendsfxf2");
                   3752:   extendsftf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_extendsftf2");
                   3753:   extenddfxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_extenddfxf2");
                   3754:   extenddftf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_extenddftf2");
                   3755: #endif NEXT_LIBGCC_NAMES
                   3756: 
                   3757: #ifndef NEXT_LIBGCC_NAMES
                   3758:   truncdfsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__truncdfsf2");
                   3759:   truncxfsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__truncxfsf2");
                   3760:   trunctfsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__trunctfsf2");
                   3761:   truncxfdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__truncxfdf2");
                   3762:   trunctfdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__trunctfdf2");
                   3763: #else NEXT_LIBGCC_NAMES
                   3764:   truncdfsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_truncdfsf2");
                   3765:   truncxfsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_truncxfsf2");
                   3766:   trunctfsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_trunctfsf2");
                   3767:   truncxfdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_truncxfdf2");
                   3768:   trunctfdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_trunctfdf2");
                   3769: #endif NEXT_LIBGCC_NAMES
                   3770: 
                   3771:   memcpy_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memcpy");
                   3772:   bcopy_libfunc = gen_rtx (SYMBOL_REF, Pmode, "bcopy");
                   3773:   memcmp_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memcmp");
                   3774: #ifndef NEXT_LIBGCC_NAMES
                   3775:   bcmp_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gcc_bcmp");
                   3776: #else NEXT_LIBGCC_NAMES
                   3777:   bcmp_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_gcc_bcmp");
                   3778: #endif NEXT_LIBGCC_NAMES
                   3779:   memset_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memset");
                   3780:   bzero_libfunc = gen_rtx (SYMBOL_REF, Pmode, "bzero");
                   3781: 
                   3782: #ifndef NEXT_LIBGCC_NAMES
                   3783:   eqsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqsf2");
                   3784:   nesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nesf2");
                   3785:   gtsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gtsf2");
                   3786:   gesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gesf2");
                   3787:   ltsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ltsf2");
                   3788:   lesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__lesf2");
                   3789: #else NEXT_LIBGCC_NAMES
                   3790:   eqsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_eqsf2");
                   3791:   nesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_nesf2");
                   3792:   gtsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_gtsf2");
                   3793:   gesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_gesf2");
                   3794:   ltsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_ltsf2");
                   3795:   lesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_lesf2");
                   3796: #endif NEXT_LIBGCC_NAMES
                   3797: 
                   3798: #ifndef NEXT_LIBGCC_NAMES
                   3799:   eqdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqdf2");
                   3800:   nedf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nedf2");
                   3801:   gtdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gtdf2");
                   3802:   gedf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gedf2");
                   3803:   ltdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ltdf2");
                   3804:   ledf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ledf2");
                   3805: #else NEXT_LIBGCC_NAMES
                   3806:   eqdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_eqdf2");
                   3807:   nedf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_nedf2");
                   3808:   gtdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_gtdf2");
                   3809:   gedf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_gedf2");
                   3810:   ltdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_ltdf2");
                   3811:   ledf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_ledf2");
                   3812: #endif NEXT_LIBGCC_NAMES
                   3813: 
                   3814: #ifndef NEXT_LIBGCC_NAMES
                   3815:   eqxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqxf2");
                   3816:   nexf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nexf2");
                   3817:   gtxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gtxf2");
                   3818:   gexf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gexf2");
                   3819:   ltxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ltxf2");
                   3820:   lexf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__lexf2");
                   3821: #else NEXT_LIBGCC_NAMES
                   3822:   eqxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_eqxf2");
                   3823:   nexf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_nexf2");
                   3824:   gtxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_gtxf2");
                   3825:   gexf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_gexf2");
                   3826:   ltxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_ltxf2");
                   3827:   lexf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_lexf2");
                   3828: #endif NEXT_LIBGCC_NAMES
                   3829: 
                   3830: #ifndef NEXT_LIBGCC_NAMES
                   3831:   eqtf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqtf2");
                   3832:   netf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__netf2");
                   3833:   gttf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gttf2");
                   3834:   getf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__getf2");
                   3835:   lttf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__lttf2");
                   3836:   letf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__letf2");
                   3837: #else NEXT_LIBGCC_NAMES
                   3838:   eqtf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_eqtf2");
                   3839:   netf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_netf2");
                   3840:   gttf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_gttf2");
                   3841:   getf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_getf2");
                   3842:   lttf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_lttf2");
                   3843:   letf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_letf2");
                   3844: #endif NEXT_LIBGCC_NAMES
                   3845: 
                   3846: #ifndef NEXT_LIBGCC_NAMES
                   3847:   floatsisf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsisf");
                   3848:   floatdisf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatdisf");
                   3849:   floattisf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floattisf");
                   3850: #else NEXT_LIBGCC_NAMES
                   3851:   floatsisf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_floatsisf");
                   3852:   floatdisf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_floatdisf");
                   3853:   floattisf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_floattisf");
                   3854: #endif NEXT_LIBGCC_NAMES
                   3855: 
                   3856: #ifndef NEXT_LIBGCC_NAMES
                   3857:   floatsidf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsidf");
                   3858:   floatdidf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatdidf");
                   3859:   floattidf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floattidf");
                   3860: #else NEXT_LIBGCC_NAMES
                   3861:   floatsidf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_floatsidf");
                   3862:   floatdidf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_floatdidf");
                   3863:   floattidf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_floattidf");
                   3864: #endif NEXT_LIBGCC_NAMES
                   3865: 
                   3866: #ifndef NEXT_LIBGCC_NAMES
                   3867:   floatsixf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsixf");
                   3868:   floatdixf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatdixf");
                   3869:   floattixf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floattixf");
                   3870: #else NEXT_LIBGCC_NAMES
                   3871:   floatsixf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_floatsixf");
                   3872:   floatdixf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_floatdixf");
                   3873:   floattixf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_floattixf");
                   3874: #endif NEXT_LIBGCC_NAMES
                   3875: 
                   3876: #ifndef NEXT_LIBGCC_NAMES
                   3877:   floatsitf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsitf");
                   3878:   floatditf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatditf");
                   3879:   floattitf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floattitf");
                   3880: #else NEXT_LIBGCC_NAMES
                   3881:   floatsitf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_floatsitf");
                   3882:   floatditf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_floatditf");
                   3883:   floattitf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_floattitf");
                   3884: #endif NEXT_LIBGCC_NAMES
                   3885: 
                   3886: #ifndef NEXT_LIBGCC_NAMES
                   3887:   fixsfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixsfsi");
                   3888:   fixsfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixsfdi");
                   3889:   fixsfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixsfti");
                   3890: #else NEXT_LIBGCC_NAMES
                   3891:   fixsfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_fixsfsi");
                   3892:   fixsfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_fixsfdi");
                   3893:   fixsfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_fixsfti");
                   3894: #endif NEXT_LIBGCC_NAMES
                   3895: 
                   3896: #ifndef NEXT_LIBGCC_NAMES
                   3897:   fixdfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixdfsi");
                   3898:   fixdfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixdfdi");
                   3899:   fixdfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixdfti");
                   3900: #else NEXT_LIBGCC_NAMES
                   3901:   fixdfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_fixdfsi");
                   3902:   fixdfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_fixdfdi");
                   3903:   fixdfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_fixdfti");
                   3904: #endif NEXT_LIBGCC_NAMES
                   3905: 
                   3906: #ifndef NEXT_LIBGCC_NAMES
                   3907:   fixxfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixxfsi");
                   3908:   fixxfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixxfdi");
                   3909:   fixxfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixxfti");
                   3910: #else NEXT_LIBGCC_NAMES
                   3911:   fixxfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_fixxfsi");
                   3912:   fixxfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_fixxfdi");
                   3913:   fixxfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_fixxfti");
                   3914: #endif NEXT_LIBGCC_NAMES
                   3915: 
                   3916: #ifndef NEXT_LIBGCC_NAMES
                   3917:   fixtfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixtfsi");
                   3918:   fixtfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixtfdi");
                   3919:   fixtfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixtfti");
                   3920: #else NEXT_LIBGCC_NAMES
                   3921:   fixtfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_fixtfsi");
                   3922:   fixtfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_fixtfdi");
                   3923:   fixtfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_fixtfti");
                   3924: #endif NEXT_LIBGCC_NAMES
                   3925: 
                   3926: #ifndef NEXT_LIBGCC_NAMES
                   3927:   fixunssfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunssfsi");
                   3928:   fixunssfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunssfdi");
                   3929:   fixunssfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunssfti");
                   3930: #else NEXT_LIBGCC_NAMES
                   3931:   fixunssfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_fixunssfsi");
                   3932:   fixunssfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_fixunssfdi");
                   3933:   fixunssfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_fixunssfti");
                   3934: #endif NEXT_LIBGCC_NAMES
                   3935: 
                   3936: #ifndef NEXT_LIBGCC_NAMES
                   3937:   fixunsdfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsdfsi");
                   3938:   fixunsdfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsdfdi");
                   3939:   fixunsdfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsdfti");
                   3940: #else NEXT_LIBGCC_NAMES
                   3941:   fixunsdfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_fixunsdfsi");
                   3942:   fixunsdfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_fixunsdfdi");
                   3943:   fixunsdfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_fixunsdfti");
                   3944: #endif NEXT_LIBGCC_NAMES
                   3945: 
                   3946: #ifndef NEXT_LIBGCC_NAMES
                   3947:   fixunsxfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsxfsi");
                   3948:   fixunsxfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsxfdi");
                   3949:   fixunsxfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsxfti");
                   3950: #else NEXT_LIBGCC_NAMES
                   3951:   fixunsxfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_fixunsxfsi");
                   3952:   fixunsxfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_fixunsxfdi");
                   3953:   fixunsxfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_fixunsxfti");
                   3954: #endif NEXT_LIBGCC_NAMES
                   3955: 
                   3956: #ifndef NEXT_LIBGCC_NAMES
                   3957:   fixunstfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunstfsi");
                   3958:   fixunstfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunstfdi");
                   3959:   fixunstfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunstfti");
                   3960: #else NEXT_LIBGCC_NAMES
                   3961:   fixunstfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_fixunstfsi");
                   3962:   fixunstfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_fixunstfdi");
                   3963:   fixunstfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "_fixunstfti");
                   3964: #endif NEXT_LIBGCC_NAMES
                   3965: }
                   3966: 
                   3967: #ifdef BROKEN_LDEXP
                   3968: 
                   3969: /* SCO 3.2 apparently has a broken ldexp. */
                   3970: 
                   3971: double
                   3972: ldexp(x,n)
                   3973:      double x;
                   3974:      int n;
                   3975: {
                   3976:   if (n > 0)
                   3977:     while (n--)
                   3978:       x *= 2;
                   3979: 
                   3980:   return x;
                   3981: }
                   3982: #endif /* BROKEN_LDEXP */

unix.superglobalmegacorp.com

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