Annotation of gcc/optabs.c, revision 1.1.1.8

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