OSDN Git Service

* ginclude/stdfix.h: New file.
[pf3gnuchains/gcc-fork.git] / gcc / optabs.c
1 /* Expand the basic unary and binary arithmetic operations, for GNU compiler.
2    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3    1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
4    Free Software Foundation, Inc.
5
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
12
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3.  If not see
20 <http://www.gnu.org/licenses/>.  */
21
22
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tm.h"
27 #include "toplev.h"
28
29 /* Include insn-config.h before expr.h so that HAVE_conditional_move
30    is properly defined.  */
31 #include "insn-config.h"
32 #include "rtl.h"
33 #include "tree.h"
34 #include "tm_p.h"
35 #include "flags.h"
36 #include "function.h"
37 #include "except.h"
38 #include "expr.h"
39 #include "optabs.h"
40 #include "libfuncs.h"
41 #include "recog.h"
42 #include "reload.h"
43 #include "ggc.h"
44 #include "real.h"
45 #include "basic-block.h"
46 #include "target.h"
47
48 /* Each optab contains info on how this target machine
49    can perform a particular operation
50    for all sizes and kinds of operands.
51
52    The operation to be performed is often specified
53    by passing one of these optabs as an argument.
54
55    See expr.h for documentation of these optabs.  */
56
57 optab optab_table[OTI_MAX];
58
59 rtx libfunc_table[LTI_MAX];
60
61 /* Tables of patterns for converting one mode to another.  */
62 convert_optab convert_optab_table[COI_MAX];
63
64 /* Contains the optab used for each rtx code.  */
65 optab code_to_optab[NUM_RTX_CODE + 1];
66
67 /* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
68    gives the gen_function to make a branch to test that condition.  */
69
70 rtxfun bcc_gen_fctn[NUM_RTX_CODE];
71
72 /* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
73    gives the insn code to make a store-condition insn
74    to test that condition.  */
75
76 enum insn_code setcc_gen_code[NUM_RTX_CODE];
77
78 #ifdef HAVE_conditional_move
79 /* Indexed by the machine mode, gives the insn code to make a conditional
80    move insn.  This is not indexed by the rtx-code like bcc_gen_fctn and
81    setcc_gen_code to cut down on the number of named patterns.  Consider a day
82    when a lot more rtx codes are conditional (eg: for the ARM).  */
83
84 enum insn_code movcc_gen_code[NUM_MACHINE_MODES];
85 #endif
86
87 /* Indexed by the machine mode, gives the insn code for vector conditional
88    operation.  */
89
90 enum insn_code vcond_gen_code[NUM_MACHINE_MODES];
91 enum insn_code vcondu_gen_code[NUM_MACHINE_MODES];
92
93 /* The insn generating function can not take an rtx_code argument.
94    TRAP_RTX is used as an rtx argument.  Its code is replaced with
95    the code to be used in the trap insn and all other fields are ignored.  */
96 static GTY(()) rtx trap_rtx;
97
98 static void prepare_float_lib_cmp (rtx *, rtx *, enum rtx_code *,
99                                    enum machine_mode *, int *);
100 static rtx expand_unop_direct (enum machine_mode, optab, rtx, rtx, int);
101
102 /* Current libcall id.  It doesn't matter what these are, as long
103    as they are unique to each libcall that is emitted.  */
104 static HOST_WIDE_INT libcall_id = 0;
105
106 /* Debug facility for use in GDB.  */
107 void debug_optab_libfuncs (void);
108
109 #ifndef HAVE_conditional_trap
110 #define HAVE_conditional_trap 0
111 #define gen_conditional_trap(a,b) (gcc_unreachable (), NULL_RTX)
112 #endif
113
114 /* Prefixes for the current version of decimal floating point (BID vs. DPD) */
115 #if ENABLE_DECIMAL_BID_FORMAT
116 #define DECIMAL_PREFIX "bid_"
117 #else
118 #define DECIMAL_PREFIX "dpd_"
119 #endif
120 \f
121
122 /* Info about libfunc.  We use same hashtable for normal optabs and conversion
123    optab.  In the first case mode2 is unused.  */
124 struct libfunc_entry GTY(())
125 {
126   size_t optab;
127   enum machine_mode mode1, mode2;
128   rtx libfunc;
129 };
130
131 /* Hash table used to convert declarations into nodes.  */
132 static GTY((param_is (struct libfunc_entry))) htab_t libfunc_hash;
133
134 /* Used for attribute_hash.  */
135
136 static hashval_t
137 hash_libfunc (const void *p)
138 {
139   const struct libfunc_entry *const e = (const struct libfunc_entry *) p;
140
141   return (((int) e->mode1 + (int) e->mode2 * NUM_MACHINE_MODES)
142           ^ e->optab);
143 }
144
145 /* Used for optab_hash.  */
146
147 static int
148 eq_libfunc (const void *p, const void *q)
149 {
150   const struct libfunc_entry *const e1 = (const struct libfunc_entry *) p;
151   const struct libfunc_entry *const e2 = (const struct libfunc_entry *) q;
152
153   return (e1->optab == e2->optab
154           && e1->mode1 == e2->mode1
155           && e1->mode2 == e2->mode2);
156 }
157
158 /* Return libfunc corresponding operation defined by OPTAB converting
159    from MODE2 to MODE1.  Trigger lazy initialization if needed, return NULL
160    if no libfunc is available.  */
161 rtx
162 convert_optab_libfunc (convert_optab optab, enum machine_mode mode1,
163                        enum machine_mode mode2)
164 {
165   struct libfunc_entry e;
166   struct libfunc_entry **slot;
167
168   e.optab = (size_t) (convert_optab_table[0] - optab);
169   e.mode1 = mode1;
170   e.mode2 = mode2;
171   slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, NO_INSERT);
172   if (!slot)
173     {
174       if (optab->libcall_gen)
175         {
176           optab->libcall_gen (optab, optab->libcall_basename, mode1, mode2);
177           slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, NO_INSERT);
178           if (slot)
179             return (*slot)->libfunc;
180           else
181             return NULL;
182         }
183       return NULL;
184     }
185   return (*slot)->libfunc;
186 }
187
188 /* Return libfunc corresponding operation defined by OPTAB in MODE.
189    Trigger lazy initialization if needed, return NULL if no libfunc is
190    available.  */
191 rtx
192 optab_libfunc (optab optab, enum machine_mode mode)
193 {
194   struct libfunc_entry e;
195   struct libfunc_entry **slot;
196
197   e.optab = (size_t) (optab_table[0] - optab);
198   e.mode1 = mode;
199   e.mode2 = VOIDmode;
200   slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, NO_INSERT);
201   if (!slot)
202     {
203       if (optab->libcall_gen)
204         {
205           optab->libcall_gen (optab, optab->libcall_basename,
206                               optab->libcall_suffix, mode);
207           slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash,
208                                                            &e, NO_INSERT);
209           if (slot)
210             return (*slot)->libfunc;
211           else
212             return NULL;
213         }
214       return NULL;
215     }
216   return (*slot)->libfunc;
217 }
218
219 \f
220 /* Add a REG_EQUAL note to the last insn in INSNS.  TARGET is being set to
221    the result of operation CODE applied to OP0 (and OP1 if it is a binary
222    operation).
223
224    If the last insn does not set TARGET, don't do anything, but return 1.
225
226    If a previous insn sets TARGET and TARGET is one of OP0 or OP1,
227    don't add the REG_EQUAL note but return 0.  Our caller can then try
228    again, ensuring that TARGET is not one of the operands.  */
229
230 static int
231 add_equal_note (rtx insns, rtx target, enum rtx_code code, rtx op0, rtx op1)
232 {
233   rtx last_insn, insn, set;
234   rtx note;
235
236   gcc_assert (insns && INSN_P (insns) && NEXT_INSN (insns));
237
238   if (GET_RTX_CLASS (code) != RTX_COMM_ARITH
239       && GET_RTX_CLASS (code) != RTX_BIN_ARITH
240       && GET_RTX_CLASS (code) != RTX_COMM_COMPARE
241       && GET_RTX_CLASS (code) != RTX_COMPARE
242       && GET_RTX_CLASS (code) != RTX_UNARY)
243     return 1;
244
245   if (GET_CODE (target) == ZERO_EXTRACT)
246     return 1;
247
248   for (last_insn = insns;
249        NEXT_INSN (last_insn) != NULL_RTX;
250        last_insn = NEXT_INSN (last_insn))
251     ;
252
253   set = single_set (last_insn);
254   if (set == NULL_RTX)
255     return 1;
256
257   if (! rtx_equal_p (SET_DEST (set), target)
258       /* For a STRICT_LOW_PART, the REG_NOTE applies to what is inside it.  */
259       && (GET_CODE (SET_DEST (set)) != STRICT_LOW_PART
260           || ! rtx_equal_p (XEXP (SET_DEST (set), 0), target)))
261     return 1;
262
263   /* If TARGET is in OP0 or OP1, check if anything in SEQ sets TARGET
264      besides the last insn.  */
265   if (reg_overlap_mentioned_p (target, op0)
266       || (op1 && reg_overlap_mentioned_p (target, op1)))
267     {
268       insn = PREV_INSN (last_insn);
269       while (insn != NULL_RTX)
270         {
271           if (reg_set_p (target, insn))
272             return 0;
273
274           insn = PREV_INSN (insn);
275         }
276     }
277
278   if (GET_RTX_CLASS (code) == RTX_UNARY)
279     note = gen_rtx_fmt_e (code, GET_MODE (target), copy_rtx (op0));
280   else
281     note = gen_rtx_fmt_ee (code, GET_MODE (target), copy_rtx (op0), copy_rtx (op1));
282
283   set_unique_reg_note (last_insn, REG_EQUAL, note);
284
285   return 1;
286 }
287 \f
288 /* Widen OP to MODE and return the rtx for the widened operand.  UNSIGNEDP
289    says whether OP is signed or unsigned.  NO_EXTEND is nonzero if we need
290    not actually do a sign-extend or zero-extend, but can leave the
291    higher-order bits of the result rtx undefined, for example, in the case
292    of logical operations, but not right shifts.  */
293
294 static rtx
295 widen_operand (rtx op, enum machine_mode mode, enum machine_mode oldmode,
296                int unsignedp, int no_extend)
297 {
298   rtx result;
299
300   /* If we don't have to extend and this is a constant, return it.  */
301   if (no_extend && GET_MODE (op) == VOIDmode)
302     return op;
303
304   /* If we must extend do so.  If OP is a SUBREG for a promoted object, also
305      extend since it will be more efficient to do so unless the signedness of
306      a promoted object differs from our extension.  */
307   if (! no_extend
308       || (GET_CODE (op) == SUBREG && SUBREG_PROMOTED_VAR_P (op)
309           && SUBREG_PROMOTED_UNSIGNED_P (op) == unsignedp))
310     return convert_modes (mode, oldmode, op, unsignedp);
311
312   /* If MODE is no wider than a single word, we return a paradoxical
313      SUBREG.  */
314   if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
315     return gen_rtx_SUBREG (mode, force_reg (GET_MODE (op), op), 0);
316
317   /* Otherwise, get an object of MODE, clobber it, and set the low-order
318      part to OP.  */
319
320   result = gen_reg_rtx (mode);
321   emit_insn (gen_rtx_CLOBBER (VOIDmode, result));
322   emit_move_insn (gen_lowpart (GET_MODE (op), result), op);
323   return result;
324 }
325 \f
326 /* Return the optab used for computing the operation given by
327    the tree code, CODE.  This function is not always usable (for
328    example, it cannot give complete results for multiplication
329    or division) but probably ought to be relied on more widely
330    throughout the expander.  */
331 optab
332 optab_for_tree_code (enum tree_code code, const_tree type)
333 {
334   bool trapv;
335   switch (code)
336     {
337     case BIT_AND_EXPR:
338       return and_optab;
339
340     case BIT_IOR_EXPR:
341       return ior_optab;
342
343     case BIT_NOT_EXPR:
344       return one_cmpl_optab;
345
346     case BIT_XOR_EXPR:
347       return xor_optab;
348
349     case TRUNC_MOD_EXPR:
350     case CEIL_MOD_EXPR:
351     case FLOOR_MOD_EXPR:
352     case ROUND_MOD_EXPR:
353       return TYPE_UNSIGNED (type) ? umod_optab : smod_optab;
354
355     case RDIV_EXPR:
356     case TRUNC_DIV_EXPR:
357     case CEIL_DIV_EXPR:
358     case FLOOR_DIV_EXPR:
359     case ROUND_DIV_EXPR:
360     case EXACT_DIV_EXPR:
361       if (TYPE_SATURATING(type))
362         return TYPE_UNSIGNED(type) ? usdiv_optab : ssdiv_optab;
363       return TYPE_UNSIGNED (type) ? udiv_optab : sdiv_optab;
364
365     case LSHIFT_EXPR:
366       if (TYPE_SATURATING(type))
367         return TYPE_UNSIGNED(type) ? usashl_optab : ssashl_optab;
368       return ashl_optab;
369
370     case RSHIFT_EXPR:
371       return TYPE_UNSIGNED (type) ? lshr_optab : ashr_optab;
372
373     case LROTATE_EXPR:
374       return rotl_optab;
375
376     case RROTATE_EXPR:
377       return rotr_optab;
378
379     case MAX_EXPR:
380       return TYPE_UNSIGNED (type) ? umax_optab : smax_optab;
381
382     case MIN_EXPR:
383       return TYPE_UNSIGNED (type) ? umin_optab : smin_optab;
384
385     case REALIGN_LOAD_EXPR:
386       return vec_realign_load_optab;
387
388     case WIDEN_SUM_EXPR:
389       return TYPE_UNSIGNED (type) ? usum_widen_optab : ssum_widen_optab;
390
391     case DOT_PROD_EXPR:
392       return TYPE_UNSIGNED (type) ? udot_prod_optab : sdot_prod_optab;
393
394     case REDUC_MAX_EXPR:
395       return TYPE_UNSIGNED (type) ? reduc_umax_optab : reduc_smax_optab;
396
397     case REDUC_MIN_EXPR:
398       return TYPE_UNSIGNED (type) ? reduc_umin_optab : reduc_smin_optab;
399
400     case REDUC_PLUS_EXPR:
401       return TYPE_UNSIGNED (type) ? reduc_uplus_optab : reduc_splus_optab;
402
403     case VEC_LSHIFT_EXPR:
404       return vec_shl_optab;
405
406     case VEC_RSHIFT_EXPR:
407       return vec_shr_optab;
408
409     case VEC_WIDEN_MULT_HI_EXPR:
410       return TYPE_UNSIGNED (type) ? 
411         vec_widen_umult_hi_optab : vec_widen_smult_hi_optab;
412
413     case VEC_WIDEN_MULT_LO_EXPR:
414       return TYPE_UNSIGNED (type) ? 
415         vec_widen_umult_lo_optab : vec_widen_smult_lo_optab;
416
417     case VEC_UNPACK_HI_EXPR:
418       return TYPE_UNSIGNED (type) ?
419         vec_unpacku_hi_optab : vec_unpacks_hi_optab;
420
421     case VEC_UNPACK_LO_EXPR:
422       return TYPE_UNSIGNED (type) ? 
423         vec_unpacku_lo_optab : vec_unpacks_lo_optab;
424
425     case VEC_UNPACK_FLOAT_HI_EXPR:
426       /* The signedness is determined from input operand.  */
427       return TYPE_UNSIGNED (type) ?
428         vec_unpacku_float_hi_optab : vec_unpacks_float_hi_optab;
429
430     case VEC_UNPACK_FLOAT_LO_EXPR:
431       /* The signedness is determined from input operand.  */
432       return TYPE_UNSIGNED (type) ? 
433         vec_unpacku_float_lo_optab : vec_unpacks_float_lo_optab;
434
435     case VEC_PACK_TRUNC_EXPR:
436       return vec_pack_trunc_optab;
437
438     case VEC_PACK_SAT_EXPR:
439       return TYPE_UNSIGNED (type) ? vec_pack_usat_optab : vec_pack_ssat_optab;
440
441     case VEC_PACK_FIX_TRUNC_EXPR:
442       /* The signedness is determined from output operand.  */
443       return TYPE_UNSIGNED (type) ?
444         vec_pack_ufix_trunc_optab : vec_pack_sfix_trunc_optab;
445
446     default:
447       break;
448     }
449
450   trapv = INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_TRAPS (type);
451   switch (code)
452     {
453     case POINTER_PLUS_EXPR:
454     case PLUS_EXPR:
455       if (TYPE_SATURATING(type))
456         return TYPE_UNSIGNED(type) ? usadd_optab : ssadd_optab;
457       return trapv ? addv_optab : add_optab;
458
459     case MINUS_EXPR:
460       if (TYPE_SATURATING(type))
461         return TYPE_UNSIGNED(type) ? ussub_optab : sssub_optab;
462       return trapv ? subv_optab : sub_optab;
463
464     case MULT_EXPR:
465       if (TYPE_SATURATING(type))
466         return TYPE_UNSIGNED(type) ? usmul_optab : ssmul_optab;
467       return trapv ? smulv_optab : smul_optab;
468
469     case NEGATE_EXPR:
470       if (TYPE_SATURATING(type))
471         return TYPE_UNSIGNED(type) ? usneg_optab : ssneg_optab;
472       return trapv ? negv_optab : neg_optab;
473
474     case ABS_EXPR:
475       return trapv ? absv_optab : abs_optab;
476
477     case VEC_EXTRACT_EVEN_EXPR:
478       return vec_extract_even_optab;
479
480     case VEC_EXTRACT_ODD_EXPR:
481       return vec_extract_odd_optab;
482
483     case VEC_INTERLEAVE_HIGH_EXPR:
484       return vec_interleave_high_optab;
485
486     case VEC_INTERLEAVE_LOW_EXPR:
487       return vec_interleave_low_optab;
488
489     default:
490       return NULL;
491     }
492 }
493 \f
494
495 /* Expand vector widening operations.
496
497    There are two different classes of operations handled here:
498    1) Operations whose result is wider than all the arguments to the operation.
499       Examples: VEC_UNPACK_HI/LO_EXPR, VEC_WIDEN_MULT_HI/LO_EXPR
500       In this case OP0 and optionally OP1 would be initialized,
501       but WIDE_OP wouldn't (not relevant for this case).
502    2) Operations whose result is of the same size as the last argument to the
503       operation, but wider than all the other arguments to the operation.
504       Examples: WIDEN_SUM_EXPR, VEC_DOT_PROD_EXPR.
505       In the case WIDE_OP, OP0 and optionally OP1 would be initialized.
506
507    E.g, when called to expand the following operations, this is how
508    the arguments will be initialized:
509                                 nops    OP0     OP1     WIDE_OP
510    widening-sum                 2       oprnd0  -       oprnd1          
511    widening-dot-product         3       oprnd0  oprnd1  oprnd2
512    widening-mult                2       oprnd0  oprnd1  -
513    type-promotion (vec-unpack)  1       oprnd0  -       -  */
514
515 rtx
516 expand_widen_pattern_expr (tree exp, rtx op0, rtx op1, rtx wide_op, rtx target,
517                            int unsignedp)
518 {   
519   tree oprnd0, oprnd1, oprnd2;
520   enum machine_mode wmode = 0, tmode0, tmode1 = 0;
521   optab widen_pattern_optab;
522   int icode; 
523   enum machine_mode xmode0, xmode1 = 0, wxmode = 0;
524   rtx temp;
525   rtx pat;
526   rtx xop0, xop1, wxop;
527   int nops = TREE_OPERAND_LENGTH (exp);
528
529   oprnd0 = TREE_OPERAND (exp, 0);
530   tmode0 = TYPE_MODE (TREE_TYPE (oprnd0));
531   widen_pattern_optab =
532         optab_for_tree_code (TREE_CODE (exp), TREE_TYPE (oprnd0));
533   icode = (int) optab_handler (widen_pattern_optab, tmode0)->insn_code;
534   gcc_assert (icode != CODE_FOR_nothing);
535   xmode0 = insn_data[icode].operand[1].mode;
536
537   if (nops >= 2)
538     {
539       oprnd1 = TREE_OPERAND (exp, 1);
540       tmode1 = TYPE_MODE (TREE_TYPE (oprnd1));
541       xmode1 = insn_data[icode].operand[2].mode;
542     }
543
544   /* The last operand is of a wider mode than the rest of the operands.  */
545   if (nops == 2)
546     {
547       wmode = tmode1;
548       wxmode = xmode1;
549     }
550   else if (nops == 3)
551     {
552       gcc_assert (tmode1 == tmode0);
553       gcc_assert (op1);
554       oprnd2 = TREE_OPERAND (exp, 2);
555       wmode = TYPE_MODE (TREE_TYPE (oprnd2));
556       wxmode = insn_data[icode].operand[3].mode;
557     }
558
559   if (!wide_op)
560     wmode = wxmode = insn_data[icode].operand[0].mode;
561
562   if (!target
563       || ! (*insn_data[icode].operand[0].predicate) (target, wmode))
564     temp = gen_reg_rtx (wmode);
565   else
566     temp = target;
567
568   xop0 = op0;
569   xop1 = op1;
570   wxop = wide_op;
571
572   /* In case the insn wants input operands in modes different from
573      those of the actual operands, convert the operands.  It would
574      seem that we don't need to convert CONST_INTs, but we do, so
575      that they're properly zero-extended, sign-extended or truncated
576      for their mode.  */
577
578   if (GET_MODE (op0) != xmode0 && xmode0 != VOIDmode)
579     xop0 = convert_modes (xmode0,
580                           GET_MODE (op0) != VOIDmode
581                           ? GET_MODE (op0)
582                           : tmode0,
583                           xop0, unsignedp);
584
585   if (op1)
586     if (GET_MODE (op1) != xmode1 && xmode1 != VOIDmode)
587       xop1 = convert_modes (xmode1,
588                             GET_MODE (op1) != VOIDmode
589                             ? GET_MODE (op1)
590                             : tmode1,
591                             xop1, unsignedp);
592
593   if (wide_op)
594     if (GET_MODE (wide_op) != wxmode && wxmode != VOIDmode)
595       wxop = convert_modes (wxmode,
596                             GET_MODE (wide_op) != VOIDmode
597                             ? GET_MODE (wide_op)
598                             : wmode,
599                             wxop, unsignedp);
600
601   /* Now, if insn's predicates don't allow our operands, put them into
602      pseudo regs.  */
603
604   if (! (*insn_data[icode].operand[1].predicate) (xop0, xmode0)
605       && xmode0 != VOIDmode)
606     xop0 = copy_to_mode_reg (xmode0, xop0);
607
608   if (op1)
609     {
610       if (! (*insn_data[icode].operand[2].predicate) (xop1, xmode1)
611           && xmode1 != VOIDmode)
612         xop1 = copy_to_mode_reg (xmode1, xop1);
613
614       if (wide_op)
615         {
616           if (! (*insn_data[icode].operand[3].predicate) (wxop, wxmode)
617               && wxmode != VOIDmode)
618             wxop = copy_to_mode_reg (wxmode, wxop);
619
620           pat = GEN_FCN (icode) (temp, xop0, xop1, wxop);
621         }
622       else
623         pat = GEN_FCN (icode) (temp, xop0, xop1);
624     }
625   else
626     {
627       if (wide_op)
628         {
629           if (! (*insn_data[icode].operand[2].predicate) (wxop, wxmode)
630               && wxmode != VOIDmode)
631             wxop = copy_to_mode_reg (wxmode, wxop);
632
633           pat = GEN_FCN (icode) (temp, xop0, wxop);
634         }
635       else
636         pat = GEN_FCN (icode) (temp, xop0);
637     }
638
639   emit_insn (pat);
640   return temp;
641 }
642
643 /* Generate code to perform an operation specified by TERNARY_OPTAB
644    on operands OP0, OP1 and OP2, with result having machine-mode MODE.
645
646    UNSIGNEDP is for the case where we have to widen the operands
647    to perform the operation.  It says to use zero-extension.
648
649    If TARGET is nonzero, the value
650    is generated there, if it is convenient to do so.
651    In all cases an rtx is returned for the locus of the value;
652    this may or may not be TARGET.  */
653
654 rtx
655 expand_ternary_op (enum machine_mode mode, optab ternary_optab, rtx op0,
656                    rtx op1, rtx op2, rtx target, int unsignedp)
657 {
658   int icode = (int) optab_handler (ternary_optab, mode)->insn_code;
659   enum machine_mode mode0 = insn_data[icode].operand[1].mode;
660   enum machine_mode mode1 = insn_data[icode].operand[2].mode;
661   enum machine_mode mode2 = insn_data[icode].operand[3].mode;
662   rtx temp;
663   rtx pat;
664   rtx xop0 = op0, xop1 = op1, xop2 = op2;
665
666   gcc_assert (optab_handler (ternary_optab, mode)->insn_code
667               != CODE_FOR_nothing);
668
669   if (!target || !insn_data[icode].operand[0].predicate (target, mode))
670     temp = gen_reg_rtx (mode);
671   else
672     temp = target;
673
674   /* In case the insn wants input operands in modes different from
675      those of the actual operands, convert the operands.  It would
676      seem that we don't need to convert CONST_INTs, but we do, so
677      that they're properly zero-extended, sign-extended or truncated
678      for their mode.  */
679
680   if (GET_MODE (op0) != mode0 && mode0 != VOIDmode)
681     xop0 = convert_modes (mode0,
682                           GET_MODE (op0) != VOIDmode
683                           ? GET_MODE (op0)
684                           : mode,
685                           xop0, unsignedp);
686
687   if (GET_MODE (op1) != mode1 && mode1 != VOIDmode)
688     xop1 = convert_modes (mode1,
689                           GET_MODE (op1) != VOIDmode
690                           ? GET_MODE (op1)
691                           : mode,
692                           xop1, unsignedp);
693
694   if (GET_MODE (op2) != mode2 && mode2 != VOIDmode)
695     xop2 = convert_modes (mode2,
696                           GET_MODE (op2) != VOIDmode
697                           ? GET_MODE (op2)
698                           : mode,
699                           xop2, unsignedp);
700
701   /* Now, if insn's predicates don't allow our operands, put them into
702      pseudo regs.  */
703
704   if (!insn_data[icode].operand[1].predicate (xop0, mode0)
705       && mode0 != VOIDmode)
706     xop0 = copy_to_mode_reg (mode0, xop0);
707
708   if (!insn_data[icode].operand[2].predicate (xop1, mode1)
709       && mode1 != VOIDmode)
710     xop1 = copy_to_mode_reg (mode1, xop1);
711
712   if (!insn_data[icode].operand[3].predicate (xop2, mode2)
713       && mode2 != VOIDmode)
714     xop2 = copy_to_mode_reg (mode2, xop2);
715
716   pat = GEN_FCN (icode) (temp, xop0, xop1, xop2);
717
718   emit_insn (pat);
719   return temp;
720 }
721
722
723 /* Like expand_binop, but return a constant rtx if the result can be
724    calculated at compile time.  The arguments and return value are
725    otherwise the same as for expand_binop.  */
726
727 static rtx
728 simplify_expand_binop (enum machine_mode mode, optab binoptab,
729                        rtx op0, rtx op1, rtx target, int unsignedp,
730                        enum optab_methods methods)
731 {
732   if (CONSTANT_P (op0) && CONSTANT_P (op1))
733     {
734       rtx x = simplify_binary_operation (binoptab->code, mode, op0, op1);
735
736       if (x)
737         return x;
738     }
739
740   return expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods);
741 }
742
743 /* Like simplify_expand_binop, but always put the result in TARGET.
744    Return true if the expansion succeeded.  */
745
746 bool
747 force_expand_binop (enum machine_mode mode, optab binoptab,
748                     rtx op0, rtx op1, rtx target, int unsignedp,
749                     enum optab_methods methods)
750 {
751   rtx x = simplify_expand_binop (mode, binoptab, op0, op1,
752                                  target, unsignedp, methods);
753   if (x == 0)
754     return false;
755   if (x != target)
756     emit_move_insn (target, x);
757   return true;
758 }
759
760 /* Generate insns for VEC_LSHIFT_EXPR, VEC_RSHIFT_EXPR.  */
761
762 rtx
763 expand_vec_shift_expr (tree vec_shift_expr, rtx target)
764 {
765   enum insn_code icode;
766   rtx rtx_op1, rtx_op2;
767   enum machine_mode mode1;
768   enum machine_mode mode2;
769   enum machine_mode mode = TYPE_MODE (TREE_TYPE (vec_shift_expr));
770   tree vec_oprnd = TREE_OPERAND (vec_shift_expr, 0);
771   tree shift_oprnd = TREE_OPERAND (vec_shift_expr, 1);
772   optab shift_optab;
773   rtx pat;
774
775   switch (TREE_CODE (vec_shift_expr))
776     {
777       case VEC_RSHIFT_EXPR:
778         shift_optab = vec_shr_optab;
779         break;
780       case VEC_LSHIFT_EXPR:
781         shift_optab = vec_shl_optab;
782         break;
783       default:
784         gcc_unreachable ();
785     }
786
787   icode = (int) optab_handler (shift_optab, mode)->insn_code;
788   gcc_assert (icode != CODE_FOR_nothing);
789
790   mode1 = insn_data[icode].operand[1].mode;
791   mode2 = insn_data[icode].operand[2].mode;
792
793   rtx_op1 = expand_normal (vec_oprnd);
794   if (!(*insn_data[icode].operand[1].predicate) (rtx_op1, mode1)
795       && mode1 != VOIDmode)
796     rtx_op1 = force_reg (mode1, rtx_op1);
797
798   rtx_op2 = expand_normal (shift_oprnd);
799   if (!(*insn_data[icode].operand[2].predicate) (rtx_op2, mode2)
800       && mode2 != VOIDmode)
801     rtx_op2 = force_reg (mode2, rtx_op2);
802
803   if (!target
804       || ! (*insn_data[icode].operand[0].predicate) (target, mode))
805     target = gen_reg_rtx (mode);
806
807   /* Emit instruction */
808   pat = GEN_FCN (icode) (target, rtx_op1, rtx_op2);
809   gcc_assert (pat);
810   emit_insn (pat);
811
812   return target;
813 }
814
815 /* This subroutine of expand_doubleword_shift handles the cases in which
816    the effective shift value is >= BITS_PER_WORD.  The arguments and return
817    value are the same as for the parent routine, except that SUPERWORD_OP1
818    is the shift count to use when shifting OUTOF_INPUT into INTO_TARGET.
819    INTO_TARGET may be null if the caller has decided to calculate it.  */
820
821 static bool
822 expand_superword_shift (optab binoptab, rtx outof_input, rtx superword_op1,
823                         rtx outof_target, rtx into_target,
824                         int unsignedp, enum optab_methods methods)
825 {
826   if (into_target != 0)
827     if (!force_expand_binop (word_mode, binoptab, outof_input, superword_op1,
828                              into_target, unsignedp, methods))
829       return false;
830
831   if (outof_target != 0)
832     {
833       /* For a signed right shift, we must fill OUTOF_TARGET with copies
834          of the sign bit, otherwise we must fill it with zeros.  */
835       if (binoptab != ashr_optab)
836         emit_move_insn (outof_target, CONST0_RTX (word_mode));
837       else
838         if (!force_expand_binop (word_mode, binoptab,
839                                  outof_input, GEN_INT (BITS_PER_WORD - 1),
840                                  outof_target, unsignedp, methods))
841           return false;
842     }
843   return true;
844 }
845
846 /* This subroutine of expand_doubleword_shift handles the cases in which
847    the effective shift value is < BITS_PER_WORD.  The arguments and return
848    value are the same as for the parent routine.  */
849
850 static bool
851 expand_subword_shift (enum machine_mode op1_mode, optab binoptab,
852                       rtx outof_input, rtx into_input, rtx op1,
853                       rtx outof_target, rtx into_target,
854                       int unsignedp, enum optab_methods methods,
855                       unsigned HOST_WIDE_INT shift_mask)
856 {
857   optab reverse_unsigned_shift, unsigned_shift;
858   rtx tmp, carries;
859
860   reverse_unsigned_shift = (binoptab == ashl_optab ? lshr_optab : ashl_optab);
861   unsigned_shift = (binoptab == ashl_optab ? ashl_optab : lshr_optab);
862
863   /* The low OP1 bits of INTO_TARGET come from the high bits of OUTOF_INPUT.
864      We therefore need to shift OUTOF_INPUT by (BITS_PER_WORD - OP1) bits in
865      the opposite direction to BINOPTAB.  */
866   if (CONSTANT_P (op1) || shift_mask >= BITS_PER_WORD)
867     {
868       carries = outof_input;
869       tmp = immed_double_const (BITS_PER_WORD, 0, op1_mode);
870       tmp = simplify_expand_binop (op1_mode, sub_optab, tmp, op1,
871                                    0, true, methods);
872     }
873   else
874     {
875       /* We must avoid shifting by BITS_PER_WORD bits since that is either
876          the same as a zero shift (if shift_mask == BITS_PER_WORD - 1) or
877          has unknown behavior.  Do a single shift first, then shift by the
878          remainder.  It's OK to use ~OP1 as the remainder if shift counts
879          are truncated to the mode size.  */
880       carries = expand_binop (word_mode, reverse_unsigned_shift,
881                               outof_input, const1_rtx, 0, unsignedp, methods);
882       if (shift_mask == BITS_PER_WORD - 1)
883         {
884           tmp = immed_double_const (-1, -1, op1_mode);
885           tmp = simplify_expand_binop (op1_mode, xor_optab, op1, tmp,
886                                        0, true, methods);
887         }
888       else
889         {
890           tmp = immed_double_const (BITS_PER_WORD - 1, 0, op1_mode);
891           tmp = simplify_expand_binop (op1_mode, sub_optab, tmp, op1,
892                                        0, true, methods);
893         }
894     }
895   if (tmp == 0 || carries == 0)
896     return false;
897   carries = expand_binop (word_mode, reverse_unsigned_shift,
898                           carries, tmp, 0, unsignedp, methods);
899   if (carries == 0)
900     return false;
901
902   /* Shift INTO_INPUT logically by OP1.  This is the last use of INTO_INPUT
903      so the result can go directly into INTO_TARGET if convenient.  */
904   tmp = expand_binop (word_mode, unsigned_shift, into_input, op1,
905                       into_target, unsignedp, methods);
906   if (tmp == 0)
907     return false;
908
909   /* Now OR in the bits carried over from OUTOF_INPUT.  */
910   if (!force_expand_binop (word_mode, ior_optab, tmp, carries,
911                            into_target, unsignedp, methods))
912     return false;
913
914   /* Use a standard word_mode shift for the out-of half.  */
915   if (outof_target != 0)
916     if (!force_expand_binop (word_mode, binoptab, outof_input, op1,
917                              outof_target, unsignedp, methods))
918       return false;
919
920   return true;
921 }
922
923
924 #ifdef HAVE_conditional_move
925 /* Try implementing expand_doubleword_shift using conditional moves.
926    The shift is by < BITS_PER_WORD if (CMP_CODE CMP1 CMP2) is true,
927    otherwise it is by >= BITS_PER_WORD.  SUBWORD_OP1 and SUPERWORD_OP1
928    are the shift counts to use in the former and latter case.  All other
929    arguments are the same as the parent routine.  */
930
931 static bool
932 expand_doubleword_shift_condmove (enum machine_mode op1_mode, optab binoptab,
933                                   enum rtx_code cmp_code, rtx cmp1, rtx cmp2,
934                                   rtx outof_input, rtx into_input,
935                                   rtx subword_op1, rtx superword_op1,
936                                   rtx outof_target, rtx into_target,
937                                   int unsignedp, enum optab_methods methods,
938                                   unsigned HOST_WIDE_INT shift_mask)
939 {
940   rtx outof_superword, into_superword;
941
942   /* Put the superword version of the output into OUTOF_SUPERWORD and
943      INTO_SUPERWORD.  */
944   outof_superword = outof_target != 0 ? gen_reg_rtx (word_mode) : 0;
945   if (outof_target != 0 && subword_op1 == superword_op1)
946     {
947       /* The value INTO_TARGET >> SUBWORD_OP1, which we later store in
948          OUTOF_TARGET, is the same as the value of INTO_SUPERWORD.  */
949       into_superword = outof_target;
950       if (!expand_superword_shift (binoptab, outof_input, superword_op1,
951                                    outof_superword, 0, unsignedp, methods))
952         return false;
953     }
954   else
955     {
956       into_superword = gen_reg_rtx (word_mode);
957       if (!expand_superword_shift (binoptab, outof_input, superword_op1,
958                                    outof_superword, into_superword,
959                                    unsignedp, methods))
960         return false;
961     }
962
963   /* Put the subword version directly in OUTOF_TARGET and INTO_TARGET.  */
964   if (!expand_subword_shift (op1_mode, binoptab,
965                              outof_input, into_input, subword_op1,
966                              outof_target, into_target,
967                              unsignedp, methods, shift_mask))
968     return false;
969
970   /* Select between them.  Do the INTO half first because INTO_SUPERWORD
971      might be the current value of OUTOF_TARGET.  */
972   if (!emit_conditional_move (into_target, cmp_code, cmp1, cmp2, op1_mode,
973                               into_target, into_superword, word_mode, false))
974     return false;
975
976   if (outof_target != 0)
977     if (!emit_conditional_move (outof_target, cmp_code, cmp1, cmp2, op1_mode,
978                                 outof_target, outof_superword,
979                                 word_mode, false))
980       return false;
981
982   return true;
983 }
984 #endif
985
986 /* Expand a doubleword shift (ashl, ashr or lshr) using word-mode shifts.
987    OUTOF_INPUT and INTO_INPUT are the two word-sized halves of the first
988    input operand; the shift moves bits in the direction OUTOF_INPUT->
989    INTO_TARGET.  OUTOF_TARGET and INTO_TARGET are the equivalent words
990    of the target.  OP1 is the shift count and OP1_MODE is its mode.
991    If OP1 is constant, it will have been truncated as appropriate
992    and is known to be nonzero.
993
994    If SHIFT_MASK is zero, the result of word shifts is undefined when the
995    shift count is outside the range [0, BITS_PER_WORD).  This routine must
996    avoid generating such shifts for OP1s in the range [0, BITS_PER_WORD * 2).
997
998    If SHIFT_MASK is nonzero, all word-mode shift counts are effectively
999    masked by it and shifts in the range [BITS_PER_WORD, SHIFT_MASK) will
1000    fill with zeros or sign bits as appropriate.
1001
1002    If SHIFT_MASK is BITS_PER_WORD - 1, this routine will synthesize
1003    a doubleword shift whose equivalent mask is BITS_PER_WORD * 2 - 1.
1004    Doing this preserves semantics required by SHIFT_COUNT_TRUNCATED.
1005    In all other cases, shifts by values outside [0, BITS_PER_UNIT * 2)
1006    are undefined.
1007
1008    BINOPTAB, UNSIGNEDP and METHODS are as for expand_binop.  This function
1009    may not use INTO_INPUT after modifying INTO_TARGET, and similarly for
1010    OUTOF_INPUT and OUTOF_TARGET.  OUTOF_TARGET can be null if the parent
1011    function wants to calculate it itself.
1012
1013    Return true if the shift could be successfully synthesized.  */
1014
1015 static bool
1016 expand_doubleword_shift (enum machine_mode op1_mode, optab binoptab,
1017                          rtx outof_input, rtx into_input, rtx op1,
1018                          rtx outof_target, rtx into_target,
1019                          int unsignedp, enum optab_methods methods,
1020                          unsigned HOST_WIDE_INT shift_mask)
1021 {
1022   rtx superword_op1, tmp, cmp1, cmp2;
1023   rtx subword_label, done_label;
1024   enum rtx_code cmp_code;
1025
1026   /* See if word-mode shifts by BITS_PER_WORD...BITS_PER_WORD * 2 - 1 will
1027      fill the result with sign or zero bits as appropriate.  If so, the value
1028      of OUTOF_TARGET will always be (SHIFT OUTOF_INPUT OP1).   Recursively call
1029      this routine to calculate INTO_TARGET (which depends on both OUTOF_INPUT
1030      and INTO_INPUT), then emit code to set up OUTOF_TARGET.
1031
1032      This isn't worthwhile for constant shifts since the optimizers will
1033      cope better with in-range shift counts.  */
1034   if (shift_mask >= BITS_PER_WORD
1035       && outof_target != 0
1036       && !CONSTANT_P (op1))
1037     {
1038       if (!expand_doubleword_shift (op1_mode, binoptab,
1039                                     outof_input, into_input, op1,
1040                                     0, into_target,
1041                                     unsignedp, methods, shift_mask))
1042         return false;
1043       if (!force_expand_binop (word_mode, binoptab, outof_input, op1,
1044                                outof_target, unsignedp, methods))
1045         return false;
1046       return true;
1047     }
1048
1049   /* Set CMP_CODE, CMP1 and CMP2 so that the rtx (CMP_CODE CMP1 CMP2)
1050      is true when the effective shift value is less than BITS_PER_WORD.
1051      Set SUPERWORD_OP1 to the shift count that should be used to shift
1052      OUTOF_INPUT into INTO_TARGET when the condition is false.  */
1053   tmp = immed_double_const (BITS_PER_WORD, 0, op1_mode);
1054   if (!CONSTANT_P (op1) && shift_mask == BITS_PER_WORD - 1)
1055     {
1056       /* Set CMP1 to OP1 & BITS_PER_WORD.  The result is zero iff OP1
1057          is a subword shift count.  */
1058       cmp1 = simplify_expand_binop (op1_mode, and_optab, op1, tmp,
1059                                     0, true, methods);
1060       cmp2 = CONST0_RTX (op1_mode);
1061       cmp_code = EQ;
1062       superword_op1 = op1;
1063     }
1064   else
1065     {
1066       /* Set CMP1 to OP1 - BITS_PER_WORD.  */
1067       cmp1 = simplify_expand_binop (op1_mode, sub_optab, op1, tmp,
1068                                     0, true, methods);
1069       cmp2 = CONST0_RTX (op1_mode);
1070       cmp_code = LT;
1071       superword_op1 = cmp1;
1072     }
1073   if (cmp1 == 0)
1074     return false;
1075
1076   /* If we can compute the condition at compile time, pick the
1077      appropriate subroutine.  */
1078   tmp = simplify_relational_operation (cmp_code, SImode, op1_mode, cmp1, cmp2);
1079   if (tmp != 0 && GET_CODE (tmp) == CONST_INT)
1080     {
1081       if (tmp == const0_rtx)
1082         return expand_superword_shift (binoptab, outof_input, superword_op1,
1083                                        outof_target, into_target,
1084                                        unsignedp, methods);
1085       else
1086         return expand_subword_shift (op1_mode, binoptab,
1087                                      outof_input, into_input, op1,
1088                                      outof_target, into_target,
1089                                      unsignedp, methods, shift_mask);
1090     }
1091
1092 #ifdef HAVE_conditional_move
1093   /* Try using conditional moves to generate straight-line code.  */
1094   {
1095     rtx start = get_last_insn ();
1096     if (expand_doubleword_shift_condmove (op1_mode, binoptab,
1097                                           cmp_code, cmp1, cmp2,
1098                                           outof_input, into_input,
1099                                           op1, superword_op1,
1100                                           outof_target, into_target,
1101                                           unsignedp, methods, shift_mask))
1102       return true;
1103     delete_insns_since (start);
1104   }
1105 #endif
1106
1107   /* As a last resort, use branches to select the correct alternative.  */
1108   subword_label = gen_label_rtx ();
1109   done_label = gen_label_rtx ();
1110
1111   NO_DEFER_POP;
1112   do_compare_rtx_and_jump (cmp1, cmp2, cmp_code, false, op1_mode,
1113                            0, 0, subword_label);
1114   OK_DEFER_POP;
1115
1116   if (!expand_superword_shift (binoptab, outof_input, superword_op1,
1117                                outof_target, into_target,
1118                                unsignedp, methods))
1119     return false;
1120
1121   emit_jump_insn (gen_jump (done_label));
1122   emit_barrier ();
1123   emit_label (subword_label);
1124
1125   if (!expand_subword_shift (op1_mode, binoptab,
1126                              outof_input, into_input, op1,
1127                              outof_target, into_target,
1128                              unsignedp, methods, shift_mask))
1129     return false;
1130
1131   emit_label (done_label);
1132   return true;
1133 }
1134 \f
1135 /* Subroutine of expand_binop.  Perform a double word multiplication of
1136    operands OP0 and OP1 both of mode MODE, which is exactly twice as wide
1137    as the target's word_mode.  This function return NULL_RTX if anything
1138    goes wrong, in which case it may have already emitted instructions
1139    which need to be deleted.
1140
1141    If we want to multiply two two-word values and have normal and widening
1142    multiplies of single-word values, we can do this with three smaller
1143    multiplications.  Note that we do not make a REG_NO_CONFLICT block here
1144    because we are not operating on one word at a time.
1145
1146    The multiplication proceeds as follows:
1147                                  _______________________
1148                                 [__op0_high_|__op0_low__]
1149                                  _______________________
1150         *                       [__op1_high_|__op1_low__]
1151         _______________________________________________
1152                                  _______________________
1153     (1)                         [__op0_low__*__op1_low__]
1154                      _______________________
1155     (2a)            [__op0_low__*__op1_high_]
1156                      _______________________
1157     (2b)            [__op0_high_*__op1_low__]
1158          _______________________
1159     (3) [__op0_high_*__op1_high_]
1160
1161
1162   This gives a 4-word result.  Since we are only interested in the
1163   lower 2 words, partial result (3) and the upper words of (2a) and
1164   (2b) don't need to be calculated.  Hence (2a) and (2b) can be
1165   calculated using non-widening multiplication.
1166
1167   (1), however, needs to be calculated with an unsigned widening
1168   multiplication.  If this operation is not directly supported we
1169   try using a signed widening multiplication and adjust the result.
1170   This adjustment works as follows:
1171
1172       If both operands are positive then no adjustment is needed.
1173
1174       If the operands have different signs, for example op0_low < 0 and
1175       op1_low >= 0, the instruction treats the most significant bit of
1176       op0_low as a sign bit instead of a bit with significance
1177       2**(BITS_PER_WORD-1), i.e. the instruction multiplies op1_low
1178       with 2**BITS_PER_WORD - op0_low, and two's complements the
1179       result.  Conclusion: We need to add op1_low * 2**BITS_PER_WORD to
1180       the result.
1181
1182       Similarly, if both operands are negative, we need to add
1183       (op0_low + op1_low) * 2**BITS_PER_WORD.
1184
1185       We use a trick to adjust quickly.  We logically shift op0_low right
1186       (op1_low) BITS_PER_WORD-1 steps to get 0 or 1, and add this to
1187       op0_high (op1_high) before it is used to calculate 2b (2a).  If no
1188       logical shift exists, we do an arithmetic right shift and subtract
1189       the 0 or -1.  */
1190
1191 static rtx
1192 expand_doubleword_mult (enum machine_mode mode, rtx op0, rtx op1, rtx target,
1193                        bool umulp, enum optab_methods methods)
1194 {
1195   int low = (WORDS_BIG_ENDIAN ? 1 : 0);
1196   int high = (WORDS_BIG_ENDIAN ? 0 : 1);
1197   rtx wordm1 = umulp ? NULL_RTX : GEN_INT (BITS_PER_WORD - 1);
1198   rtx product, adjust, product_high, temp;
1199
1200   rtx op0_high = operand_subword_force (op0, high, mode);
1201   rtx op0_low = operand_subword_force (op0, low, mode);
1202   rtx op1_high = operand_subword_force (op1, high, mode);
1203   rtx op1_low = operand_subword_force (op1, low, mode);
1204
1205   /* If we're using an unsigned multiply to directly compute the product
1206      of the low-order words of the operands and perform any required
1207      adjustments of the operands, we begin by trying two more multiplications
1208      and then computing the appropriate sum.
1209
1210      We have checked above that the required addition is provided.
1211      Full-word addition will normally always succeed, especially if
1212      it is provided at all, so we don't worry about its failure.  The
1213      multiplication may well fail, however, so we do handle that.  */
1214
1215   if (!umulp)
1216     {
1217       /* ??? This could be done with emit_store_flag where available.  */
1218       temp = expand_binop (word_mode, lshr_optab, op0_low, wordm1,
1219                            NULL_RTX, 1, methods);
1220       if (temp)
1221         op0_high = expand_binop (word_mode, add_optab, op0_high, temp,
1222                                  NULL_RTX, 0, OPTAB_DIRECT);
1223       else
1224         {
1225           temp = expand_binop (word_mode, ashr_optab, op0_low, wordm1,
1226                                NULL_RTX, 0, methods);
1227           if (!temp)
1228             return NULL_RTX;
1229           op0_high = expand_binop (word_mode, sub_optab, op0_high, temp,
1230                                    NULL_RTX, 0, OPTAB_DIRECT);
1231         }
1232
1233       if (!op0_high)
1234         return NULL_RTX;
1235     }
1236
1237   adjust = expand_binop (word_mode, smul_optab, op0_high, op1_low,
1238                          NULL_RTX, 0, OPTAB_DIRECT);
1239   if (!adjust)
1240     return NULL_RTX;
1241
1242   /* OP0_HIGH should now be dead.  */
1243
1244   if (!umulp)
1245     {
1246       /* ??? This could be done with emit_store_flag where available.  */
1247       temp = expand_binop (word_mode, lshr_optab, op1_low, wordm1,
1248                            NULL_RTX, 1, methods);
1249       if (temp)
1250         op1_high = expand_binop (word_mode, add_optab, op1_high, temp,
1251                                  NULL_RTX, 0, OPTAB_DIRECT);
1252       else
1253         {
1254           temp = expand_binop (word_mode, ashr_optab, op1_low, wordm1,
1255                                NULL_RTX, 0, methods);
1256           if (!temp)
1257             return NULL_RTX;
1258           op1_high = expand_binop (word_mode, sub_optab, op1_high, temp,
1259                                    NULL_RTX, 0, OPTAB_DIRECT);
1260         }
1261
1262       if (!op1_high)
1263         return NULL_RTX;
1264     }
1265
1266   temp = expand_binop (word_mode, smul_optab, op1_high, op0_low,
1267                        NULL_RTX, 0, OPTAB_DIRECT);
1268   if (!temp)
1269     return NULL_RTX;
1270
1271   /* OP1_HIGH should now be dead.  */
1272
1273   adjust = expand_binop (word_mode, add_optab, adjust, temp,
1274                          adjust, 0, OPTAB_DIRECT);
1275
1276   if (target && !REG_P (target))
1277     target = NULL_RTX;
1278
1279   if (umulp)
1280     product = expand_binop (mode, umul_widen_optab, op0_low, op1_low,
1281                             target, 1, OPTAB_DIRECT);
1282   else
1283     product = expand_binop (mode, smul_widen_optab, op0_low, op1_low,
1284                             target, 1, OPTAB_DIRECT);
1285
1286   if (!product)
1287     return NULL_RTX;
1288
1289   product_high = operand_subword (product, high, 1, mode);
1290   adjust = expand_binop (word_mode, add_optab, product_high, adjust,
1291                          REG_P (product_high) ? product_high : adjust,
1292                          0, OPTAB_DIRECT);
1293   emit_move_insn (product_high, adjust);
1294   return product;
1295 }
1296 \f
1297 /* Wrapper around expand_binop which takes an rtx code to specify
1298    the operation to perform, not an optab pointer.  All other
1299    arguments are the same.  */
1300 rtx
1301 expand_simple_binop (enum machine_mode mode, enum rtx_code code, rtx op0,
1302                      rtx op1, rtx target, int unsignedp,
1303                      enum optab_methods methods)
1304 {
1305   optab binop = code_to_optab[(int) code];
1306   gcc_assert (binop);
1307
1308   return expand_binop (mode, binop, op0, op1, target, unsignedp, methods);
1309 }
1310
1311 /* Return whether OP0 and OP1 should be swapped when expanding a commutative
1312    binop.  Order them according to commutative_operand_precedence and, if
1313    possible, try to put TARGET or a pseudo first.  */
1314 static bool
1315 swap_commutative_operands_with_target (rtx target, rtx op0, rtx op1)
1316 {
1317   int op0_prec = commutative_operand_precedence (op0);
1318   int op1_prec = commutative_operand_precedence (op1);
1319
1320   if (op0_prec < op1_prec)
1321     return true;
1322
1323   if (op0_prec > op1_prec)
1324     return false;
1325
1326   /* With equal precedence, both orders are ok, but it is better if the
1327      first operand is TARGET, or if both TARGET and OP0 are pseudos.  */
1328   if (target == 0 || REG_P (target))
1329     return (REG_P (op1) && !REG_P (op0)) || target == op1;
1330   else
1331     return rtx_equal_p (op1, target);
1332 }
1333
1334 /* Return true if BINOPTAB implements a shift operation.  */
1335
1336 static bool
1337 shift_optab_p (optab binoptab)
1338 {
1339   switch (binoptab->code)
1340     {
1341     case ASHIFT:
1342     case SS_ASHIFT:
1343     case US_ASHIFT:
1344     case ASHIFTRT:
1345     case LSHIFTRT:
1346     case ROTATE:
1347     case ROTATERT:
1348       return true;
1349
1350     default:
1351       return false;
1352     }
1353 }
1354
1355 /* Return true if BINOPTAB implements a commutative binary operation.  */
1356
1357 static bool
1358 commutative_optab_p (optab binoptab)
1359 {
1360   return (GET_RTX_CLASS (binoptab->code) == RTX_COMM_ARITH
1361           || binoptab == smul_widen_optab
1362           || binoptab == umul_widen_optab
1363           || binoptab == smul_highpart_optab
1364           || binoptab == umul_highpart_optab);
1365 }
1366
1367 /* X is to be used in mode MODE as an operand to BINOPTAB.  If we're
1368    optimizing, and if the operand is a constant that costs more than
1369    1 instruction, force the constant into a register and return that
1370    register.  Return X otherwise.  UNSIGNEDP says whether X is unsigned.  */
1371
1372 static rtx
1373 avoid_expensive_constant (enum machine_mode mode, optab binoptab,
1374                           rtx x, bool unsignedp)
1375 {
1376   if (mode != VOIDmode
1377       && optimize
1378       && CONSTANT_P (x)
1379       && rtx_cost (x, binoptab->code) > COSTS_N_INSNS (1))
1380     {
1381       if (GET_CODE (x) == CONST_INT)
1382         {
1383           HOST_WIDE_INT intval = trunc_int_for_mode (INTVAL (x), mode);
1384           if (intval != INTVAL (x))
1385             x = GEN_INT (intval);
1386         }
1387       else
1388         x = convert_modes (mode, VOIDmode, x, unsignedp);
1389       x = force_reg (mode, x);
1390     }
1391   return x;
1392 }
1393
1394 /* Helper function for expand_binop: handle the case where there
1395    is an insn that directly implements the indicated operation.
1396    Returns null if this is not possible.  */
1397 static rtx
1398 expand_binop_directly (enum machine_mode mode, optab binoptab,
1399                        rtx op0, rtx op1,
1400                        rtx target, int unsignedp, enum optab_methods methods,
1401                        rtx last)
1402 {
1403   int icode = (int) optab_handler (binoptab, mode)->insn_code;
1404   enum machine_mode mode0 = insn_data[icode].operand[1].mode;
1405   enum machine_mode mode1 = insn_data[icode].operand[2].mode;
1406   enum machine_mode tmp_mode;
1407   bool commutative_p;
1408   rtx pat;
1409   rtx xop0 = op0, xop1 = op1;
1410   rtx temp;
1411   rtx swap;
1412   
1413   if (target)
1414     temp = target;
1415   else
1416     temp = gen_reg_rtx (mode);
1417
1418   /* If it is a commutative operator and the modes would match
1419      if we would swap the operands, we can save the conversions.  */
1420   commutative_p = commutative_optab_p (binoptab);
1421   if (commutative_p
1422       && GET_MODE (xop0) != mode0 && GET_MODE (xop1) != mode1
1423       && GET_MODE (xop0) == mode1 && GET_MODE (xop1) == mode1)
1424     {
1425       swap = xop0;
1426       xop0 = xop1;
1427       xop1 = swap;
1428     }
1429   
1430   /* If we are optimizing, force expensive constants into a register.  */
1431   xop0 = avoid_expensive_constant (mode0, binoptab, xop0, unsignedp);
1432   if (!shift_optab_p (binoptab))
1433     xop1 = avoid_expensive_constant (mode1, binoptab, xop1, unsignedp);
1434
1435   /* In case the insn wants input operands in modes different from
1436      those of the actual operands, convert the operands.  It would
1437      seem that we don't need to convert CONST_INTs, but we do, so
1438      that they're properly zero-extended, sign-extended or truncated
1439      for their mode.  */
1440   
1441   if (GET_MODE (xop0) != mode0 && mode0 != VOIDmode)
1442     xop0 = convert_modes (mode0,
1443                           GET_MODE (xop0) != VOIDmode
1444                           ? GET_MODE (xop0)
1445                           : mode,
1446                           xop0, unsignedp);
1447   
1448   if (GET_MODE (xop1) != mode1 && mode1 != VOIDmode)
1449     xop1 = convert_modes (mode1,
1450                           GET_MODE (xop1) != VOIDmode
1451                           ? GET_MODE (xop1)
1452                           : mode,
1453                           xop1, unsignedp);
1454   
1455   /* If operation is commutative,
1456      try to make the first operand a register.
1457      Even better, try to make it the same as the target.
1458      Also try to make the last operand a constant.  */
1459   if (commutative_p
1460       && swap_commutative_operands_with_target (target, xop0, xop1))
1461     {
1462       swap = xop1;
1463       xop1 = xop0;
1464       xop0 = swap;
1465     }
1466
1467   /* Now, if insn's predicates don't allow our operands, put them into
1468      pseudo regs.  */
1469   
1470   if (!insn_data[icode].operand[1].predicate (xop0, mode0)
1471       && mode0 != VOIDmode)
1472     xop0 = copy_to_mode_reg (mode0, xop0);
1473   
1474   if (!insn_data[icode].operand[2].predicate (xop1, mode1)
1475       && mode1 != VOIDmode)
1476     xop1 = copy_to_mode_reg (mode1, xop1);
1477   
1478   if (binoptab == vec_pack_trunc_optab 
1479       || binoptab == vec_pack_usat_optab
1480       || binoptab == vec_pack_ssat_optab
1481       || binoptab == vec_pack_ufix_trunc_optab
1482       || binoptab == vec_pack_sfix_trunc_optab)
1483     {
1484       /* The mode of the result is different then the mode of the
1485          arguments.  */
1486       tmp_mode = insn_data[icode].operand[0].mode;
1487       if (GET_MODE_NUNITS (tmp_mode) != 2 * GET_MODE_NUNITS (mode))
1488         return 0;
1489     }
1490   else
1491     tmp_mode = mode;
1492
1493   if (!insn_data[icode].operand[0].predicate (temp, tmp_mode))
1494     temp = gen_reg_rtx (tmp_mode);
1495   
1496   pat = GEN_FCN (icode) (temp, xop0, xop1);
1497   if (pat)
1498     {
1499       /* If PAT is composed of more than one insn, try to add an appropriate
1500          REG_EQUAL note to it.  If we can't because TEMP conflicts with an
1501          operand, call expand_binop again, this time without a target.  */
1502       if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX
1503           && ! add_equal_note (pat, temp, binoptab->code, xop0, xop1))
1504         {
1505           delete_insns_since (last);
1506           return expand_binop (mode, binoptab, op0, op1, NULL_RTX,
1507                                unsignedp, methods);
1508         }
1509       
1510       emit_insn (pat);
1511       return temp;
1512     }
1513
1514   delete_insns_since (last);
1515   return NULL_RTX;
1516 }
1517
1518 /* Generate code to perform an operation specified by BINOPTAB
1519    on operands OP0 and OP1, with result having machine-mode MODE.
1520
1521    UNSIGNEDP is for the case where we have to widen the operands
1522    to perform the operation.  It says to use zero-extension.
1523
1524    If TARGET is nonzero, the value
1525    is generated there, if it is convenient to do so.
1526    In all cases an rtx is returned for the locus of the value;
1527    this may or may not be TARGET.  */
1528
1529 rtx
1530 expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
1531               rtx target, int unsignedp, enum optab_methods methods)
1532 {
1533   enum optab_methods next_methods
1534     = (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN
1535        ? OPTAB_WIDEN : methods);
1536   enum mode_class class;
1537   enum machine_mode wider_mode;
1538   rtx libfunc;
1539   rtx temp;
1540   rtx entry_last = get_last_insn ();
1541   rtx last;
1542
1543   class = GET_MODE_CLASS (mode);
1544
1545   /* If subtracting an integer constant, convert this into an addition of
1546      the negated constant.  */
1547
1548   if (binoptab == sub_optab && GET_CODE (op1) == CONST_INT)
1549     {
1550       op1 = negate_rtx (mode, op1);
1551       binoptab = add_optab;
1552     }
1553
1554   /* Record where to delete back to if we backtrack.  */
1555   last = get_last_insn ();
1556
1557   /* If we can do it with a three-operand insn, do so.  */
1558
1559   if (methods != OPTAB_MUST_WIDEN
1560       && optab_handler (binoptab, mode)->insn_code != CODE_FOR_nothing)
1561     {
1562       temp = expand_binop_directly (mode, binoptab, op0, op1, target,
1563                                     unsignedp, methods, last);
1564       if (temp)
1565         return temp;
1566     }
1567
1568   /* If we were trying to rotate, and that didn't work, try rotating
1569      the other direction before falling back to shifts and bitwise-or.  */
1570   if (((binoptab == rotl_optab
1571         && optab_handler (rotr_optab, mode)->insn_code != CODE_FOR_nothing)
1572        || (binoptab == rotr_optab
1573            && optab_handler (rotl_optab, mode)->insn_code != CODE_FOR_nothing))
1574       && class == MODE_INT)
1575     {
1576       optab otheroptab = (binoptab == rotl_optab ? rotr_optab : rotl_optab);
1577       rtx newop1;
1578       unsigned int bits = GET_MODE_BITSIZE (mode);
1579
1580       if (GET_CODE (op1) == CONST_INT)
1581         newop1 = GEN_INT (bits - INTVAL (op1));
1582       else if (targetm.shift_truncation_mask (mode) == bits - 1)
1583         newop1 = negate_rtx (mode, op1);
1584       else
1585         newop1 = expand_binop (mode, sub_optab,
1586                                GEN_INT (bits), op1,
1587                                NULL_RTX, unsignedp, OPTAB_DIRECT);
1588                                    
1589       temp = expand_binop_directly (mode, otheroptab, op0, newop1,
1590                                     target, unsignedp, methods, last);
1591       if (temp)
1592         return temp;
1593     }
1594
1595   /* If this is a multiply, see if we can do a widening operation that
1596      takes operands of this mode and makes a wider mode.  */
1597
1598   if (binoptab == smul_optab
1599       && GET_MODE_WIDER_MODE (mode) != VOIDmode
1600       && ((optab_handler ((unsignedp ? umul_widen_optab : smul_widen_optab),
1601                           GET_MODE_WIDER_MODE (mode))->insn_code)
1602           != CODE_FOR_nothing))
1603     {
1604       temp = expand_binop (GET_MODE_WIDER_MODE (mode),
1605                            unsignedp ? umul_widen_optab : smul_widen_optab,
1606                            op0, op1, NULL_RTX, unsignedp, OPTAB_DIRECT);
1607
1608       if (temp != 0)
1609         {
1610           if (GET_MODE_CLASS (mode) == MODE_INT
1611               && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
1612                                         GET_MODE_BITSIZE (GET_MODE (temp))))
1613             return gen_lowpart (mode, temp);
1614           else
1615             return convert_to_mode (mode, temp, unsignedp);
1616         }
1617     }
1618
1619   /* Look for a wider mode of the same class for which we think we
1620      can open-code the operation.  Check for a widening multiply at the
1621      wider mode as well.  */
1622
1623   if (CLASS_HAS_WIDER_MODES_P (class)
1624       && methods != OPTAB_DIRECT && methods != OPTAB_LIB)
1625     for (wider_mode = GET_MODE_WIDER_MODE (mode);
1626          wider_mode != VOIDmode;
1627          wider_mode = GET_MODE_WIDER_MODE (wider_mode))
1628       {
1629         if (optab_handler (binoptab, wider_mode)->insn_code != CODE_FOR_nothing
1630             || (binoptab == smul_optab
1631                 && GET_MODE_WIDER_MODE (wider_mode) != VOIDmode
1632                 && ((optab_handler ((unsignedp ? umul_widen_optab
1633                                      : smul_widen_optab),
1634                                      GET_MODE_WIDER_MODE (wider_mode))->insn_code)
1635                     != CODE_FOR_nothing)))
1636           {
1637             rtx xop0 = op0, xop1 = op1;
1638             int no_extend = 0;
1639
1640             /* For certain integer operations, we need not actually extend
1641                the narrow operands, as long as we will truncate
1642                the results to the same narrowness.  */
1643
1644             if ((binoptab == ior_optab || binoptab == and_optab
1645                  || binoptab == xor_optab
1646                  || binoptab == add_optab || binoptab == sub_optab
1647                  || binoptab == smul_optab || binoptab == ashl_optab)
1648                 && class == MODE_INT)
1649               {
1650                 no_extend = 1;
1651                 xop0 = avoid_expensive_constant (mode, binoptab,
1652                                                  xop0, unsignedp);
1653                 if (binoptab != ashl_optab)
1654                   xop1 = avoid_expensive_constant (mode, binoptab,
1655                                                    xop1, unsignedp);
1656               }
1657
1658             xop0 = widen_operand (xop0, wider_mode, mode, unsignedp, no_extend);
1659
1660             /* The second operand of a shift must always be extended.  */
1661             xop1 = widen_operand (xop1, wider_mode, mode, unsignedp,
1662                                   no_extend && binoptab != ashl_optab);
1663
1664             temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX,
1665                                  unsignedp, OPTAB_DIRECT);
1666             if (temp)
1667               {
1668                 if (class != MODE_INT
1669                     || !TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
1670                                                GET_MODE_BITSIZE (wider_mode)))
1671                   {
1672                     if (target == 0)
1673                       target = gen_reg_rtx (mode);
1674                     convert_move (target, temp, 0);
1675                     return target;
1676                   }
1677                 else
1678                   return gen_lowpart (mode, temp);
1679               }
1680             else
1681               delete_insns_since (last);
1682           }
1683       }
1684
1685   /* If operation is commutative,
1686      try to make the first operand a register.
1687      Even better, try to make it the same as the target.
1688      Also try to make the last operand a constant.  */
1689   if (commutative_optab_p (binoptab)
1690       && swap_commutative_operands_with_target (target, op0, op1))
1691     {
1692       temp = op1;
1693       op1 = op0;
1694       op0 = temp;
1695     }
1696
1697   /* These can be done a word at a time.  */
1698   if ((binoptab == and_optab || binoptab == ior_optab || binoptab == xor_optab)
1699       && class == MODE_INT
1700       && GET_MODE_SIZE (mode) > UNITS_PER_WORD
1701       && optab_handler (binoptab, word_mode)->insn_code != CODE_FOR_nothing)
1702     {
1703       int i;
1704       rtx insns;
1705       rtx equiv_value;
1706
1707       /* If TARGET is the same as one of the operands, the REG_EQUAL note
1708          won't be accurate, so use a new target.  */
1709       if (target == 0 || target == op0 || target == op1)
1710         target = gen_reg_rtx (mode);
1711
1712       start_sequence ();
1713
1714       /* Do the actual arithmetic.  */
1715       for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)
1716         {
1717           rtx target_piece = operand_subword (target, i, 1, mode);
1718           rtx x = expand_binop (word_mode, binoptab,
1719                                 operand_subword_force (op0, i, mode),
1720                                 operand_subword_force (op1, i, mode),
1721                                 target_piece, unsignedp, next_methods);
1722
1723           if (x == 0)
1724             break;
1725
1726           if (target_piece != x)
1727             emit_move_insn (target_piece, x);
1728         }
1729
1730       insns = get_insns ();
1731       end_sequence ();
1732
1733       if (i == GET_MODE_BITSIZE (mode) / BITS_PER_WORD)
1734         {
1735           if (binoptab->code != UNKNOWN)
1736             equiv_value
1737               = gen_rtx_fmt_ee (binoptab->code, mode,
1738                                 copy_rtx (op0), copy_rtx (op1));
1739           else
1740             equiv_value = 0;
1741
1742           emit_no_conflict_block (insns, target, op0, op1, equiv_value);
1743           return target;
1744         }
1745     }
1746
1747   /* Synthesize double word shifts from single word shifts.  */
1748   if ((binoptab == lshr_optab || binoptab == ashl_optab
1749        || binoptab == ashr_optab)
1750       && class == MODE_INT
1751       && (GET_CODE (op1) == CONST_INT || !optimize_size)
1752       && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
1753       && optab_handler (binoptab, word_mode)->insn_code != CODE_FOR_nothing
1754       && optab_handler (ashl_optab, word_mode)->insn_code != CODE_FOR_nothing
1755       && optab_handler (lshr_optab, word_mode)->insn_code != CODE_FOR_nothing)
1756     {
1757       unsigned HOST_WIDE_INT shift_mask, double_shift_mask;
1758       enum machine_mode op1_mode;
1759
1760       double_shift_mask = targetm.shift_truncation_mask (mode);
1761       shift_mask = targetm.shift_truncation_mask (word_mode);
1762       op1_mode = GET_MODE (op1) != VOIDmode ? GET_MODE (op1) : word_mode;
1763
1764       /* Apply the truncation to constant shifts.  */
1765       if (double_shift_mask > 0 && GET_CODE (op1) == CONST_INT)
1766         op1 = GEN_INT (INTVAL (op1) & double_shift_mask);
1767
1768       if (op1 == CONST0_RTX (op1_mode))
1769         return op0;
1770
1771       /* Make sure that this is a combination that expand_doubleword_shift
1772          can handle.  See the comments there for details.  */
1773       if (double_shift_mask == 0
1774           || (shift_mask == BITS_PER_WORD - 1
1775               && double_shift_mask == BITS_PER_WORD * 2 - 1))
1776         {
1777           rtx insns, equiv_value;
1778           rtx into_target, outof_target;
1779           rtx into_input, outof_input;
1780           int left_shift, outof_word;
1781
1782           /* If TARGET is the same as one of the operands, the REG_EQUAL note
1783              won't be accurate, so use a new target.  */
1784           if (target == 0 || target == op0 || target == op1)
1785             target = gen_reg_rtx (mode);
1786
1787           start_sequence ();
1788
1789           /* OUTOF_* is the word we are shifting bits away from, and
1790              INTO_* is the word that we are shifting bits towards, thus
1791              they differ depending on the direction of the shift and
1792              WORDS_BIG_ENDIAN.  */
1793
1794           left_shift = binoptab == ashl_optab;
1795           outof_word = left_shift ^ ! WORDS_BIG_ENDIAN;
1796
1797           outof_target = operand_subword (target, outof_word, 1, mode);
1798           into_target = operand_subword (target, 1 - outof_word, 1, mode);
1799
1800           outof_input = operand_subword_force (op0, outof_word, mode);
1801           into_input = operand_subword_force (op0, 1 - outof_word, mode);
1802
1803           if (expand_doubleword_shift (op1_mode, binoptab,
1804                                        outof_input, into_input, op1,
1805                                        outof_target, into_target,
1806                                        unsignedp, next_methods, shift_mask))
1807             {
1808               insns = get_insns ();
1809               end_sequence ();
1810
1811               equiv_value = gen_rtx_fmt_ee (binoptab->code, mode, op0, op1);
1812               emit_no_conflict_block (insns, target, op0, op1, equiv_value);
1813               return target;
1814             }
1815           end_sequence ();
1816         }
1817     }
1818
1819   /* Synthesize double word rotates from single word shifts.  */
1820   if ((binoptab == rotl_optab || binoptab == rotr_optab)
1821       && class == MODE_INT
1822       && GET_CODE (op1) == CONST_INT
1823       && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
1824       && optab_handler (ashl_optab, word_mode)->insn_code != CODE_FOR_nothing
1825       && optab_handler (lshr_optab, word_mode)->insn_code != CODE_FOR_nothing)
1826     {
1827       rtx insns;
1828       rtx into_target, outof_target;
1829       rtx into_input, outof_input;
1830       rtx inter;
1831       int shift_count, left_shift, outof_word;
1832
1833       /* If TARGET is the same as one of the operands, the REG_EQUAL note
1834          won't be accurate, so use a new target. Do this also if target is not
1835          a REG, first because having a register instead may open optimization
1836          opportunities, and second because if target and op0 happen to be MEMs
1837          designating the same location, we would risk clobbering it too early
1838          in the code sequence we generate below.  */
1839       if (target == 0 || target == op0 || target == op1 || ! REG_P (target))
1840         target = gen_reg_rtx (mode);
1841
1842       start_sequence ();
1843
1844       shift_count = INTVAL (op1);
1845
1846       /* OUTOF_* is the word we are shifting bits away from, and
1847          INTO_* is the word that we are shifting bits towards, thus
1848          they differ depending on the direction of the shift and
1849          WORDS_BIG_ENDIAN.  */
1850
1851       left_shift = (binoptab == rotl_optab);
1852       outof_word = left_shift ^ ! WORDS_BIG_ENDIAN;
1853
1854       outof_target = operand_subword (target, outof_word, 1, mode);
1855       into_target = operand_subword (target, 1 - outof_word, 1, mode);
1856
1857       outof_input = operand_subword_force (op0, outof_word, mode);
1858       into_input = operand_subword_force (op0, 1 - outof_word, mode);
1859
1860       if (shift_count == BITS_PER_WORD)
1861         {
1862           /* This is just a word swap.  */
1863           emit_move_insn (outof_target, into_input);
1864           emit_move_insn (into_target, outof_input);
1865           inter = const0_rtx;
1866         }
1867       else
1868         {
1869           rtx into_temp1, into_temp2, outof_temp1, outof_temp2;
1870           rtx first_shift_count, second_shift_count;
1871           optab reverse_unsigned_shift, unsigned_shift;
1872
1873           reverse_unsigned_shift = (left_shift ^ (shift_count < BITS_PER_WORD)
1874                                     ? lshr_optab : ashl_optab);
1875
1876           unsigned_shift = (left_shift ^ (shift_count < BITS_PER_WORD)
1877                             ? ashl_optab : lshr_optab);
1878
1879           if (shift_count > BITS_PER_WORD)
1880             {
1881               first_shift_count = GEN_INT (shift_count - BITS_PER_WORD);
1882               second_shift_count = GEN_INT (2 * BITS_PER_WORD - shift_count);
1883             }
1884           else
1885             {
1886               first_shift_count = GEN_INT (BITS_PER_WORD - shift_count);
1887               second_shift_count = GEN_INT (shift_count);
1888             }
1889
1890           into_temp1 = expand_binop (word_mode, unsigned_shift,
1891                                      outof_input, first_shift_count,
1892                                      NULL_RTX, unsignedp, next_methods);
1893           into_temp2 = expand_binop (word_mode, reverse_unsigned_shift,
1894                                      into_input, second_shift_count,
1895                                      NULL_RTX, unsignedp, next_methods);
1896
1897           if (into_temp1 != 0 && into_temp2 != 0)
1898             inter = expand_binop (word_mode, ior_optab, into_temp1, into_temp2,
1899                                   into_target, unsignedp, next_methods);
1900           else
1901             inter = 0;
1902
1903           if (inter != 0 && inter != into_target)
1904             emit_move_insn (into_target, inter);
1905
1906           outof_temp1 = expand_binop (word_mode, unsigned_shift,
1907                                       into_input, first_shift_count,
1908                                       NULL_RTX, unsignedp, next_methods);
1909           outof_temp2 = expand_binop (word_mode, reverse_unsigned_shift,
1910                                       outof_input, second_shift_count,
1911                                       NULL_RTX, unsignedp, next_methods);
1912
1913           if (inter != 0 && outof_temp1 != 0 && outof_temp2 != 0)
1914             inter = expand_binop (word_mode, ior_optab,
1915                                   outof_temp1, outof_temp2,
1916                                   outof_target, unsignedp, next_methods);
1917
1918           if (inter != 0 && inter != outof_target)
1919             emit_move_insn (outof_target, inter);
1920         }
1921
1922       insns = get_insns ();
1923       end_sequence ();
1924
1925       if (inter != 0)
1926         {
1927           /* One may be tempted to wrap the insns in a REG_NO_CONFLICT
1928              block to help the register allocator a bit.  But a multi-word
1929              rotate will need all the input bits when setting the output
1930              bits, so there clearly is a conflict between the input and
1931              output registers.  So we can't use a no-conflict block here.  */
1932           emit_insn (insns);
1933           return target;
1934         }
1935     }
1936
1937   /* These can be done a word at a time by propagating carries.  */
1938   if ((binoptab == add_optab || binoptab == sub_optab)
1939       && class == MODE_INT
1940       && GET_MODE_SIZE (mode) >= 2 * UNITS_PER_WORD
1941       && optab_handler (binoptab, word_mode)->insn_code != CODE_FOR_nothing)
1942     {
1943       unsigned int i;
1944       optab otheroptab = binoptab == add_optab ? sub_optab : add_optab;
1945       const unsigned int nwords = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
1946       rtx carry_in = NULL_RTX, carry_out = NULL_RTX;
1947       rtx xop0, xop1, xtarget;
1948
1949       /* We can handle either a 1 or -1 value for the carry.  If STORE_FLAG
1950          value is one of those, use it.  Otherwise, use 1 since it is the
1951          one easiest to get.  */
1952 #if STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1
1953       int normalizep = STORE_FLAG_VALUE;
1954 #else
1955       int normalizep = 1;
1956 #endif
1957
1958       /* Prepare the operands.  */
1959       xop0 = force_reg (mode, op0);
1960       xop1 = force_reg (mode, op1);
1961
1962       xtarget = gen_reg_rtx (mode);
1963
1964       if (target == 0 || !REG_P (target))
1965         target = xtarget;
1966
1967       /* Indicate for flow that the entire target reg is being set.  */
1968       if (REG_P (target))
1969         emit_insn (gen_rtx_CLOBBER (VOIDmode, xtarget));
1970
1971       /* Do the actual arithmetic.  */
1972       for (i = 0; i < nwords; i++)
1973         {
1974           int index = (WORDS_BIG_ENDIAN ? nwords - i - 1 : i);
1975           rtx target_piece = operand_subword (xtarget, index, 1, mode);
1976           rtx op0_piece = operand_subword_force (xop0, index, mode);
1977           rtx op1_piece = operand_subword_force (xop1, index, mode);
1978           rtx x;
1979
1980           /* Main add/subtract of the input operands.  */
1981           x = expand_binop (word_mode, binoptab,
1982                             op0_piece, op1_piece,
1983                             target_piece, unsignedp, next_methods);
1984           if (x == 0)
1985             break;
1986
1987           if (i + 1 < nwords)
1988             {
1989               /* Store carry from main add/subtract.  */
1990               carry_out = gen_reg_rtx (word_mode);
1991               carry_out = emit_store_flag_force (carry_out,
1992                                                  (binoptab == add_optab
1993                                                   ? LT : GT),
1994                                                  x, op0_piece,
1995                                                  word_mode, 1, normalizep);
1996             }
1997
1998           if (i > 0)
1999             {
2000               rtx newx;
2001
2002               /* Add/subtract previous carry to main result.  */
2003               newx = expand_binop (word_mode,
2004                                    normalizep == 1 ? binoptab : otheroptab,
2005                                    x, carry_in,
2006                                    NULL_RTX, 1, next_methods);
2007
2008               if (i + 1 < nwords)
2009                 {
2010                   /* Get out carry from adding/subtracting carry in.  */
2011                   rtx carry_tmp = gen_reg_rtx (word_mode);
2012                   carry_tmp = emit_store_flag_force (carry_tmp,
2013                                                      (binoptab == add_optab
2014                                                       ? LT : GT),
2015                                                      newx, x,
2016                                                      word_mode, 1, normalizep);
2017
2018                   /* Logical-ior the two poss. carry together.  */
2019                   carry_out = expand_binop (word_mode, ior_optab,
2020                                             carry_out, carry_tmp,
2021                                             carry_out, 0, next_methods);
2022                   if (carry_out == 0)
2023                     break;
2024                 }
2025               emit_move_insn (target_piece, newx);
2026             }
2027           else
2028             {
2029               if (x != target_piece)
2030                 emit_move_insn (target_piece, x);
2031             }
2032
2033           carry_in = carry_out;
2034         }
2035
2036       if (i == GET_MODE_BITSIZE (mode) / (unsigned) BITS_PER_WORD)
2037         {
2038           if (optab_handler (mov_optab, mode)->insn_code != CODE_FOR_nothing
2039               || ! rtx_equal_p (target, xtarget))
2040             {
2041               rtx temp = emit_move_insn (target, xtarget);
2042
2043               set_unique_reg_note (temp,
2044                                    REG_EQUAL,
2045                                    gen_rtx_fmt_ee (binoptab->code, mode,
2046                                                    copy_rtx (xop0),
2047                                                    copy_rtx (xop1)));
2048             }
2049           else
2050             target = xtarget;
2051
2052           return target;
2053         }
2054
2055       else
2056         delete_insns_since (last);
2057     }
2058
2059   /* Attempt to synthesize double word multiplies using a sequence of word
2060      mode multiplications.  We first attempt to generate a sequence using a
2061      more efficient unsigned widening multiply, and if that fails we then
2062      try using a signed widening multiply.  */
2063
2064   if (binoptab == smul_optab
2065       && class == MODE_INT
2066       && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
2067       && optab_handler (smul_optab, word_mode)->insn_code != CODE_FOR_nothing
2068       && optab_handler (add_optab, word_mode)->insn_code != CODE_FOR_nothing)
2069     {
2070       rtx product = NULL_RTX;
2071
2072       if (optab_handler (umul_widen_optab, mode)->insn_code
2073           != CODE_FOR_nothing)
2074         {
2075           product = expand_doubleword_mult (mode, op0, op1, target,
2076                                             true, methods);
2077           if (!product)
2078             delete_insns_since (last);
2079         }
2080
2081       if (product == NULL_RTX
2082           && optab_handler (smul_widen_optab, mode)->insn_code
2083              != CODE_FOR_nothing)
2084         {
2085           product = expand_doubleword_mult (mode, op0, op1, target,
2086                                             false, methods);
2087           if (!product)
2088             delete_insns_since (last);
2089         }
2090
2091       if (product != NULL_RTX)
2092         {
2093           if (optab_handler (mov_optab, mode)->insn_code != CODE_FOR_nothing)
2094             {
2095               temp = emit_move_insn (target ? target : product, product);
2096               set_unique_reg_note (temp,
2097                                    REG_EQUAL,
2098                                    gen_rtx_fmt_ee (MULT, mode,
2099                                                    copy_rtx (op0),
2100                                                    copy_rtx (op1)));
2101             }
2102           return product;
2103         }
2104     }
2105
2106   /* It can't be open-coded in this mode.
2107      Use a library call if one is available and caller says that's ok.  */
2108
2109   libfunc = optab_libfunc (binoptab, mode);
2110   if (libfunc
2111       && (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN))
2112     {
2113       rtx insns;
2114       rtx op1x = op1;
2115       enum machine_mode op1_mode = mode;
2116       rtx value;
2117
2118       start_sequence ();
2119
2120       if (shift_optab_p (binoptab))
2121         {
2122           op1_mode = targetm.libgcc_shift_count_mode ();
2123           /* Specify unsigned here,
2124              since negative shift counts are meaningless.  */
2125           op1x = convert_to_mode (op1_mode, op1, 1);
2126         }
2127
2128       if (GET_MODE (op0) != VOIDmode
2129           && GET_MODE (op0) != mode)
2130         op0 = convert_to_mode (mode, op0, unsignedp);
2131
2132       /* Pass 1 for NO_QUEUE so we don't lose any increments
2133          if the libcall is cse'd or moved.  */
2134       value = emit_library_call_value (libfunc,
2135                                        NULL_RTX, LCT_CONST, mode, 2,
2136                                        op0, mode, op1x, op1_mode);
2137
2138       insns = get_insns ();
2139       end_sequence ();
2140
2141       target = gen_reg_rtx (mode);
2142       emit_libcall_block (insns, target, value,
2143                           gen_rtx_fmt_ee (binoptab->code, mode, op0, op1));
2144
2145       return target;
2146     }
2147
2148   delete_insns_since (last);
2149
2150   /* It can't be done in this mode.  Can we do it in a wider mode?  */
2151
2152   if (! (methods == OPTAB_WIDEN || methods == OPTAB_LIB_WIDEN
2153          || methods == OPTAB_MUST_WIDEN))
2154     {
2155       /* Caller says, don't even try.  */
2156       delete_insns_since (entry_last);
2157       return 0;
2158     }
2159
2160   /* Compute the value of METHODS to pass to recursive calls.
2161      Don't allow widening to be tried recursively.  */
2162
2163   methods = (methods == OPTAB_LIB_WIDEN ? OPTAB_LIB : OPTAB_DIRECT);
2164
2165   /* Look for a wider mode of the same class for which it appears we can do
2166      the operation.  */
2167
2168   if (CLASS_HAS_WIDER_MODES_P (class))
2169     {
2170       for (wider_mode = GET_MODE_WIDER_MODE (mode);
2171            wider_mode != VOIDmode;
2172            wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2173         {
2174           if ((optab_handler (binoptab, wider_mode)->insn_code
2175                != CODE_FOR_nothing)
2176               || (methods == OPTAB_LIB
2177                   && optab_libfunc (binoptab, wider_mode)))
2178             {
2179               rtx xop0 = op0, xop1 = op1;
2180               int no_extend = 0;
2181
2182               /* For certain integer operations, we need not actually extend
2183                  the narrow operands, as long as we will truncate
2184                  the results to the same narrowness.  */
2185
2186               if ((binoptab == ior_optab || binoptab == and_optab
2187                    || binoptab == xor_optab
2188                    || binoptab == add_optab || binoptab == sub_optab
2189                    || binoptab == smul_optab || binoptab == ashl_optab)
2190                   && class == MODE_INT)
2191                 no_extend = 1;
2192
2193               xop0 = widen_operand (xop0, wider_mode, mode,
2194                                     unsignedp, no_extend);
2195
2196               /* The second operand of a shift must always be extended.  */
2197               xop1 = widen_operand (xop1, wider_mode, mode, unsignedp,
2198                                     no_extend && binoptab != ashl_optab);
2199
2200               temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX,
2201                                    unsignedp, methods);
2202               if (temp)
2203                 {
2204                   if (class != MODE_INT
2205                       || !TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
2206                                                  GET_MODE_BITSIZE (wider_mode)))
2207                     {
2208                       if (target == 0)
2209                         target = gen_reg_rtx (mode);
2210                       convert_move (target, temp, 0);
2211                       return target;
2212                     }
2213                   else
2214                     return gen_lowpart (mode, temp);
2215                 }
2216               else
2217                 delete_insns_since (last);
2218             }
2219         }
2220     }
2221
2222   delete_insns_since (entry_last);
2223   return 0;
2224 }
2225 \f
2226 /* Expand a binary operator which has both signed and unsigned forms.
2227    UOPTAB is the optab for unsigned operations, and SOPTAB is for
2228    signed operations.
2229
2230    If we widen unsigned operands, we may use a signed wider operation instead
2231    of an unsigned wider operation, since the result would be the same.  */
2232
2233 rtx
2234 sign_expand_binop (enum machine_mode mode, optab uoptab, optab soptab,
2235                    rtx op0, rtx op1, rtx target, int unsignedp,
2236                    enum optab_methods methods)
2237 {
2238   rtx temp;
2239   optab direct_optab = unsignedp ? uoptab : soptab;
2240   struct optab wide_soptab;
2241
2242   /* Do it without widening, if possible.  */
2243   temp = expand_binop (mode, direct_optab, op0, op1, target,
2244                        unsignedp, OPTAB_DIRECT);
2245   if (temp || methods == OPTAB_DIRECT)
2246     return temp;
2247
2248   /* Try widening to a signed int.  Make a fake signed optab that
2249      hides any signed insn for direct use.  */
2250   wide_soptab = *soptab;
2251   optab_handler (&wide_soptab, mode)->insn_code = CODE_FOR_nothing;
2252
2253   temp = expand_binop (mode, &wide_soptab, op0, op1, target,
2254                        unsignedp, OPTAB_WIDEN);
2255
2256   /* For unsigned operands, try widening to an unsigned int.  */
2257   if (temp == 0 && unsignedp)
2258     temp = expand_binop (mode, uoptab, op0, op1, target,
2259                          unsignedp, OPTAB_WIDEN);
2260   if (temp || methods == OPTAB_WIDEN)
2261     return temp;
2262
2263   /* Use the right width lib call if that exists.  */
2264   temp = expand_binop (mode, direct_optab, op0, op1, target, unsignedp, OPTAB_LIB);
2265   if (temp || methods == OPTAB_LIB)
2266     return temp;
2267
2268   /* Must widen and use a lib call, use either signed or unsigned.  */
2269   temp = expand_binop (mode, &wide_soptab, op0, op1, target,
2270                        unsignedp, methods);
2271   if (temp != 0)
2272     return temp;
2273   if (unsignedp)
2274     return expand_binop (mode, uoptab, op0, op1, target,
2275                          unsignedp, methods);
2276   return 0;
2277 }
2278 \f
2279 /* Generate code to perform an operation specified by UNOPPTAB
2280    on operand OP0, with two results to TARG0 and TARG1.
2281    We assume that the order of the operands for the instruction
2282    is TARG0, TARG1, OP0.
2283
2284    Either TARG0 or TARG1 may be zero, but what that means is that
2285    the result is not actually wanted.  We will generate it into
2286    a dummy pseudo-reg and discard it.  They may not both be zero.
2287
2288    Returns 1 if this operation can be performed; 0 if not.  */
2289
2290 int
2291 expand_twoval_unop (optab unoptab, rtx op0, rtx targ0, rtx targ1,
2292                     int unsignedp)
2293 {
2294   enum machine_mode mode = GET_MODE (targ0 ? targ0 : targ1);
2295   enum mode_class class;
2296   enum machine_mode wider_mode;
2297   rtx entry_last = get_last_insn ();
2298   rtx last;
2299
2300   class = GET_MODE_CLASS (mode);
2301
2302   if (!targ0)
2303     targ0 = gen_reg_rtx (mode);
2304   if (!targ1)
2305     targ1 = gen_reg_rtx (mode);
2306
2307   /* Record where to go back to if we fail.  */
2308   last = get_last_insn ();
2309
2310   if (optab_handler (unoptab, mode)->insn_code != CODE_FOR_nothing)
2311     {
2312       int icode = (int) optab_handler (unoptab, mode)->insn_code;
2313       enum machine_mode mode0 = insn_data[icode].operand[2].mode;
2314       rtx pat;
2315       rtx xop0 = op0;
2316
2317       if (GET_MODE (xop0) != VOIDmode
2318           && GET_MODE (xop0) != mode0)
2319         xop0 = convert_to_mode (mode0, xop0, unsignedp);
2320
2321       /* Now, if insn doesn't accept these operands, put them into pseudos.  */
2322       if (!insn_data[icode].operand[2].predicate (xop0, mode0))
2323         xop0 = copy_to_mode_reg (mode0, xop0);
2324
2325       /* We could handle this, but we should always be called with a pseudo
2326          for our targets and all insns should take them as outputs.  */
2327       gcc_assert (insn_data[icode].operand[0].predicate (targ0, mode));
2328       gcc_assert (insn_data[icode].operand[1].predicate (targ1, mode));
2329
2330       pat = GEN_FCN (icode) (targ0, targ1, xop0);
2331       if (pat)
2332         {
2333           emit_insn (pat);
2334           return 1;
2335         }
2336       else
2337         delete_insns_since (last);
2338     }
2339
2340   /* It can't be done in this mode.  Can we do it in a wider mode?  */
2341
2342   if (CLASS_HAS_WIDER_MODES_P (class))
2343     {
2344       for (wider_mode = GET_MODE_WIDER_MODE (mode);
2345            wider_mode != VOIDmode;
2346            wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2347         {
2348           if (optab_handler (unoptab, wider_mode)->insn_code
2349               != CODE_FOR_nothing)
2350             {
2351               rtx t0 = gen_reg_rtx (wider_mode);
2352               rtx t1 = gen_reg_rtx (wider_mode);
2353               rtx cop0 = convert_modes (wider_mode, mode, op0, unsignedp);
2354
2355               if (expand_twoval_unop (unoptab, cop0, t0, t1, unsignedp))
2356                 {
2357                   convert_move (targ0, t0, unsignedp);
2358                   convert_move (targ1, t1, unsignedp);
2359                   return 1;
2360                 }
2361               else
2362                 delete_insns_since (last);
2363             }
2364         }
2365     }
2366
2367   delete_insns_since (entry_last);
2368   return 0;
2369 }
2370 \f
2371 /* Generate code to perform an operation specified by BINOPTAB
2372    on operands OP0 and OP1, with two results to TARG1 and TARG2.
2373    We assume that the order of the operands for the instruction
2374    is TARG0, OP0, OP1, TARG1, which would fit a pattern like
2375    [(set TARG0 (operate OP0 OP1)) (set TARG1 (operate ...))].
2376
2377    Either TARG0 or TARG1 may be zero, but what that means is that
2378    the result is not actually wanted.  We will generate it into
2379    a dummy pseudo-reg and discard it.  They may not both be zero.
2380
2381    Returns 1 if this operation can be performed; 0 if not.  */
2382
2383 int
2384 expand_twoval_binop (optab binoptab, rtx op0, rtx op1, rtx targ0, rtx targ1,
2385                      int unsignedp)
2386 {
2387   enum machine_mode mode = GET_MODE (targ0 ? targ0 : targ1);
2388   enum mode_class class;
2389   enum machine_mode wider_mode;
2390   rtx entry_last = get_last_insn ();
2391   rtx last;
2392
2393   class = GET_MODE_CLASS (mode);
2394
2395   if (!targ0)
2396     targ0 = gen_reg_rtx (mode);
2397   if (!targ1)
2398     targ1 = gen_reg_rtx (mode);
2399
2400   /* Record where to go back to if we fail.  */
2401   last = get_last_insn ();
2402
2403   if (optab_handler (binoptab, mode)->insn_code != CODE_FOR_nothing)
2404     {
2405       int icode = (int) optab_handler (binoptab, mode)->insn_code;
2406       enum machine_mode mode0 = insn_data[icode].operand[1].mode;
2407       enum machine_mode mode1 = insn_data[icode].operand[2].mode;
2408       rtx pat;
2409       rtx xop0 = op0, xop1 = op1;
2410
2411       /* If we are optimizing, force expensive constants into a register.  */
2412       xop0 = avoid_expensive_constant (mode0, binoptab, xop0, unsignedp);
2413       xop1 = avoid_expensive_constant (mode1, binoptab, xop1, unsignedp);
2414
2415       /* In case the insn wants input operands in modes different from
2416          those of the actual operands, convert the operands.  It would
2417          seem that we don't need to convert CONST_INTs, but we do, so
2418          that they're properly zero-extended, sign-extended or truncated
2419          for their mode.  */
2420
2421       if (GET_MODE (op0) != mode0 && mode0 != VOIDmode)
2422         xop0 = convert_modes (mode0,
2423                               GET_MODE (op0) != VOIDmode
2424                               ? GET_MODE (op0)
2425                               : mode,
2426                               xop0, unsignedp);
2427
2428       if (GET_MODE (op1) != mode1 && mode1 != VOIDmode)
2429         xop1 = convert_modes (mode1,
2430                               GET_MODE (op1) != VOIDmode
2431                               ? GET_MODE (op1)
2432                               : mode,
2433                               xop1, unsignedp);
2434
2435       /* Now, if insn doesn't accept these operands, put them into pseudos.  */
2436       if (!insn_data[icode].operand[1].predicate (xop0, mode0))
2437         xop0 = copy_to_mode_reg (mode0, xop0);
2438
2439       if (!insn_data[icode].operand[2].predicate (xop1, mode1))
2440         xop1 = copy_to_mode_reg (mode1, xop1);
2441
2442       /* We could handle this, but we should always be called with a pseudo
2443          for our targets and all insns should take them as outputs.  */
2444       gcc_assert (insn_data[icode].operand[0].predicate (targ0, mode));
2445       gcc_assert (insn_data[icode].operand[3].predicate (targ1, mode));
2446
2447       pat = GEN_FCN (icode) (targ0, xop0, xop1, targ1);
2448       if (pat)
2449         {
2450           emit_insn (pat);
2451           return 1;
2452         }
2453       else
2454         delete_insns_since (last);
2455     }
2456
2457   /* It can't be done in this mode.  Can we do it in a wider mode?  */
2458
2459   if (CLASS_HAS_WIDER_MODES_P (class))
2460     {
2461       for (wider_mode = GET_MODE_WIDER_MODE (mode);
2462            wider_mode != VOIDmode;
2463            wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2464         {
2465           if (optab_handler (binoptab, wider_mode)->insn_code
2466               != CODE_FOR_nothing)
2467             {
2468               rtx t0 = gen_reg_rtx (wider_mode);
2469               rtx t1 = gen_reg_rtx (wider_mode);
2470               rtx cop0 = convert_modes (wider_mode, mode, op0, unsignedp);
2471               rtx cop1 = convert_modes (wider_mode, mode, op1, unsignedp);
2472
2473               if (expand_twoval_binop (binoptab, cop0, cop1,
2474                                        t0, t1, unsignedp))
2475                 {
2476                   convert_move (targ0, t0, unsignedp);
2477                   convert_move (targ1, t1, unsignedp);
2478                   return 1;
2479                 }
2480               else
2481                 delete_insns_since (last);
2482             }
2483         }
2484     }
2485
2486   delete_insns_since (entry_last);
2487   return 0;
2488 }
2489
2490 /* Expand the two-valued library call indicated by BINOPTAB, but
2491    preserve only one of the values.  If TARG0 is non-NULL, the first
2492    value is placed into TARG0; otherwise the second value is placed
2493    into TARG1.  Exactly one of TARG0 and TARG1 must be non-NULL.  The
2494    value stored into TARG0 or TARG1 is equivalent to (CODE OP0 OP1).
2495    This routine assumes that the value returned by the library call is
2496    as if the return value was of an integral mode twice as wide as the
2497    mode of OP0.  Returns 1 if the call was successful.  */
2498
2499 bool
2500 expand_twoval_binop_libfunc (optab binoptab, rtx op0, rtx op1,
2501                              rtx targ0, rtx targ1, enum rtx_code code)
2502 {
2503   enum machine_mode mode;
2504   enum machine_mode libval_mode;
2505   rtx libval;
2506   rtx insns;
2507   rtx libfunc;
2508
2509   /* Exactly one of TARG0 or TARG1 should be non-NULL.  */
2510   gcc_assert (!targ0 != !targ1);
2511
2512   mode = GET_MODE (op0);
2513   libfunc = optab_libfunc (binoptab, mode);
2514   if (!libfunc)
2515     return false;
2516
2517   /* The value returned by the library function will have twice as
2518      many bits as the nominal MODE.  */
2519   libval_mode = smallest_mode_for_size (2 * GET_MODE_BITSIZE (mode),
2520                                         MODE_INT);
2521   start_sequence ();
2522   libval = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
2523                                     libval_mode, 2,
2524                                     op0, mode,
2525                                     op1, mode);
2526   /* Get the part of VAL containing the value that we want.  */
2527   libval = simplify_gen_subreg (mode, libval, libval_mode,
2528                                 targ0 ? 0 : GET_MODE_SIZE (mode));
2529   insns = get_insns ();
2530   end_sequence ();
2531   /* Move the into the desired location.  */
2532   emit_libcall_block (insns, targ0 ? targ0 : targ1, libval,
2533                       gen_rtx_fmt_ee (code, mode, op0, op1));
2534
2535   return true;
2536 }
2537
2538 \f
2539 /* Wrapper around expand_unop which takes an rtx code to specify
2540    the operation to perform, not an optab pointer.  All other
2541    arguments are the same.  */
2542 rtx
2543 expand_simple_unop (enum machine_mode mode, enum rtx_code code, rtx op0,
2544                     rtx target, int unsignedp)
2545 {
2546   optab unop = code_to_optab[(int) code];
2547   gcc_assert (unop);
2548
2549   return expand_unop (mode, unop, op0, target, unsignedp);
2550 }
2551
2552 /* Try calculating
2553         (clz:narrow x)
2554    as
2555         (clz:wide (zero_extend:wide x)) - ((width wide) - (width narrow)).  */
2556 static rtx
2557 widen_clz (enum machine_mode mode, rtx op0, rtx target)
2558 {
2559   enum mode_class class = GET_MODE_CLASS (mode);
2560   if (CLASS_HAS_WIDER_MODES_P (class))
2561     {
2562       enum machine_mode wider_mode;
2563       for (wider_mode = GET_MODE_WIDER_MODE (mode);
2564            wider_mode != VOIDmode;
2565            wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2566         {
2567           if (optab_handler (clz_optab, wider_mode)->insn_code
2568               != CODE_FOR_nothing)
2569             {
2570               rtx xop0, temp, last;
2571
2572               last = get_last_insn ();
2573
2574               if (target == 0)
2575                 target = gen_reg_rtx (mode);
2576               xop0 = widen_operand (op0, wider_mode, mode, true, false);
2577               temp = expand_unop (wider_mode, clz_optab, xop0, NULL_RTX, true);
2578               if (temp != 0)
2579                 temp = expand_binop (wider_mode, sub_optab, temp,
2580                                      GEN_INT (GET_MODE_BITSIZE (wider_mode)
2581                                               - GET_MODE_BITSIZE (mode)),
2582                                      target, true, OPTAB_DIRECT);
2583               if (temp == 0)
2584                 delete_insns_since (last);
2585
2586               return temp;
2587             }
2588         }
2589     }
2590   return 0;
2591 }
2592
2593 /* Try calculating clz of a double-word quantity as two clz's of word-sized
2594    quantities, choosing which based on whether the high word is nonzero.  */
2595 static rtx
2596 expand_doubleword_clz (enum machine_mode mode, rtx op0, rtx target)
2597 {
2598   rtx xop0 = force_reg (mode, op0);
2599   rtx subhi = gen_highpart (word_mode, xop0);
2600   rtx sublo = gen_lowpart (word_mode, xop0);
2601   rtx hi0_label = gen_label_rtx ();
2602   rtx after_label = gen_label_rtx ();
2603   rtx seq, temp, result;
2604
2605   /* If we were not given a target, use a word_mode register, not a
2606      'mode' register.  The result will fit, and nobody is expecting
2607      anything bigger (the return type of __builtin_clz* is int).  */
2608   if (!target)
2609     target = gen_reg_rtx (word_mode);
2610
2611   /* In any case, write to a word_mode scratch in both branches of the
2612      conditional, so we can ensure there is a single move insn setting
2613      'target' to tag a REG_EQUAL note on.  */
2614   result = gen_reg_rtx (word_mode);
2615
2616   start_sequence ();
2617
2618   /* If the high word is not equal to zero,
2619      then clz of the full value is clz of the high word.  */
2620   emit_cmp_and_jump_insns (subhi, CONST0_RTX (word_mode), EQ, 0,
2621                            word_mode, true, hi0_label);
2622
2623   temp = expand_unop_direct (word_mode, clz_optab, subhi, result, true);
2624   if (!temp)
2625     goto fail;
2626
2627   if (temp != result)
2628     convert_move (result, temp, true);
2629
2630   emit_jump_insn (gen_jump (after_label));
2631   emit_barrier ();
2632
2633   /* Else clz of the full value is clz of the low word plus the number
2634      of bits in the high word.  */
2635   emit_label (hi0_label);
2636
2637   temp = expand_unop_direct (word_mode, clz_optab, sublo, 0, true);
2638   if (!temp)
2639     goto fail;
2640   temp = expand_binop (word_mode, add_optab, temp,
2641                        GEN_INT (GET_MODE_BITSIZE (word_mode)),
2642                        result, true, OPTAB_DIRECT);
2643   if (!temp)
2644     goto fail;
2645   if (temp != result)
2646     convert_move (result, temp, true);
2647
2648   emit_label (after_label);
2649   convert_move (target, result, true);
2650
2651   seq = get_insns ();
2652   end_sequence ();
2653
2654   add_equal_note (seq, target, CLZ, xop0, 0);
2655   emit_insn (seq);
2656   return target;
2657
2658  fail:
2659   end_sequence ();
2660   return 0;
2661 }
2662
2663 /* Try calculating
2664         (bswap:narrow x)
2665    as
2666         (lshiftrt:wide (bswap:wide x) ((width wide) - (width narrow))).  */
2667 static rtx
2668 widen_bswap (enum machine_mode mode, rtx op0, rtx target)
2669 {
2670   enum mode_class class = GET_MODE_CLASS (mode);
2671   enum machine_mode wider_mode;
2672   rtx x, last;
2673
2674   if (!CLASS_HAS_WIDER_MODES_P (class))
2675     return NULL_RTX;
2676
2677   for (wider_mode = GET_MODE_WIDER_MODE (mode);
2678        wider_mode != VOIDmode;
2679        wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2680     if (optab_handler (bswap_optab, wider_mode)->insn_code != CODE_FOR_nothing)
2681       goto found;
2682   return NULL_RTX;
2683
2684  found:
2685   last = get_last_insn ();
2686
2687   x = widen_operand (op0, wider_mode, mode, true, true);
2688   x = expand_unop (wider_mode, bswap_optab, x, NULL_RTX, true);
2689
2690   if (x != 0)
2691     x = expand_shift (RSHIFT_EXPR, wider_mode, x,
2692                       size_int (GET_MODE_BITSIZE (wider_mode)
2693                                 - GET_MODE_BITSIZE (mode)),
2694                       NULL_RTX, true);
2695
2696   if (x != 0)
2697     {
2698       if (target == 0)
2699         target = gen_reg_rtx (mode);
2700       emit_move_insn (target, gen_lowpart (mode, x));
2701     }
2702   else
2703     delete_insns_since (last);
2704
2705   return target;
2706 }
2707
2708 /* Try calculating bswap as two bswaps of two word-sized operands.  */
2709
2710 static rtx
2711 expand_doubleword_bswap (enum machine_mode mode, rtx op, rtx target)
2712 {
2713   rtx t0, t1;
2714
2715   t1 = expand_unop (word_mode, bswap_optab,
2716                     operand_subword_force (op, 0, mode), NULL_RTX, true);
2717   t0 = expand_unop (word_mode, bswap_optab,
2718                     operand_subword_force (op, 1, mode), NULL_RTX, true);
2719
2720   if (target == 0)
2721     target = gen_reg_rtx (mode);
2722   if (REG_P (target))
2723     emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
2724   emit_move_insn (operand_subword (target, 0, 1, mode), t0);
2725   emit_move_insn (operand_subword (target, 1, 1, mode), t1);
2726
2727   return target;
2728 }
2729
2730 /* Try calculating (parity x) as (and (popcount x) 1), where
2731    popcount can also be done in a wider mode.  */
2732 static rtx
2733 expand_parity (enum machine_mode mode, rtx op0, rtx target)
2734 {
2735   enum mode_class class = GET_MODE_CLASS (mode);
2736   if (CLASS_HAS_WIDER_MODES_P (class))
2737     {
2738       enum machine_mode wider_mode;
2739       for (wider_mode = mode; wider_mode != VOIDmode;
2740            wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2741         {
2742           if (optab_handler (popcount_optab, wider_mode)->insn_code
2743               != CODE_FOR_nothing)
2744             {
2745               rtx xop0, temp, last;
2746
2747               last = get_last_insn ();
2748
2749               if (target == 0)
2750                 target = gen_reg_rtx (mode);
2751               xop0 = widen_operand (op0, wider_mode, mode, true, false);
2752               temp = expand_unop (wider_mode, popcount_optab, xop0, NULL_RTX,
2753                                   true);
2754               if (temp != 0)
2755                 temp = expand_binop (wider_mode, and_optab, temp, const1_rtx,
2756                                      target, true, OPTAB_DIRECT);
2757               if (temp == 0)
2758                 delete_insns_since (last);
2759
2760               return temp;
2761             }
2762         }
2763     }
2764   return 0;
2765 }
2766
2767 /* Try calculating ctz(x) as K - clz(x & -x) ,
2768    where K is GET_MODE_BITSIZE(mode) - 1.
2769
2770    Both __builtin_ctz and __builtin_clz are undefined at zero, so we
2771    don't have to worry about what the hardware does in that case.  (If
2772    the clz instruction produces the usual value at 0, which is K, the
2773    result of this code sequence will be -1; expand_ffs, below, relies
2774    on this.  It might be nice to have it be K instead, for consistency
2775    with the (very few) processors that provide a ctz with a defined
2776    value, but that would take one more instruction, and it would be
2777    less convenient for expand_ffs anyway.  */
2778
2779 static rtx
2780 expand_ctz (enum machine_mode mode, rtx op0, rtx target)
2781 {
2782   rtx seq, temp;
2783   
2784   if (optab_handler (clz_optab, mode)->insn_code == CODE_FOR_nothing)
2785     return 0;
2786   
2787   start_sequence ();
2788
2789   temp = expand_unop_direct (mode, neg_optab, op0, NULL_RTX, true);
2790   if (temp)
2791     temp = expand_binop (mode, and_optab, op0, temp, NULL_RTX,
2792                          true, OPTAB_DIRECT);
2793   if (temp)
2794     temp = expand_unop_direct (mode, clz_optab, temp, NULL_RTX, true);
2795   if (temp)
2796     temp = expand_binop (mode, sub_optab, GEN_INT (GET_MODE_BITSIZE (mode) - 1),
2797                          temp, target,
2798                          true, OPTAB_DIRECT);
2799   if (temp == 0)
2800     {
2801       end_sequence ();
2802       return 0;
2803     }
2804
2805   seq = get_insns ();
2806   end_sequence ();
2807
2808   add_equal_note (seq, temp, CTZ, op0, 0);
2809   emit_insn (seq);
2810   return temp;
2811 }
2812
2813
2814 /* Try calculating ffs(x) using ctz(x) if we have that instruction, or
2815    else with the sequence used by expand_clz.
2816    
2817    The ffs builtin promises to return zero for a zero value and ctz/clz
2818    may have an undefined value in that case.  If they do not give us a
2819    convenient value, we have to generate a test and branch.  */
2820 static rtx
2821 expand_ffs (enum machine_mode mode, rtx op0, rtx target)
2822 {
2823   HOST_WIDE_INT val = 0;
2824   bool defined_at_zero = false;
2825   rtx temp, seq;
2826
2827   if (optab_handler (ctz_optab, mode)->insn_code != CODE_FOR_nothing)
2828     {
2829       start_sequence ();
2830
2831       temp = expand_unop_direct (mode, ctz_optab, op0, 0, true);
2832       if (!temp)
2833         goto fail;
2834
2835       defined_at_zero = (CTZ_DEFINED_VALUE_AT_ZERO (mode, val) == 2);
2836     }
2837   else if (optab_handler (clz_optab, mode)->insn_code != CODE_FOR_nothing)
2838     {
2839       start_sequence ();
2840       temp = expand_ctz (mode, op0, 0);
2841       if (!temp)
2842         goto fail;
2843
2844       if (CLZ_DEFINED_VALUE_AT_ZERO (mode, val) == 2)
2845         {
2846           defined_at_zero = true;
2847           val = (GET_MODE_BITSIZE (mode) - 1) - val;
2848         }
2849     }
2850   else
2851     return 0;
2852
2853   if (defined_at_zero && val == -1)
2854     /* No correction needed at zero.  */;
2855   else 
2856     {
2857       /* We don't try to do anything clever with the situation found
2858          on some processors (eg Alpha) where ctz(0:mode) ==
2859          bitsize(mode).  If someone can think of a way to send N to -1
2860          and leave alone all values in the range 0..N-1 (where N is a
2861          power of two), cheaper than this test-and-branch, please add it.
2862
2863          The test-and-branch is done after the operation itself, in case
2864          the operation sets condition codes that can be recycled for this.
2865          (This is true on i386, for instance.)  */
2866
2867       rtx nonzero_label = gen_label_rtx ();
2868       emit_cmp_and_jump_insns (op0, CONST0_RTX (mode), NE, 0,
2869                                mode, true, nonzero_label);
2870
2871       convert_move (temp, GEN_INT (-1), false);
2872       emit_label (nonzero_label);
2873     }
2874
2875   /* temp now has a value in the range -1..bitsize-1.  ffs is supposed
2876      to produce a value in the range 0..bitsize.  */
2877   temp = expand_binop (mode, add_optab, temp, GEN_INT (1),
2878                        target, false, OPTAB_DIRECT);
2879   if (!temp)
2880     goto fail;
2881
2882   seq = get_insns ();
2883   end_sequence ();
2884
2885   add_equal_note (seq, temp, FFS, op0, 0);
2886   emit_insn (seq);
2887   return temp;
2888
2889  fail:
2890   end_sequence ();
2891   return 0;
2892 }
2893
2894 /* Extract the OMODE lowpart from VAL, which has IMODE.  Under certain
2895    conditions, VAL may already be a SUBREG against which we cannot generate
2896    a further SUBREG.  In this case, we expect forcing the value into a
2897    register will work around the situation.  */
2898
2899 static rtx
2900 lowpart_subreg_maybe_copy (enum machine_mode omode, rtx val,
2901                            enum machine_mode imode)
2902 {
2903   rtx ret;
2904   ret = lowpart_subreg (omode, val, imode);
2905   if (ret == NULL)
2906     {
2907       val = force_reg (imode, val);
2908       ret = lowpart_subreg (omode, val, imode);
2909       gcc_assert (ret != NULL);
2910     }
2911   return ret;
2912 }
2913
2914 /* Expand a floating point absolute value or negation operation via a
2915    logical operation on the sign bit.  */
2916
2917 static rtx
2918 expand_absneg_bit (enum rtx_code code, enum machine_mode mode,
2919                    rtx op0, rtx target)
2920 {
2921   const struct real_format *fmt;
2922   int bitpos, word, nwords, i;
2923   enum machine_mode imode;
2924   HOST_WIDE_INT hi, lo;
2925   rtx temp, insns;
2926
2927   /* The format has to have a simple sign bit.  */
2928   fmt = REAL_MODE_FORMAT (mode);
2929   if (fmt == NULL)
2930     return NULL_RTX;
2931
2932   bitpos = fmt->signbit_rw;
2933   if (bitpos < 0)
2934     return NULL_RTX;
2935
2936   /* Don't create negative zeros if the format doesn't support them.  */
2937   if (code == NEG && !fmt->has_signed_zero)
2938     return NULL_RTX;
2939
2940   if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
2941     {
2942       imode = int_mode_for_mode (mode);
2943       if (imode == BLKmode)
2944         return NULL_RTX;
2945       word = 0;
2946       nwords = 1;
2947     }
2948   else
2949     {
2950       imode = word_mode;
2951
2952       if (FLOAT_WORDS_BIG_ENDIAN)
2953         word = (GET_MODE_BITSIZE (mode) - bitpos) / BITS_PER_WORD;
2954       else
2955         word = bitpos / BITS_PER_WORD;
2956       bitpos = bitpos % BITS_PER_WORD;
2957       nwords = (GET_MODE_BITSIZE (mode) + BITS_PER_WORD - 1) / BITS_PER_WORD;
2958     }
2959
2960   if (bitpos < HOST_BITS_PER_WIDE_INT)
2961     {
2962       hi = 0;
2963       lo = (HOST_WIDE_INT) 1 << bitpos;
2964     }
2965   else
2966     {
2967       hi = (HOST_WIDE_INT) 1 << (bitpos - HOST_BITS_PER_WIDE_INT);
2968       lo = 0;
2969     }
2970   if (code == ABS)
2971     lo = ~lo, hi = ~hi;
2972
2973   if (target == 0 || target == op0)
2974     target = gen_reg_rtx (mode);
2975
2976   if (nwords > 1)
2977     {
2978       start_sequence ();
2979
2980       for (i = 0; i < nwords; ++i)
2981         {
2982           rtx targ_piece = operand_subword (target, i, 1, mode);
2983           rtx op0_piece = operand_subword_force (op0, i, mode);
2984
2985           if (i == word)
2986             {
2987               temp = expand_binop (imode, code == ABS ? and_optab : xor_optab,
2988                                    op0_piece,
2989                                    immed_double_const (lo, hi, imode),
2990                                    targ_piece, 1, OPTAB_LIB_WIDEN);
2991               if (temp != targ_piece)
2992                 emit_move_insn (targ_piece, temp);
2993             }
2994           else
2995             emit_move_insn (targ_piece, op0_piece);
2996         }
2997
2998       insns = get_insns ();
2999       end_sequence ();
3000
3001       temp = gen_rtx_fmt_e (code, mode, copy_rtx (op0));
3002       emit_no_conflict_block (insns, target, op0, NULL_RTX, temp);
3003     }
3004   else
3005     {
3006       temp = expand_binop (imode, code == ABS ? and_optab : xor_optab,
3007                            gen_lowpart (imode, op0),
3008                            immed_double_const (lo, hi, imode),
3009                            gen_lowpart (imode, target), 1, OPTAB_LIB_WIDEN);
3010       target = lowpart_subreg_maybe_copy (mode, temp, imode);
3011
3012       set_unique_reg_note (get_last_insn (), REG_EQUAL,
3013                            gen_rtx_fmt_e (code, mode, copy_rtx (op0)));
3014     }
3015
3016   return target;
3017 }
3018
3019 /* As expand_unop, but will fail rather than attempt the operation in a
3020    different mode or with a libcall.  */
3021 static rtx
3022 expand_unop_direct (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
3023              int unsignedp)
3024 {
3025   if (optab_handler (unoptab, mode)->insn_code != CODE_FOR_nothing)
3026     {
3027       int icode = (int) optab_handler (unoptab, mode)->insn_code;
3028       enum machine_mode mode0 = insn_data[icode].operand[1].mode;
3029       rtx xop0 = op0;
3030       rtx last = get_last_insn ();
3031       rtx pat, temp;
3032
3033       if (target)
3034         temp = target;
3035       else
3036         temp = gen_reg_rtx (mode);
3037
3038       if (GET_MODE (xop0) != VOIDmode
3039           && GET_MODE (xop0) != mode0)
3040         xop0 = convert_to_mode (mode0, xop0, unsignedp);
3041
3042       /* Now, if insn doesn't accept our operand, put it into a pseudo.  */
3043
3044       if (!insn_data[icode].operand[1].predicate (xop0, mode0))
3045         xop0 = copy_to_mode_reg (mode0, xop0);
3046
3047       if (!insn_data[icode].operand[0].predicate (temp, mode))
3048         temp = gen_reg_rtx (mode);
3049
3050       pat = GEN_FCN (icode) (temp, xop0);
3051       if (pat)
3052         {
3053           if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX
3054               && ! add_equal_note (pat, temp, unoptab->code, xop0, NULL_RTX))
3055             {
3056               delete_insns_since (last);
3057               return expand_unop (mode, unoptab, op0, NULL_RTX, unsignedp);
3058             }
3059
3060           emit_insn (pat);
3061
3062           return temp;
3063         }
3064       else
3065         delete_insns_since (last);
3066     }
3067   return 0;
3068 }
3069
3070 /* Generate code to perform an operation specified by UNOPTAB
3071    on operand OP0, with result having machine-mode MODE.
3072
3073    UNSIGNEDP is for the case where we have to widen the operands
3074    to perform the operation.  It says to use zero-extension.
3075
3076    If TARGET is nonzero, the value
3077    is generated there, if it is convenient to do so.
3078    In all cases an rtx is returned for the locus of the value;
3079    this may or may not be TARGET.  */
3080
3081 rtx
3082 expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
3083              int unsignedp)
3084 {
3085   enum mode_class class = GET_MODE_CLASS (mode);
3086   enum machine_mode wider_mode;
3087   rtx temp;
3088   rtx libfunc;
3089
3090   temp = expand_unop_direct (mode, unoptab, op0, target, unsignedp);
3091   if (temp)
3092     return temp;
3093
3094   /* It can't be done in this mode.  Can we open-code it in a wider mode?  */
3095
3096   /* Widening (or narrowing) clz needs special treatment.  */
3097   if (unoptab == clz_optab)
3098     {
3099       temp = widen_clz (mode, op0, target);
3100       if (temp)
3101         return temp;
3102
3103       if (GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
3104           && optab_handler (unoptab, word_mode)->insn_code != CODE_FOR_nothing)
3105         {
3106           temp = expand_doubleword_clz (mode, op0, target);
3107           if (temp)
3108             return temp;
3109         }
3110
3111         goto try_libcall;
3112     }
3113
3114   /* Widening (or narrowing) bswap needs special treatment.  */
3115   if (unoptab == bswap_optab)
3116     {
3117       temp = widen_bswap (mode, op0, target);
3118       if (temp)
3119         return temp;
3120
3121       if (GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
3122           && optab_handler (unoptab, word_mode)->insn_code != CODE_FOR_nothing)
3123         {
3124           temp = expand_doubleword_bswap (mode, op0, target);
3125           if (temp)
3126             return temp;
3127         }
3128
3129       goto try_libcall;
3130     }
3131
3132   if (CLASS_HAS_WIDER_MODES_P (class))
3133     for (wider_mode = GET_MODE_WIDER_MODE (mode);
3134          wider_mode != VOIDmode;
3135          wider_mode = GET_MODE_WIDER_MODE (wider_mode))
3136       {
3137         if (optab_handler (unoptab, wider_mode)->insn_code != CODE_FOR_nothing)
3138           {
3139             rtx xop0 = op0;
3140             rtx last = get_last_insn ();
3141
3142             /* For certain operations, we need not actually extend
3143                the narrow operand, as long as we will truncate the
3144                results to the same narrowness.  */
3145
3146             xop0 = widen_operand (xop0, wider_mode, mode, unsignedp,
3147                                   (unoptab == neg_optab
3148                                    || unoptab == one_cmpl_optab)
3149                                   && class == MODE_INT);
3150
3151             temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
3152                                 unsignedp);
3153
3154             if (temp)
3155               {
3156                 if (class != MODE_INT
3157                     || !TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
3158                                                GET_MODE_BITSIZE (wider_mode)))
3159                   {
3160                     if (target == 0)
3161                       target = gen_reg_rtx (mode);
3162                     convert_move (target, temp, 0);
3163                     return target;
3164                   }
3165                 else
3166                   return gen_lowpart (mode, temp);
3167               }
3168             else
3169               delete_insns_since (last);
3170           }
3171       }
3172
3173   /* These can be done a word at a time.  */
3174   if (unoptab == one_cmpl_optab
3175       && class == MODE_INT
3176       && GET_MODE_SIZE (mode) > UNITS_PER_WORD
3177       && optab_handler (unoptab, word_mode)->insn_code != CODE_FOR_nothing)
3178     {
3179       int i;
3180       rtx insns;
3181
3182       if (target == 0 || target == op0)
3183         target = gen_reg_rtx (mode);
3184
3185       start_sequence ();
3186
3187       /* Do the actual arithmetic.  */
3188       for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)
3189         {
3190           rtx target_piece = operand_subword (target, i, 1, mode);
3191           rtx x = expand_unop (word_mode, unoptab,
3192                                operand_subword_force (op0, i, mode),
3193                                target_piece, unsignedp);
3194
3195           if (target_piece != x)
3196             emit_move_insn (target_piece, x);
3197         }
3198
3199       insns = get_insns ();
3200       end_sequence ();
3201
3202       emit_no_conflict_block (insns, target, op0, NULL_RTX,
3203                               gen_rtx_fmt_e (unoptab->code, mode,
3204                                              copy_rtx (op0)));
3205       return target;
3206     }
3207
3208   if (unoptab->code == NEG)
3209     {
3210       /* Try negating floating point values by flipping the sign bit.  */
3211       if (SCALAR_FLOAT_MODE_P (mode))
3212         {
3213           temp = expand_absneg_bit (NEG, mode, op0, target);
3214           if (temp)
3215             return temp;
3216         }
3217
3218       /* If there is no negation pattern, and we have no negative zero,
3219          try subtracting from zero.  */
3220       if (!HONOR_SIGNED_ZEROS (mode))
3221         {
3222           temp = expand_binop (mode, (unoptab == negv_optab
3223                                       ? subv_optab : sub_optab),
3224                                CONST0_RTX (mode), op0, target,
3225                                unsignedp, OPTAB_DIRECT);
3226           if (temp)
3227             return temp;
3228         }
3229     }
3230
3231   /* Try calculating parity (x) as popcount (x) % 2.  */
3232   if (unoptab == parity_optab)
3233     {
3234       temp = expand_parity (mode, op0, target);
3235       if (temp)
3236         return temp;
3237     }
3238
3239   /* Try implementing ffs (x) in terms of clz (x).  */
3240   if (unoptab == ffs_optab)
3241     {
3242       temp = expand_ffs (mode, op0, target);
3243       if (temp)
3244         return temp;
3245     }
3246
3247   /* Try implementing ctz (x) in terms of clz (x).  */
3248   if (unoptab == ctz_optab)
3249     {
3250       temp = expand_ctz (mode, op0, target);
3251       if (temp)
3252         return temp;
3253     }
3254
3255  try_libcall:
3256   /* Now try a library call in this mode.  */
3257   libfunc = optab_libfunc (unoptab, mode);
3258   if (libfunc)
3259     {
3260       rtx insns;
3261       rtx value;
3262       enum machine_mode outmode = mode;
3263
3264       /* All of these functions return small values.  Thus we choose to
3265          have them return something that isn't a double-word.  */
3266       if (unoptab == ffs_optab || unoptab == clz_optab || unoptab == ctz_optab
3267           || unoptab == popcount_optab || unoptab == parity_optab)
3268         outmode
3269             = GET_MODE (hard_libcall_value (TYPE_MODE (integer_type_node)));
3270
3271       start_sequence ();
3272
3273       /* Pass 1 for NO_QUEUE so we don't lose any increments
3274          if the libcall is cse'd or moved.  */
3275       value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST, outmode,
3276                                        1, op0, mode);
3277       insns = get_insns ();
3278       end_sequence ();
3279
3280       target = gen_reg_rtx (outmode);
3281       emit_libcall_block (insns, target, value,
3282                           gen_rtx_fmt_e (unoptab->code, outmode, op0));
3283
3284       return target;
3285     }
3286
3287   /* It can't be done in this mode.  Can we do it in a wider mode?  */
3288
3289   if (CLASS_HAS_WIDER_MODES_P (class))
3290     {
3291       for (wider_mode = GET_MODE_WIDER_MODE (mode);
3292            wider_mode != VOIDmode;
3293            wider_mode = GET_MODE_WIDER_MODE (wider_mode))
3294         {
3295           if ((optab_handler (unoptab, wider_mode)->insn_code
3296                != CODE_FOR_nothing)
3297               || optab_libfunc (unoptab, wider_mode))
3298             {
3299               rtx xop0 = op0;
3300               rtx last = get_last_insn ();
3301
3302               /* For certain operations, we need not actually extend
3303                  the narrow operand, as long as we will truncate the
3304                  results to the same narrowness.  */
3305
3306               xop0 = widen_operand (xop0, wider_mode, mode, unsignedp,
3307                                     (unoptab == neg_optab
3308                                      || unoptab == one_cmpl_optab)
3309                                     && class == MODE_INT);
3310
3311               temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
3312                                   unsignedp);
3313
3314               /* If we are generating clz using wider mode, adjust the
3315                  result.  */
3316               if (unoptab == clz_optab && temp != 0)
3317                 temp = expand_binop (wider_mode, sub_optab, temp,
3318                                      GEN_INT (GET_MODE_BITSIZE (wider_mode)
3319                                               - GET_MODE_BITSIZE (mode)),
3320                                      target, true, OPTAB_DIRECT);
3321
3322               if (temp)
3323                 {
3324                   if (class != MODE_INT)
3325                     {
3326                       if (target == 0)
3327                         target = gen_reg_rtx (mode);
3328                       convert_move (target, temp, 0);
3329                       return target;
3330                     }
3331                   else
3332                     return gen_lowpart (mode, temp);
3333                 }
3334               else
3335                 delete_insns_since (last);
3336             }
3337         }
3338     }
3339
3340   /* One final attempt at implementing negation via subtraction,
3341      this time allowing widening of the operand.  */
3342   if (unoptab->code == NEG && !HONOR_SIGNED_ZEROS (mode))
3343     {
3344       rtx temp;
3345       temp = expand_binop (mode,
3346                            unoptab == negv_optab ? subv_optab : sub_optab,
3347                            CONST0_RTX (mode), op0,
3348                            target, unsignedp, OPTAB_LIB_WIDEN);
3349       if (temp)
3350         return temp;
3351     }
3352
3353   return 0;
3354 }
3355 \f
3356 /* Emit code to compute the absolute value of OP0, with result to
3357    TARGET if convenient.  (TARGET may be 0.)  The return value says
3358    where the result actually is to be found.
3359
3360    MODE is the mode of the operand; the mode of the result is
3361    different but can be deduced from MODE.
3362
3363  */
3364
3365 rtx
3366 expand_abs_nojump (enum machine_mode mode, rtx op0, rtx target,
3367                    int result_unsignedp)
3368 {
3369   rtx temp;
3370
3371   if (! flag_trapv)
3372     result_unsignedp = 1;
3373
3374   /* First try to do it with a special abs instruction.  */
3375   temp = expand_unop (mode, result_unsignedp ? abs_optab : absv_optab,
3376                       op0, target, 0);
3377   if (temp != 0)
3378     return temp;
3379
3380   /* For floating point modes, try clearing the sign bit.  */
3381   if (SCALAR_FLOAT_MODE_P (mode))
3382     {
3383       temp = expand_absneg_bit (ABS, mode, op0, target);
3384       if (temp)
3385         return temp;
3386     }
3387
3388   /* If we have a MAX insn, we can do this as MAX (x, -x).  */
3389   if (optab_handler (smax_optab, mode)->insn_code != CODE_FOR_nothing
3390       && !HONOR_SIGNED_ZEROS (mode))
3391     {
3392       rtx last = get_last_insn ();
3393
3394       temp = expand_unop (mode, neg_optab, op0, NULL_RTX, 0);
3395       if (temp != 0)
3396         temp = expand_binop (mode, smax_optab, op0, temp, target, 0,
3397                              OPTAB_WIDEN);
3398
3399       if (temp != 0)
3400         return temp;
3401
3402       delete_insns_since (last);
3403     }
3404
3405   /* If this machine has expensive jumps, we can do integer absolute
3406      value of X as (((signed) x >> (W-1)) ^ x) - ((signed) x >> (W-1)),
3407      where W is the width of MODE.  */
3408
3409   if (GET_MODE_CLASS (mode) == MODE_INT && BRANCH_COST >= 2)
3410     {
3411       rtx extended = expand_shift (RSHIFT_EXPR, mode, op0,
3412                                    size_int (GET_MODE_BITSIZE (mode) - 1),
3413                                    NULL_RTX, 0);
3414
3415       temp = expand_binop (mode, xor_optab, extended, op0, target, 0,
3416                            OPTAB_LIB_WIDEN);
3417       if (temp != 0)
3418         temp = expand_binop (mode, result_unsignedp ? sub_optab : subv_optab,
3419                              temp, extended, target, 0, OPTAB_LIB_WIDEN);
3420
3421       if (temp != 0)
3422         return temp;
3423     }
3424
3425   return NULL_RTX;
3426 }
3427
3428 rtx
3429 expand_abs (enum machine_mode mode, rtx op0, rtx target,
3430             int result_unsignedp, int safe)
3431 {
3432   rtx temp, op1;
3433
3434   if (! flag_trapv)
3435     result_unsignedp = 1;
3436
3437   temp = expand_abs_nojump (mode, op0, target, result_unsignedp);
3438   if (temp != 0)
3439     return temp;
3440
3441   /* If that does not win, use conditional jump and negate.  */
3442
3443   /* It is safe to use the target if it is the same
3444      as the source if this is also a pseudo register */
3445   if (op0 == target && REG_P (op0)
3446       && REGNO (op0) >= FIRST_PSEUDO_REGISTER)
3447     safe = 1;
3448
3449   op1 = gen_label_rtx ();
3450   if (target == 0 || ! safe
3451       || GET_MODE (target) != mode
3452       || (MEM_P (target) && MEM_VOLATILE_P (target))
3453       || (REG_P (target)
3454           && REGNO (target) < FIRST_PSEUDO_REGISTER))
3455     target = gen_reg_rtx (mode);
3456
3457   emit_move_insn (target, op0);
3458   NO_DEFER_POP;
3459
3460   do_compare_rtx_and_jump (target, CONST0_RTX (mode), GE, 0, mode,
3461                            NULL_RTX, NULL_RTX, op1);
3462
3463   op0 = expand_unop (mode, result_unsignedp ? neg_optab : negv_optab,
3464                      target, target, 0);
3465   if (op0 != target)
3466     emit_move_insn (target, op0);
3467   emit_label (op1);
3468   OK_DEFER_POP;
3469   return target;
3470 }
3471
3472 /* A subroutine of expand_copysign, perform the copysign operation using the
3473    abs and neg primitives advertised to exist on the target.  The assumption
3474    is that we have a split register file, and leaving op0 in fp registers,
3475    and not playing with subregs so much, will help the register allocator.  */
3476
3477 static rtx
3478 expand_copysign_absneg (enum machine_mode mode, rtx op0, rtx op1, rtx target,
3479                         int bitpos, bool op0_is_abs)
3480 {
3481   enum machine_mode imode;
3482   int icode;
3483   rtx sign, label;
3484
3485   if (target == op1)
3486     target = NULL_RTX;
3487
3488   /* Check if the back end provides an insn that handles signbit for the
3489      argument's mode. */
3490   icode = (int) signbit_optab->handlers [(int) mode].insn_code;
3491   if (icode != CODE_FOR_nothing)
3492     {
3493       imode = insn_data[icode].operand[0].mode;
3494       sign = gen_reg_rtx (imode);
3495       emit_unop_insn (icode, sign, op1, UNKNOWN);
3496     }
3497   else
3498     {
3499       HOST_WIDE_INT hi, lo;
3500
3501       if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
3502         {
3503           imode = int_mode_for_mode (mode);
3504           if (imode == BLKmode)
3505             return NULL_RTX;
3506           op1 = gen_lowpart (imode, op1);
3507         }
3508       else
3509         {
3510           int word;
3511
3512           imode = word_mode;
3513           if (FLOAT_WORDS_BIG_ENDIAN)
3514             word = (GET_MODE_BITSIZE (mode) - bitpos) / BITS_PER_WORD;
3515           else
3516             word = bitpos / BITS_PER_WORD;
3517           bitpos = bitpos % BITS_PER_WORD;
3518           op1 = operand_subword_force (op1, word, mode);
3519         }
3520
3521       if (bitpos < HOST_BITS_PER_WIDE_INT)
3522         {
3523           hi = 0;
3524           lo = (HOST_WIDE_INT) 1 << bitpos;
3525         }
3526       else
3527         {
3528           hi = (HOST_WIDE_INT) 1 << (bitpos - HOST_BITS_PER_WIDE_INT);
3529           lo = 0;
3530         }
3531
3532       sign = gen_reg_rtx (imode);
3533       sign = expand_binop (imode, and_optab, op1,
3534                            immed_double_const (lo, hi, imode),
3535                            NULL_RTX, 1, OPTAB_LIB_WIDEN);
3536     }
3537
3538   if (!op0_is_abs)
3539     {
3540       op0 = expand_unop (mode, abs_optab, op0, target, 0);
3541       if (op0 == NULL)
3542         return NULL_RTX;
3543       target = op0;
3544     }
3545   else
3546     {
3547       if (target == NULL_RTX)
3548         target = copy_to_reg (op0);
3549       else
3550         emit_move_insn (target, op0);
3551     }
3552
3553   label = gen_label_rtx ();
3554   emit_cmp_and_jump_insns (sign, const0_rtx, EQ, NULL_RTX, imode, 1, label);
3555
3556   if (GET_CODE (op0) == CONST_DOUBLE)
3557     op0 = simplify_unary_operation (NEG, mode, op0, mode);
3558   else
3559     op0 = expand_unop (mode, neg_optab, op0, target, 0);
3560   if (op0 != target)
3561     emit_move_insn (target, op0);
3562
3563   emit_label (label);
3564
3565   return target;
3566 }
3567
3568
3569 /* A subroutine of expand_copysign, perform the entire copysign operation
3570    with integer bitmasks.  BITPOS is the position of the sign bit; OP0_IS_ABS
3571    is true if op0 is known to have its sign bit clear.  */
3572
3573 static rtx
3574 expand_copysign_bit (enum machine_mode mode, rtx op0, rtx op1, rtx target,
3575                      int bitpos, bool op0_is_abs)
3576 {
3577   enum machine_mode imode;
3578   HOST_WIDE_INT hi, lo;
3579   int word, nwords, i;
3580   rtx temp, insns;
3581
3582   if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
3583     {
3584       imode = int_mode_for_mode (mode);
3585       if (imode == BLKmode)
3586         return NULL_RTX;
3587       word = 0;
3588       nwords = 1;
3589     }
3590   else
3591     {
3592       imode = word_mode;
3593
3594       if (FLOAT_WORDS_BIG_ENDIAN)
3595         word = (GET_MODE_BITSIZE (mode) - bitpos) / BITS_PER_WORD;
3596       else
3597         word = bitpos / BITS_PER_WORD;
3598       bitpos = bitpos % BITS_PER_WORD;
3599       nwords = (GET_MODE_BITSIZE (mode) + BITS_PER_WORD - 1) / BITS_PER_WORD;
3600     }
3601
3602   if (bitpos < HOST_BITS_PER_WIDE_INT)
3603     {
3604       hi = 0;
3605       lo = (HOST_WIDE_INT) 1 << bitpos;
3606     }
3607   else
3608     {
3609       hi = (HOST_WIDE_INT) 1 << (bitpos - HOST_BITS_PER_WIDE_INT);
3610       lo = 0;
3611     }
3612
3613   if (target == 0 || target == op0 || target == op1)
3614     target = gen_reg_rtx (mode);
3615
3616   if (nwords > 1)
3617     {
3618       start_sequence ();
3619
3620       for (i = 0; i < nwords; ++i)
3621         {
3622           rtx targ_piece = operand_subword (target, i, 1, mode);
3623           rtx op0_piece = operand_subword_force (op0, i, mode);
3624
3625           if (i == word)
3626             {
3627               if (!op0_is_abs)
3628                 op0_piece = expand_binop (imode, and_optab, op0_piece,
3629                                           immed_double_const (~lo, ~hi, imode),
3630                                           NULL_RTX, 1, OPTAB_LIB_WIDEN);
3631
3632               op1 = expand_binop (imode, and_optab,
3633                                   operand_subword_force (op1, i, mode),
3634                                   immed_double_const (lo, hi, imode),
3635                                   NULL_RTX, 1, OPTAB_LIB_WIDEN);
3636
3637               temp = expand_binop (imode, ior_optab, op0_piece, op1,
3638                                    targ_piece, 1, OPTAB_LIB_WIDEN);
3639               if (temp != targ_piece)
3640                 emit_move_insn (targ_piece, temp);
3641             }
3642           else
3643             emit_move_insn (targ_piece, op0_piece);
3644         }
3645
3646       insns = get_insns ();
3647       end_sequence ();
3648
3649       emit_no_conflict_block (insns, target, op0, op1, NULL_RTX);
3650     }
3651   else
3652     {
3653       op1 = expand_binop (imode, and_optab, gen_lowpart (imode, op1),
3654                           immed_double_const (lo, hi, imode),
3655                           NULL_RTX, 1, OPTAB_LIB_WIDEN);
3656
3657       op0 = gen_lowpart (imode, op0);
3658       if (!op0_is_abs)
3659         op0 = expand_binop (imode, and_optab, op0,
3660                             immed_double_const (~lo, ~hi, imode),
3661                             NULL_RTX, 1, OPTAB_LIB_WIDEN);
3662
3663       temp = expand_binop (imode, ior_optab, op0, op1,
3664                            gen_lowpart (imode, target), 1, OPTAB_LIB_WIDEN);
3665       target = lowpart_subreg_maybe_copy (mode, temp, imode);
3666     }
3667
3668   return target;
3669 }
3670
3671 /* Expand the C99 copysign operation.  OP0 and OP1 must be the same
3672    scalar floating point mode.  Return NULL if we do not know how to
3673    expand the operation inline.  */
3674
3675 rtx
3676 expand_copysign (rtx op0, rtx op1, rtx target)
3677 {
3678   enum machine_mode mode = GET_MODE (op0);
3679   const struct real_format *fmt;
3680   bool op0_is_abs;
3681   rtx temp;
3682
3683   gcc_assert (SCALAR_FLOAT_MODE_P (mode));
3684   gcc_assert (GET_MODE (op1) == mode);
3685
3686   /* First try to do it with a special instruction.  */
3687   temp = expand_binop (mode, copysign_optab, op0, op1,
3688                        target, 0, OPTAB_DIRECT);
3689   if (temp)
3690     return temp;
3691
3692   fmt = REAL_MODE_FORMAT (mode);
3693   if (fmt == NULL || !fmt->has_signed_zero)
3694     return NULL_RTX;
3695
3696   op0_is_abs = false;
3697   if (GET_CODE (op0) == CONST_DOUBLE)
3698     {
3699       if (real_isneg (CONST_DOUBLE_REAL_VALUE (op0)))
3700         op0 = simplify_unary_operation (ABS, mode, op0, mode);
3701       op0_is_abs = true;
3702     }
3703
3704   if (fmt->signbit_ro >= 0
3705       && (GET_CODE (op0) == CONST_DOUBLE
3706           || (optab_handler (neg_optab, mode)->insn_code != CODE_FOR_nothing
3707               && optab_handler (abs_optab, mode)->insn_code != CODE_FOR_nothing)))
3708     {
3709       temp = expand_copysign_absneg (mode, op0, op1, target,
3710                                      fmt->signbit_ro, op0_is_abs);
3711       if (temp)
3712         return temp;
3713     }
3714
3715   if (fmt->signbit_rw < 0)
3716     return NULL_RTX;
3717   return expand_copysign_bit (mode, op0, op1, target,
3718                               fmt->signbit_rw, op0_is_abs);
3719 }
3720 \f
3721 /* Generate an instruction whose insn-code is INSN_CODE,
3722    with two operands: an output TARGET and an input OP0.
3723    TARGET *must* be nonzero, and the output is always stored there.
3724    CODE is an rtx code such that (CODE OP0) is an rtx that describes
3725    the value that is stored into TARGET.  */
3726
3727 void
3728 emit_unop_insn (int icode, rtx target, rtx op0, enum rtx_code code)
3729 {
3730   rtx temp;
3731   enum machine_mode mode0 = insn_data[icode].operand[1].mode;
3732   rtx pat;
3733
3734   temp = target;
3735
3736   /* Now, if insn does not accept our operands, put them into pseudos.  */
3737
3738   if (!insn_data[icode].operand[1].predicate (op0, mode0))
3739     op0 = copy_to_mode_reg (mode0, op0);
3740
3741   if (!insn_data[icode].operand[0].predicate (temp, GET_MODE (temp)))
3742     temp = gen_reg_rtx (GET_MODE (temp));
3743
3744   pat = GEN_FCN (icode) (temp, op0);
3745
3746   if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX && code != UNKNOWN)
3747     add_equal_note (pat, temp, code, op0, NULL_RTX);
3748
3749   emit_insn (pat);
3750
3751   if (temp != target)
3752     emit_move_insn (target, temp);
3753 }
3754 \f
3755 struct no_conflict_data
3756 {
3757   rtx target, first, insn;
3758   bool must_stay;
3759 };
3760
3761 /* Called via note_stores by emit_no_conflict_block and emit_libcall_block.
3762    Set P->must_stay if the currently examined clobber / store has to stay
3763    in the list of insns that constitute the actual no_conflict block /
3764    libcall block.  */
3765 static void
3766 no_conflict_move_test (rtx dest, const_rtx set, void *p0)
3767 {
3768   struct no_conflict_data *p= p0;
3769
3770   /* If this inns directly contributes to setting the target, it must stay.  */
3771   if (reg_overlap_mentioned_p (p->target, dest))
3772     p->must_stay = true;
3773   /* If we haven't committed to keeping any other insns in the list yet,
3774      there is nothing more to check.  */
3775   else if (p->insn == p->first)
3776     return;
3777   /* If this insn sets / clobbers a register that feeds one of the insns
3778      already in the list, this insn has to stay too.  */
3779   else if (reg_overlap_mentioned_p (dest, PATTERN (p->first))
3780            || (CALL_P (p->first) && (find_reg_fusage (p->first, USE, dest)))
3781            || reg_used_between_p (dest, p->first, p->insn)
3782            /* Likewise if this insn depends on a register set by a previous
3783               insn in the list, or if it sets a result (presumably a hard
3784               register) that is set or clobbered by a previous insn.
3785               N.B. the modified_*_p (SET_DEST...) tests applied to a MEM
3786               SET_DEST perform the former check on the address, and the latter
3787               check on the MEM.  */
3788            || (GET_CODE (set) == SET
3789                && (modified_in_p (SET_SRC (set), p->first)
3790                    || modified_in_p (SET_DEST (set), p->first)
3791                    || modified_between_p (SET_SRC (set), p->first, p->insn)
3792                    || modified_between_p (SET_DEST (set), p->first, p->insn))))
3793     p->must_stay = true;
3794 }
3795
3796 /* Encapsulate the block starting at FIRST and ending with LAST, which is
3797    logically equivalent to EQUIV, so it gets manipulated as a unit if it
3798    is possible to do so.  */
3799
3800 void
3801 maybe_encapsulate_block (rtx first, rtx last, rtx equiv)
3802 {
3803   if (!flag_non_call_exceptions || !may_trap_p (equiv))
3804     {
3805       /* We can't attach the REG_LIBCALL and REG_RETVAL notes when the
3806          encapsulated region would not be in one basic block, i.e. when
3807          there is a control_flow_insn_p insn between FIRST and LAST.  */
3808       bool attach_libcall_retval_notes = true;
3809       rtx insn, next = NEXT_INSN (last);
3810
3811       for (insn = first; insn != next; insn = NEXT_INSN (insn))
3812         if (control_flow_insn_p (insn))
3813           {
3814             attach_libcall_retval_notes = false;
3815             break;
3816           }
3817
3818       if (attach_libcall_retval_notes)
3819         {
3820           REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last,
3821                                                  REG_NOTES (first));
3822           REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first,
3823                                                 REG_NOTES (last));
3824           next = NEXT_INSN (last);
3825           for (insn = first; insn != next; insn = NEXT_INSN (insn))
3826             REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_LIBCALL_ID,
3827                                                   GEN_INT (libcall_id),
3828                                                   REG_NOTES (insn));
3829           libcall_id++;
3830         }
3831     }
3832 }
3833
3834 /* Emit code to perform a series of operations on a multi-word quantity, one
3835    word at a time.
3836
3837    Such a block is preceded by a CLOBBER of the output, consists of multiple
3838    insns, each setting one word of the output, and followed by a SET copying
3839    the output to itself.
3840
3841    Each of the insns setting words of the output receives a REG_NO_CONFLICT
3842    note indicating that it doesn't conflict with the (also multi-word)
3843    inputs.  The entire block is surrounded by REG_LIBCALL and REG_RETVAL
3844    notes.
3845
3846    INSNS is a block of code generated to perform the operation, not including
3847    the CLOBBER and final copy.  All insns that compute intermediate values
3848    are first emitted, followed by the block as described above.
3849
3850    TARGET, OP0, and OP1 are the output and inputs of the operations,
3851    respectively.  OP1 may be zero for a unary operation.
3852
3853    EQUIV, if nonzero, is an expression to be placed into a REG_EQUAL note
3854    on the last insn.
3855
3856    If TARGET is not a register, INSNS is simply emitted with no special
3857    processing.  Likewise if anything in INSNS is not an INSN or if
3858    there is a libcall block inside INSNS.
3859
3860    The final insn emitted is returned.  */
3861
3862 rtx
3863 emit_no_conflict_block (rtx insns, rtx target, rtx op0, rtx op1, rtx equiv)
3864 {
3865   rtx prev, next, first, last, insn;
3866
3867   if (!REG_P (target) || reload_in_progress)
3868     return emit_insn (insns);
3869   else
3870     for (insn = insns; insn; insn = NEXT_INSN (insn))
3871       if (!NONJUMP_INSN_P (insn)
3872           || find_reg_note (insn, REG_LIBCALL, NULL_RTX))
3873         return emit_insn (insns);
3874
3875   /* First emit all insns that do not store into words of the output and remove
3876      these from the list.  */
3877   for (insn = insns; insn; insn = next)
3878     {
3879       rtx note;
3880       struct no_conflict_data data;
3881
3882       next = NEXT_INSN (insn);
3883
3884       /* Some ports (cris) create a libcall regions at their own.  We must
3885          avoid any potential nesting of LIBCALLs.  */
3886       if ((note = find_reg_note (insn, REG_LIBCALL, NULL)) != NULL)
3887         remove_note (insn, note);
3888       if ((note = find_reg_note (insn, REG_RETVAL, NULL)) != NULL)
3889         remove_note (insn, note);
3890       if ((note = find_reg_note (insn, REG_LIBCALL_ID, NULL)) != NULL)
3891         remove_note (insn, note);
3892
3893       data.target = target;
3894       data.first = insns;
3895       data.insn = insn;
3896       data.must_stay = 0;
3897       note_stores (PATTERN (insn), no_conflict_move_test, &data);
3898       if (! data.must_stay)
3899         {
3900           if (PREV_INSN (insn))
3901             NEXT_INSN (PREV_INSN (insn)) = next;
3902           else
3903             insns = next;
3904
3905           if (next)
3906             PREV_INSN (next) = PREV_INSN (insn);
3907
3908           add_insn (insn);
3909         }
3910     }
3911
3912   prev = get_last_insn ();
3913
3914   /* Now write the CLOBBER of the output, followed by the setting of each
3915      of the words, followed by the final copy.  */
3916   if (target != op0 && target != op1)
3917     emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
3918
3919   for (insn = insns; insn; insn = next)
3920     {
3921       next = NEXT_INSN (insn);
3922       add_insn (insn);
3923
3924       if (op1 && REG_P (op1))
3925         REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_NO_CONFLICT, op1,
3926                                               REG_NOTES (insn));
3927
3928       if (op0 && REG_P (op0))
3929         REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_NO_CONFLICT, op0,
3930                                               REG_NOTES (insn));
3931     }
3932
3933   if (optab_handler (mov_optab, GET_MODE (target))->insn_code
3934       != CODE_FOR_nothing)
3935     {
3936       last = emit_move_insn (target, target);
3937       if (equiv)
3938         set_unique_reg_note (last, REG_EQUAL, equiv);
3939     }
3940   else
3941     {
3942       last = get_last_insn ();
3943
3944       /* Remove any existing REG_EQUAL note from "last", or else it will
3945          be mistaken for a note referring to the full contents of the
3946          alleged libcall value when found together with the REG_RETVAL
3947          note added below.  An existing note can come from an insn
3948          expansion at "last".  */
3949       remove_note (last, find_reg_note (last, REG_EQUAL, NULL_RTX));
3950     }
3951
3952   if (prev == 0)
3953     first = get_insns ();
3954   else
3955     first = NEXT_INSN (prev);
3956
3957   maybe_encapsulate_block (first, last, equiv);
3958
3959   return last;
3960 }
3961 \f
3962 /* Emit code to make a call to a constant function or a library call.
3963
3964    INSNS is a list containing all insns emitted in the call.
3965    These insns leave the result in RESULT.  Our block is to copy RESULT
3966    to TARGET, which is logically equivalent to EQUIV.
3967
3968    We first emit any insns that set a pseudo on the assumption that these are
3969    loading constants into registers; doing so allows them to be safely cse'ed
3970    between blocks.  Then we emit all the other insns in the block, followed by
3971    an insn to move RESULT to TARGET.  This last insn will have a REQ_EQUAL
3972    note with an operand of EQUIV.
3973
3974    Moving assignments to pseudos outside of the block is done to improve
3975    the generated code, but is not required to generate correct code,
3976    hence being unable to move an assignment is not grounds for not making
3977    a libcall block.  There are two reasons why it is safe to leave these
3978    insns inside the block: First, we know that these pseudos cannot be
3979    used in generated RTL outside the block since they are created for
3980    temporary purposes within the block.  Second, CSE will not record the
3981    values of anything set inside a libcall block, so we know they must
3982    be dead at the end of the block.
3983
3984    Except for the first group of insns (the ones setting pseudos), the
3985    block is delimited by REG_RETVAL and REG_LIBCALL notes.  */
3986 void
3987 emit_libcall_block (rtx insns, rtx target, rtx result, rtx equiv)
3988 {
3989   rtx final_dest = target;
3990   rtx prev, next, first, last, insn;
3991
3992   /* If this is a reg with REG_USERVAR_P set, then it could possibly turn
3993      into a MEM later.  Protect the libcall block from this change.  */
3994   if (! REG_P (target) || REG_USERVAR_P (target))
3995     target = gen_reg_rtx (GET_MODE (target));
3996
3997   /* If we're using non-call exceptions, a libcall corresponding to an
3998      operation that may trap may also trap.  */
3999   if (flag_non_call_exceptions && may_trap_p (equiv))
4000     {
4001       for (insn = insns; insn; insn = NEXT_INSN (insn))
4002         if (CALL_P (insn))
4003           {
4004             rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
4005
4006             if (note != 0 && INTVAL (XEXP (note, 0)) <= 0)
4007               remove_note (insn, note);
4008           }
4009     }
4010   else
4011   /* look for any CALL_INSNs in this sequence, and attach a REG_EH_REGION
4012      reg note to indicate that this call cannot throw or execute a nonlocal
4013      goto (unless there is already a REG_EH_REGION note, in which case
4014      we update it).  */
4015     for (insn = insns; insn; insn = NEXT_INSN (insn))
4016       if (CALL_P (insn))
4017         {
4018           rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
4019
4020           if (note != 0)
4021             XEXP (note, 0) = constm1_rtx;
4022           else
4023             REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EH_REGION, constm1_rtx,
4024                                                   REG_NOTES (insn));
4025         }
4026
4027   /* First emit all insns that set pseudos.  Remove them from the list as
4028      we go.  Avoid insns that set pseudos which were referenced in previous
4029      insns.  These can be generated by move_by_pieces, for example,
4030      to update an address.  Similarly, avoid insns that reference things
4031      set in previous insns.  */
4032
4033   for (insn = insns; insn; insn = next)
4034     {
4035       rtx set = single_set (insn);
4036       rtx note;
4037
4038       /* Some ports (cris) create a libcall regions at their own.  We must
4039          avoid any potential nesting of LIBCALLs.  */
4040       if ((note = find_reg_note (insn, REG_LIBCALL, NULL)) != NULL)
4041         remove_note (insn, note);
4042       if ((note = find_reg_note (insn, REG_RETVAL, NULL)) != NULL)
4043         remove_note (insn, note);
4044       if ((note = find_reg_note (insn, REG_LIBCALL_ID, NULL)) != NULL)
4045         remove_note (insn, note);
4046
4047       next = NEXT_INSN (insn);
4048
4049       if (set != 0 && REG_P (SET_DEST (set))
4050           && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER)
4051         {
4052           struct no_conflict_data data;
4053
4054           data.target = const0_rtx;
4055           data.first = insns;
4056           data.insn = insn;
4057           data.must_stay = 0;
4058           note_stores (PATTERN (insn), no_conflict_move_test, &data);
4059           if (! data.must_stay)
4060             {
4061               if (PREV_INSN (insn))
4062                 NEXT_INSN (PREV_INSN (insn)) = next;
4063               else
4064                 insns = next;
4065
4066               if (next)
4067                 PREV_INSN (next) = PREV_INSN (insn);
4068
4069               add_insn (insn);
4070             }
4071         }
4072
4073       /* Some ports use a loop to copy large arguments onto the stack.
4074          Don't move anything outside such a loop.  */
4075       if (LABEL_P (insn))
4076         break;
4077     }
4078
4079   prev = get_last_insn ();
4080
4081   /* Write the remaining insns followed by the final copy.  */
4082
4083   for (insn = insns; insn; insn = next)
4084     {
4085       next = NEXT_INSN (insn);
4086
4087       add_insn (insn);
4088     }
4089
4090   last = emit_move_insn (target, result);
4091   if (optab_handler (mov_optab, GET_MODE (target))->insn_code
4092       != CODE_FOR_nothing)
4093     set_unique_reg_note (last, REG_EQUAL, copy_rtx (equiv));
4094   else
4095     {
4096       /* Remove any existing REG_EQUAL note from "last", or else it will
4097          be mistaken for a note referring to the full contents of the
4098          libcall value when found together with the REG_RETVAL note added
4099          below.  An existing note can come from an insn expansion at
4100          "last".  */
4101       remove_note (last, find_reg_note (last, REG_EQUAL, NULL_RTX));
4102     }
4103
4104   if (final_dest != target)
4105     emit_move_insn (final_dest, target);
4106
4107   if (prev == 0)
4108     first = get_insns ();
4109   else
4110     first = NEXT_INSN (prev);
4111
4112   maybe_encapsulate_block (first, last, equiv);
4113 }
4114 \f
4115 /* Nonzero if we can perform a comparison of mode MODE straightforwardly.
4116    PURPOSE describes how this comparison will be used.  CODE is the rtx
4117    comparison code we will be using.
4118
4119    ??? Actually, CODE is slightly weaker than that.  A target is still
4120    required to implement all of the normal bcc operations, but not
4121    required to implement all (or any) of the unordered bcc operations.  */
4122
4123 int
4124 can_compare_p (enum rtx_code code, enum machine_mode mode,
4125                enum can_compare_purpose purpose)
4126 {
4127   do
4128     {
4129       if (optab_handler (cmp_optab, mode)->insn_code != CODE_FOR_nothing)
4130         {
4131           if (purpose == ccp_jump)
4132             return bcc_gen_fctn[(int) code] != NULL;
4133           else if (purpose == ccp_store_flag)
4134             return setcc_gen_code[(int) code] != CODE_FOR_nothing;
4135           else
4136             /* There's only one cmov entry point, and it's allowed to fail.  */
4137             return 1;
4138         }
4139       if (purpose == ccp_jump
4140           && optab_handler (cbranch_optab, mode)->insn_code != CODE_FOR_nothing)
4141         return 1;
4142       if (purpose == ccp_cmov
4143           && optab_handler (cmov_optab, mode)->insn_code != CODE_FOR_nothing)
4144         return 1;
4145       if (purpose == ccp_store_flag
4146           && optab_handler (cstore_optab, mode)->insn_code != CODE_FOR_nothing)
4147         return 1;
4148       mode = GET_MODE_WIDER_MODE (mode);
4149     }
4150   while (mode != VOIDmode);
4151
4152   return 0;
4153 }
4154
4155 /* This function is called when we are going to emit a compare instruction that
4156    compares the values found in *PX and *PY, using the rtl operator COMPARISON.
4157
4158    *PMODE is the mode of the inputs (in case they are const_int).
4159    *PUNSIGNEDP nonzero says that the operands are unsigned;
4160    this matters if they need to be widened.
4161
4162    If they have mode BLKmode, then SIZE specifies the size of both operands.
4163
4164    This function performs all the setup necessary so that the caller only has
4165    to emit a single comparison insn.  This setup can involve doing a BLKmode
4166    comparison or emitting a library call to perform the comparison if no insn
4167    is available to handle it.
4168    The values which are passed in through pointers can be modified; the caller
4169    should perform the comparison on the modified values.  Constant
4170    comparisons must have already been folded.  */
4171
4172 static void
4173 prepare_cmp_insn (rtx *px, rtx *py, enum rtx_code *pcomparison, rtx size,
4174                   enum machine_mode *pmode, int *punsignedp,
4175                   enum can_compare_purpose purpose)
4176 {
4177   enum machine_mode mode = *pmode;
4178   rtx x = *px, y = *py;
4179   int unsignedp = *punsignedp;
4180   rtx libfunc;
4181
4182   /* If we are inside an appropriately-short loop and we are optimizing,
4183      force expensive constants into a register.  */
4184   if (CONSTANT_P (x) && optimize
4185       && rtx_cost (x, COMPARE) > COSTS_N_INSNS (1))
4186     x = force_reg (mode, x);
4187
4188   if (CONSTANT_P (y) && optimize
4189       && rtx_cost (y, COMPARE) > COSTS_N_INSNS (1))
4190     y = force_reg (mode, y);
4191
4192 #ifdef HAVE_cc0
4193   /* Make sure if we have a canonical comparison.  The RTL
4194      documentation states that canonical comparisons are required only
4195      for targets which have cc0.  */
4196   gcc_assert (!CONSTANT_P (x) || CONSTANT_P (y));
4197 #endif
4198
4199   /* Don't let both operands fail to indicate the mode.  */
4200   if (GET_MODE (x) == VOIDmode && GET_MODE (y) == VOIDmode)
4201     x = force_reg (mode, x);
4202
4203   /* Handle all BLKmode compares.  */
4204
4205   if (mode == BLKmode)
4206     {
4207       enum machine_mode cmp_mode, result_mode;
4208       enum insn_code cmp_code;
4209       tree length_type;
4210       rtx libfunc;
4211       rtx result;
4212       rtx opalign
4213         = GEN_INT (MIN (MEM_ALIGN (x), MEM_ALIGN (y)) / BITS_PER_UNIT);
4214
4215       gcc_assert (size);
4216
4217       /* Try to use a memory block compare insn - either cmpstr
4218          or cmpmem will do.  */
4219       for (cmp_mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
4220            cmp_mode != VOIDmode;
4221            cmp_mode = GET_MODE_WIDER_MODE (cmp_mode))
4222         {
4223           cmp_code = cmpmem_optab[cmp_mode];
4224           if (cmp_code == CODE_FOR_nothing)
4225             cmp_code = cmpstr_optab[cmp_mode];
4226           if (cmp_code == CODE_FOR_nothing)
4227             cmp_code = cmpstrn_optab[cmp_mode];
4228           if (cmp_code == CODE_FOR_nothing)
4229             continue;
4230
4231           /* Must make sure the size fits the insn's mode.  */
4232           if ((GET_CODE (size) == CONST_INT
4233                && INTVAL (size) >= (1 << GET_MODE_BITSIZE (cmp_mode)))
4234               || (GET_MODE_BITSIZE (GET_MODE (size))
4235                   > GET_MODE_BITSIZE (cmp_mode)))
4236             continue;
4237
4238           result_mode = insn_data[cmp_code].operand[0].mode;
4239           result = gen_reg_rtx (result_mode);
4240           size = convert_to_mode (cmp_mode, size, 1);
4241           emit_insn (GEN_FCN (cmp_code) (result, x, y, size, opalign));
4242
4243           *px = result;
4244           *py = const0_rtx;
4245           *pmode = result_mode;
4246           return;
4247         }
4248
4249       /* Otherwise call a library function, memcmp.  */
4250       libfunc = memcmp_libfunc;
4251       length_type = sizetype;
4252       result_mode = TYPE_MODE (integer_type_node);
4253       cmp_mode = TYPE_MODE (length_type);
4254       size = convert_to_mode (TYPE_MODE (length_type), size,
4255                               TYPE_UNSIGNED (length_type));
4256
4257       result = emit_library_call_value (libfunc, 0, LCT_PURE_MAKE_BLOCK,
4258                                         result_mode, 3,
4259                                         XEXP (x, 0), Pmode,
4260                                         XEXP (y, 0), Pmode,
4261                                         size, cmp_mode);
4262       *px = result;
4263       *py = const0_rtx;
4264       *pmode = result_mode;
4265       return;
4266     }
4267
4268   /* Don't allow operands to the compare to trap, as that can put the
4269      compare and branch in different basic blocks.  */
4270   if (flag_non_call_exceptions)
4271     {
4272       if (may_trap_p (x))
4273         x = force_reg (mode, x);
4274       if (may_trap_p (y))
4275         y = force_reg (mode, y);
4276     }
4277
4278   *px = x;
4279   *py = y;
4280   if (can_compare_p (*pcomparison, mode, purpose))
4281     return;
4282
4283   /* Handle a lib call just for the mode we are using.  */
4284
4285   libfunc = optab_libfunc (cmp_optab, mode);
4286   if (libfunc && !SCALAR_FLOAT_MODE_P (mode))
4287     {
4288       rtx result;
4289       rtx ulibfunc;
4290
4291       /* If we want unsigned, and this mode has a distinct unsigned
4292          comparison routine, use that.  */
4293       if (unsignedp)
4294         {
4295           ulibfunc = optab_libfunc (ucmp_optab, mode);
4296         }
4297       if (unsignedp && ulibfunc)
4298         libfunc = ulibfunc;
4299
4300       result = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST_MAKE_BLOCK,
4301                                         targetm.libgcc_cmp_return_mode (),
4302                                         2, x, mode, y, mode);
4303
4304       /* There are two kinds of comparison routines. Biased routines
4305          return 0/1/2, and unbiased routines return -1/0/1. Other parts
4306          of gcc expect that the comparison operation is equivalent
4307          to the modified comparison. For signed comparisons compare the 
4308          result against 1 in the biased case, and zero in the unbiased
4309          case. For unsigned comparisons always compare against 1 after
4310          biasing the unbiased result by adding 1. This gives us a way to
4311          represent LTU. */
4312       *px = result;
4313       *pmode = word_mode;
4314       *py = const1_rtx;
4315
4316       if (!TARGET_LIB_INT_CMP_BIASED)
4317         {
4318           if (*punsignedp)
4319             *px = plus_constant (result, 1);  
4320           else
4321             *py = const0_rtx;
4322         }
4323       return;
4324     }
4325
4326   gcc_assert (SCALAR_FLOAT_MODE_P (mode));
4327   prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp);
4328 }
4329
4330 /* Before emitting an insn with code ICODE, make sure that X, which is going
4331    to be used for operand OPNUM of the insn, is converted from mode MODE to
4332    WIDER_MODE (UNSIGNEDP determines whether it is an unsigned conversion), and
4333    that it is accepted by the operand predicate.  Return the new value.  */
4334
4335 static rtx
4336 prepare_operand (int icode, rtx x, int opnum, enum machine_mode mode,
4337                  enum machine_mode wider_mode, int unsignedp)
4338 {
4339   if (mode != wider_mode)
4340     x = convert_modes (wider_mode, mode, x, unsignedp);
4341
4342   if (!insn_data[icode].operand[opnum].predicate
4343       (x, insn_data[icode].operand[opnum].mode))
4344     {
4345       if (reload_completed)
4346         return NULL_RTX;
4347       x = copy_to_mode_reg (insn_data[icode].operand[opnum].mode, x);
4348     }
4349
4350   return x;
4351 }
4352
4353 /* Subroutine of emit_cmp_and_jump_insns; this function is called when we know
4354    we can do the comparison.
4355    The arguments are the same as for emit_cmp_and_jump_insns; but LABEL may
4356    be NULL_RTX which indicates that only a comparison is to be generated.  */
4357
4358 static void
4359 emit_cmp_and_jump_insn_1 (rtx x, rtx y, enum machine_mode mode,
4360                           enum rtx_code comparison, int unsignedp, rtx label)
4361 {
4362   rtx test = gen_rtx_fmt_ee (comparison, mode, x, y);
4363   enum mode_class class = GET_MODE_CLASS (mode);
4364   enum machine_mode wider_mode = mode;
4365
4366   /* Try combined insns first.  */
4367   do
4368     {
4369       enum insn_code icode;
4370       PUT_MODE (test, wider_mode);
4371
4372       if (label)
4373         {
4374           icode = optab_handler (cbranch_optab, wider_mode)->insn_code;
4375
4376           if (icode != CODE_FOR_nothing
4377               && insn_data[icode].operand[0].predicate (test, wider_mode))
4378             {
4379               x = prepare_operand (icode, x, 1, mode, wider_mode, unsignedp);
4380               y = prepare_operand (icode, y, 2, mode, wider_mode, unsignedp);
4381               emit_jump_insn (GEN_FCN (icode) (test, x, y, label));
4382               return;
4383             }
4384         }
4385
4386       /* Handle some compares against zero.  */
4387       icode = (int) optab_handler (tst_optab, wider_mode)->insn_code;
4388       if (y == CONST0_RTX (mode) && icode != CODE_FOR_nothing)
4389         {
4390           x = prepare_operand (icode, x, 0, mode, wider_mode, unsignedp);
4391           emit_insn (GEN_FCN (icode) (x));
4392           if (label)
4393             emit_jump_insn (bcc_gen_fctn[(int) comparison] (label));
4394           return;
4395         }
4396
4397       /* Handle compares for which there is a directly suitable insn.  */
4398
4399       icode = (int) optab_handler (cmp_optab, wider_mode)->insn_code;
4400       if (icode != CODE_FOR_nothing)
4401         {
4402           x = prepare_operand (icode, x, 0, mode, wider_mode, unsignedp);
4403           y = prepare_operand (icode, y, 1, mode, wider_mode, unsignedp);
4404           emit_insn (GEN_FCN (icode) (x, y));
4405           if (label)
4406             emit_jump_insn (bcc_gen_fctn[(int) comparison] (label));
4407           return;
4408         }
4409
4410       if (!CLASS_HAS_WIDER_MODES_P (class))
4411         break;
4412
4413       wider_mode = GET_MODE_WIDER_MODE (wider_mode);
4414     }
4415   while (wider_mode != VOIDmode);
4416
4417   gcc_unreachable ();
4418 }
4419
4420 /* Generate code to compare X with Y so that the condition codes are
4421    set and to jump to LABEL if the condition is true.  If X is a
4422    constant and Y is not a constant, then the comparison is swapped to
4423    ensure that the comparison RTL has the canonical form.
4424
4425    UNSIGNEDP nonzero says that X and Y are unsigned; this matters if they
4426    need to be widened by emit_cmp_insn.  UNSIGNEDP is also used to select
4427    the proper branch condition code.
4428
4429    If X and Y have mode BLKmode, then SIZE specifies the size of both X and Y.
4430
4431    MODE is the mode of the inputs (in case they are const_int).
4432
4433    COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).  It will
4434    be passed unchanged to emit_cmp_insn, then potentially converted into an
4435    unsigned variant based on UNSIGNEDP to select a proper jump instruction.  */
4436
4437 void
4438 emit_cmp_and_jump_insns (rtx x, rtx y, enum rtx_code comparison, rtx size,
4439                          enum machine_mode mode, int unsignedp, rtx label)
4440 {
4441   rtx op0 = x, op1 = y;
4442
4443   /* Swap operands and condition to ensure canonical RTL.  */
4444   if (swap_commutative_operands_p (x, y))
4445     {
4446       /* If we're not emitting a branch, callers are required to pass
4447          operands in an order conforming to canonical RTL.  We relax this
4448          for commutative comparisons so callers using EQ don't need to do
4449          swapping by hand.  */
4450       gcc_assert (label || (comparison == swap_condition (comparison)));
4451
4452       op0 = y, op1 = x;
4453       comparison = swap_condition (comparison);
4454     }
4455
4456 #ifdef HAVE_cc0
4457   /* If OP0 is still a constant, then both X and Y must be constants.
4458      Force X into a register to create canonical RTL.  */
4459   if (CONSTANT_P (op0))
4460     op0 = force_reg (mode, op0);
4461 #endif
4462
4463   if (unsignedp)
4464     comparison = unsigned_condition (comparison);
4465
4466   prepare_cmp_insn (&op0, &op1, &comparison, size, &mode, &unsignedp,
4467                     ccp_jump);
4468   emit_cmp_and_jump_insn_1 (op0, op1, mode, comparison, unsignedp, label);
4469 }
4470
4471 /* Like emit_cmp_and_jump_insns, but generate only the comparison.  */
4472
4473 void
4474 emit_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size,
4475                enum machine_mode mode, int unsignedp)
4476 {
4477   emit_cmp_and_jump_insns (x, y, comparison, size, mode, unsignedp, 0);
4478 }
4479 \f
4480 /* Emit a library call comparison between floating point X and Y.
4481    COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).  */
4482
4483 static void
4484 prepare_float_lib_cmp (rtx *px, rtx *py, enum rtx_code *pcomparison,
4485                        enum machine_mode *pmode, int *punsignedp)
4486 {
4487   enum rtx_code comparison = *pcomparison;
4488   enum rtx_code swapped = swap_condition (comparison);
4489   enum rtx_code reversed = reverse_condition_maybe_unordered (comparison);
4490   rtx x = *px;
4491   rtx y = *py;
4492   enum machine_mode orig_mode = GET_MODE (x);
4493   enum machine_mode mode, cmp_mode;
4494   rtx value, target, insns, equiv;
4495   rtx libfunc = 0;
4496   bool reversed_p = false;
4497   cmp_mode = targetm.libgcc_cmp_return_mode ();
4498
4499   for (mode = orig_mode;
4500        mode != VOIDmode;
4501        mode = GET_MODE_WIDER_MODE (mode))
4502     {
4503       if ((libfunc = optab_libfunc (code_to_optab[comparison], mode)))
4504         break;
4505
4506       if ((libfunc = optab_libfunc (code_to_optab[swapped] , mode)))
4507         {
4508           rtx tmp;
4509           tmp = x; x = y; y = tmp;
4510           comparison = swapped;
4511           break;
4512         }
4513
4514       if ((libfunc = optab_libfunc (code_to_optab[reversed], mode))
4515           && FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, reversed))
4516         {
4517           comparison = reversed;
4518           reversed_p = true;
4519           break;
4520         }
4521     }
4522
4523   gcc_assert (mode != VOIDmode);
4524
4525   if (mode != orig_mode)
4526     {
4527       x = convert_to_mode (mode, x, 0);
4528       y = convert_to_mode (mode, y, 0);
4529     }
4530
4531   /* Attach a REG_EQUAL note describing the semantics of the libcall to
4532      the RTL.  The allows the RTL optimizers to delete the libcall if the
4533      condition can be determined at compile-time.  */
4534   if (comparison == UNORDERED)
4535     {
4536       rtx temp = simplify_gen_relational (NE, cmp_mode, mode, x, x);
4537       equiv = simplify_gen_relational (NE, cmp_mode, mode, y, y);
4538       equiv = simplify_gen_ternary (IF_THEN_ELSE, cmp_mode, cmp_mode,
4539                                     temp, const_true_rtx, equiv);
4540     }
4541   else
4542     {
4543       equiv = simplify_gen_relational (comparison, cmp_mode, mode, x, y);
4544       if (! FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, comparison))
4545         {
4546           rtx true_rtx, false_rtx;
4547
4548           switch (comparison)
4549             {
4550             case EQ:
4551               true_rtx = const0_rtx;
4552               false_rtx = const_true_rtx;
4553               break;
4554
4555             case NE:
4556               true_rtx = const_true_rtx;
4557               false_rtx = const0_rtx;
4558               break;
4559
4560             case GT:
4561               true_rtx = const1_rtx;
4562               false_rtx = const0_rtx;
4563               break;
4564
4565             case GE:
4566               true_rtx = const0_rtx;
4567               false_rtx = constm1_rtx;
4568               break;
4569
4570             case LT:
4571               true_rtx = constm1_rtx;
4572               false_rtx = const0_rtx;
4573               break;
4574
4575             case LE:
4576               true_rtx = const0_rtx;
4577               false_rtx = const1_rtx;
4578               break;
4579
4580             default:
4581               gcc_unreachable ();
4582             }
4583           equiv = simplify_gen_ternary (IF_THEN_ELSE, cmp_mode, cmp_mode,
4584                                         equiv, true_rtx, false_rtx);
4585         }
4586     }
4587
4588   start_sequence ();
4589   value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
4590                                    cmp_mode, 2, x, mode, y, mode);
4591   insns = get_insns ();
4592   end_sequence ();
4593
4594   target = gen_reg_rtx (cmp_mode);
4595   emit_libcall_block (insns, target, value, equiv);
4596
4597   if (comparison == UNORDERED
4598       || FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, comparison))
4599     comparison = reversed_p ? EQ : NE;
4600
4601   *px = target;
4602   *py = const0_rtx;
4603   *pmode = cmp_mode;
4604   *pcomparison = comparison;
4605   *punsignedp = 0;
4606 }
4607 \f
4608 /* Generate code to indirectly jump to a location given in the rtx LOC.  */
4609
4610 void
4611 emit_indirect_jump (rtx loc)
4612 {
4613   if (!insn_data[(int) CODE_FOR_indirect_jump].operand[0].predicate
4614       (loc, Pmode))
4615     loc = copy_to_mode_reg (Pmode, loc);
4616
4617   emit_jump_insn (gen_indirect_jump (loc));
4618   emit_barrier ();
4619 }
4620 \f
4621 #ifdef HAVE_conditional_move
4622
4623 /* Emit a conditional move instruction if the machine supports one for that
4624    condition and machine mode.
4625
4626    OP0 and OP1 are the operands that should be compared using CODE.  CMODE is
4627    the mode to use should they be constants.  If it is VOIDmode, they cannot
4628    both be constants.
4629
4630    OP2 should be stored in TARGET if the comparison is true, otherwise OP3
4631    should be stored there.  MODE is the mode to use should they be constants.
4632    If it is VOIDmode, they cannot both be constants.
4633
4634    The result is either TARGET (perhaps modified) or NULL_RTX if the operation
4635    is not supported.  */
4636
4637 rtx
4638 emit_conditional_move (rtx target, enum rtx_code code, rtx op0, rtx op1,
4639                        enum machine_mode cmode, rtx op2, rtx op3,
4640                        enum machine_mode mode, int unsignedp)
4641 {
4642   rtx tem, subtarget, comparison, insn;
4643   enum insn_code icode;
4644   enum rtx_code reversed;
4645
4646   /* If one operand is constant, make it the second one.  Only do this
4647      if the other operand is not constant as well.  */
4648
4649   if (swap_commutative_operands_p (op0, op1))
4650     {
4651       tem = op0;
4652       op0 = op1;
4653       op1 = tem;
4654       code = swap_condition (code);
4655     }
4656
4657   /* get_condition will prefer to generate LT and GT even if the old
4658      comparison was against zero, so undo that canonicalization here since
4659      comparisons against zero are cheaper.  */
4660   if (code == LT && op1 == const1_rtx)
4661     code = LE, op1 = const0_rtx;
4662   else if (code == GT && op1 == constm1_rtx)
4663     code = GE, op1 = const0_rtx;
4664
4665   if (cmode == VOIDmode)
4666     cmode = GET_MODE (op0);
4667
4668   if (swap_commutative_operands_p (op2, op3)
4669       && ((reversed = reversed_comparison_code_parts (code, op0, op1, NULL))
4670           != UNKNOWN))
4671     {
4672       tem = op2;
4673       op2 = op3;
4674       op3 = tem;
4675       code = reversed;
4676     }
4677
4678   if (mode == VOIDmode)
4679     mode = GET_MODE (op2);
4680
4681   icode = movcc_gen_code[mode];
4682
4683   if (icode == CODE_FOR_nothing)
4684     return 0;
4685
4686   if (!target)
4687     target = gen_reg_rtx (mode);
4688
4689   subtarget = target;
4690
4691   /* If the insn doesn't accept these operands, put them in pseudos.  */
4692
4693   if (!insn_data[icode].operand[0].predicate
4694       (subtarget, insn_data[icode].operand[0].mode))
4695     subtarget = gen_reg_rtx (insn_data[icode].operand[0].mode);
4696
4697   if (!insn_data[icode].operand[2].predicate
4698       (op2, insn_data[icode].operand[2].mode))
4699     op2 = copy_to_mode_reg (insn_data[icode].operand[2].mode, op2);
4700
4701   if (!insn_data[icode].operand[3].predicate
4702       (op3, insn_data[icode].operand[3].mode))
4703     op3 = copy_to_mode_reg (insn_data[icode].operand[3].mode, op3);
4704
4705   /* Everything should now be in the suitable form, so emit the compare insn
4706      and then the conditional move.  */
4707
4708   comparison
4709     = compare_from_rtx (op0, op1, code, unsignedp, cmode, NULL_RTX);
4710
4711   /* ??? Watch for const0_rtx (nop) and const_true_rtx (unconditional)?  */
4712   /* We can get const0_rtx or const_true_rtx in some circumstances.  Just
4713      return NULL and let the caller figure out how best to deal with this
4714      situation.  */
4715   if (GET_CODE (comparison) != code)
4716     return NULL_RTX;
4717
4718   insn = GEN_FCN (icode) (subtarget, comparison, op2, op3);
4719
4720   /* If that failed, then give up.  */
4721   if (insn == 0)
4722     return 0;
4723
4724   emit_insn (insn);
4725
4726   if (subtarget != target)
4727     convert_move (target, subtarget, 0);
4728
4729   return target;
4730 }
4731
4732 /* Return nonzero if a conditional move of mode MODE is supported.
4733
4734    This function is for combine so it can tell whether an insn that looks
4735    like a conditional move is actually supported by the hardware.  If we
4736    guess wrong we lose a bit on optimization, but that's it.  */
4737 /* ??? sparc64 supports conditionally moving integers values based on fp
4738    comparisons, and vice versa.  How do we handle them?  */
4739
4740 int
4741 can_conditionally_move_p (enum machine_mode mode)
4742 {
4743   if (movcc_gen_code[mode] != CODE_FOR_nothing)
4744     return 1;
4745
4746   return 0;
4747 }
4748
4749 #endif /* HAVE_conditional_move */
4750
4751 /* Emit a conditional addition instruction if the machine supports one for that
4752    condition and machine mode.
4753
4754    OP0 and OP1 are the operands that should be compared using CODE.  CMODE is
4755    the mode to use should they be constants.  If it is VOIDmode, they cannot
4756    both be constants.
4757
4758    OP2 should be stored in TARGET if the comparison is true, otherwise OP2+OP3
4759    should be stored there.  MODE is the mode to use should they be constants.
4760    If it is VOIDmode, they cannot both be constants.
4761
4762    The result is either TARGET (perhaps modified) or NULL_RTX if the operation
4763    is not supported.  */
4764
4765 rtx
4766 emit_conditional_add (rtx target, enum rtx_code code, rtx op0, rtx op1,
4767                       enum machine_mode cmode, rtx op2, rtx op3,
4768                       enum machine_mode mode, int unsignedp)
4769 {
4770   rtx tem, subtarget, comparison, insn;
4771   enum insn_code icode;
4772   enum rtx_code reversed;
4773
4774   /* If one operand is constant, make it the second one.  Only do this
4775      if the other operand is not constant as well.  */
4776
4777   if (swap_commutative_operands_p (op0, op1))
4778     {
4779       tem = op0;
4780       op0 = op1;
4781       op1 = tem;
4782       code = swap_condition (code);
4783     }
4784
4785   /* get_condition will prefer to generate LT and GT even if the old
4786      comparison was against zero, so undo that canonicalization here since
4787      comparisons against zero are cheaper.  */
4788   if (code == LT && op1 == const1_rtx)
4789     code = LE, op1 = const0_rtx;
4790   else if (code == GT && op1 == constm1_rtx)
4791     code = GE, op1 = const0_rtx;
4792
4793   if (cmode == VOIDmode)
4794     cmode = GET_MODE (op0);
4795
4796   if (swap_commutative_operands_p (op2, op3)
4797       && ((reversed = reversed_comparison_code_parts (code, op0, op1, NULL))
4798           != UNKNOWN))
4799     {
4800       tem = op2;
4801       op2 = op3;
4802       op3 = tem;
4803       code = reversed;
4804     }
4805
4806   if (mode == VOIDmode)
4807     mode = GET_MODE (op2);
4808
4809   icode = optab_handler (addcc_optab, mode)->insn_code;
4810
4811   if (icode == CODE_FOR_nothing)
4812     return 0;
4813
4814   if (!target)
4815     target = gen_reg_rtx (mode);
4816
4817   /* If the insn doesn't accept these operands, put them in pseudos.  */
4818
4819   if (!insn_data[icode].operand[0].predicate
4820       (target, insn_data[icode].operand[0].mode))
4821     subtarget = gen_reg_rtx (insn_data[icode].operand[0].mode);
4822   else
4823     subtarget = target;
4824
4825   if (!insn_data[icode].operand[2].predicate
4826       (op2, insn_data[icode].operand[2].mode))
4827     op2 = copy_to_mode_reg (insn_data[icode].operand[2].mode, op2);
4828
4829   if (!insn_data[icode].operand[3].predicate
4830       (op3, insn_data[icode].operand[3].mode))
4831     op3 = copy_to_mode_reg (insn_data[icode].operand[3].mode, op3);
4832
4833   /* Everything should now be in the suitable form, so emit the compare insn
4834      and then the conditional move.  */
4835
4836   comparison
4837     = compare_from_rtx (op0, op1, code, unsignedp, cmode, NULL_RTX);
4838
4839   /* ??? Watch for const0_rtx (nop) and const_true_rtx (unconditional)?  */
4840   /* We can get const0_rtx or const_true_rtx in some circumstances.  Just
4841      return NULL and let the caller figure out how best to deal with this
4842      situation.  */
4843   if (GET_CODE (comparison) != code)
4844     return NULL_RTX;
4845
4846   insn = GEN_FCN (icode) (subtarget, comparison, op2, op3);
4847
4848   /* If that failed, then give up.  */
4849   if (insn == 0)
4850     return 0;
4851
4852   emit_insn (insn);
4853
4854   if (subtarget != target)
4855     convert_move (target, subtarget, 0);
4856
4857   return target;
4858 }
4859 \f
4860 /* These functions attempt to generate an insn body, rather than
4861    emitting the insn, but if the gen function already emits them, we
4862    make no attempt to turn them back into naked patterns.  */
4863
4864 /* Generate and return an insn body to add Y to X.  */
4865
4866 rtx
4867 gen_add2_insn (rtx x, rtx y)
4868 {
4869   int icode = (int) optab_handler (add_optab, GET_MODE (x))->insn_code;
4870
4871   gcc_assert (insn_data[icode].operand[0].predicate
4872               (x, insn_data[icode].operand[0].mode));
4873   gcc_assert (insn_data[icode].operand[1].predicate
4874               (x, insn_data[icode].operand[1].mode));
4875   gcc_assert (insn_data[icode].operand[2].predicate
4876               (y, insn_data[icode].operand[2].mode));
4877
4878   return GEN_FCN (icode) (x, x, y);
4879 }
4880
4881 /* Generate and return an insn body to add r1 and c,
4882    storing the result in r0.  */
4883
4884 rtx
4885 gen_add3_insn (rtx r0, rtx r1, rtx c)
4886 {
4887   int icode = (int) optab_handler (add_optab, GET_MODE (r0))->insn_code;
4888
4889   if (icode == CODE_FOR_nothing
4890       || !(insn_data[icode].operand[0].predicate
4891            (r0, insn_data[icode].operand[0].mode))
4892       || !(insn_data[icode].operand[1].predicate
4893            (r1, insn_data[icode].operand[1].mode))
4894       || !(insn_data[icode].operand[2].predicate
4895            (c, insn_data[icode].operand[2].mode)))
4896     return NULL_RTX;
4897
4898   return GEN_FCN (icode) (r0, r1, c);
4899 }
4900
4901 int
4902 have_add2_insn (rtx x, rtx y)
4903 {
4904   int icode;
4905
4906   gcc_assert (GET_MODE (x) != VOIDmode);
4907
4908   icode = (int) optab_handler (add_optab, GET_MODE (x))->insn_code;
4909
4910   if (icode == CODE_FOR_nothing)
4911     return 0;
4912
4913   if (!(insn_data[icode].operand[0].predicate
4914         (x, insn_data[icode].operand[0].mode))
4915       || !(insn_data[icode].operand[1].predicate
4916            (x, insn_data[icode].operand[1].mode))
4917       || !(insn_data[icode].operand[2].predicate
4918            (y, insn_data[icode].operand[2].mode)))
4919     return 0;
4920
4921   return 1;
4922 }
4923
4924 /* Generate and return an insn body to subtract Y from X.  */
4925
4926 rtx
4927 gen_sub2_insn (rtx x, rtx y)
4928 {
4929   int icode = (int) optab_handler (sub_optab, GET_MODE (x))->insn_code;
4930
4931   gcc_assert (insn_data[icode].operand[0].predicate
4932               (x, insn_data[icode].operand[0].mode));
4933   gcc_assert (insn_data[icode].operand[1].predicate
4934               (x, insn_data[icode].operand[1].mode));
4935   gcc_assert  (insn_data[icode].operand[2].predicate
4936                (y, insn_data[icode].operand[2].mode));
4937
4938   return GEN_FCN (icode) (x, x, y);
4939 }
4940
4941 /* Generate and return an insn body to subtract r1 and c,
4942    storing the result in r0.  */
4943
4944 rtx
4945 gen_sub3_insn (rtx r0, rtx r1, rtx c)
4946 {
4947   int icode = (int) optab_handler (sub_optab, GET_MODE (r0))->insn_code;
4948
4949   if (icode == CODE_FOR_nothing
4950       || !(insn_data[icode].operand[0].predicate
4951            (r0, insn_data[icode].operand[0].mode))
4952       || !(insn_data[icode].operand[1].predicate
4953            (r1, insn_data[icode].operand[1].mode))
4954       || !(insn_data[icode].operand[2].predicate
4955            (c, insn_data[icode].operand[2].mode)))
4956     return NULL_RTX;
4957
4958   return GEN_FCN (icode) (r0, r1, c);
4959 }
4960
4961 int
4962 have_sub2_insn (rtx x, rtx y)
4963 {
4964   int icode;
4965
4966   gcc_assert (GET_MODE (x) != VOIDmode);
4967
4968   icode = (int) optab_handler (sub_optab, GET_MODE (x))->insn_code;
4969
4970   if (icode == CODE_FOR_nothing)
4971     return 0;
4972
4973   if (!(insn_data[icode].operand[0].predicate
4974         (x, insn_data[icode].operand[0].mode))
4975       || !(insn_data[icode].operand[1].predicate
4976            (x, insn_data[icode].operand[1].mode))
4977       || !(insn_data[icode].operand[2].predicate
4978            (y, insn_data[icode].operand[2].mode)))
4979     return 0;
4980
4981   return 1;
4982 }
4983
4984 /* Generate the body of an instruction to copy Y into X.
4985    It may be a list of insns, if one insn isn't enough.  */
4986
4987 rtx
4988 gen_move_insn (rtx x, rtx y)
4989 {
4990   rtx seq;
4991
4992   start_sequence ();
4993   emit_move_insn_1 (x, y);
4994   seq = get_insns ();
4995   end_sequence ();
4996   return seq;
4997 }
4998 \f
4999 /* Return the insn code used to extend FROM_MODE to TO_MODE.
5000    UNSIGNEDP specifies zero-extension instead of sign-extension.  If
5001    no such operation exists, CODE_FOR_nothing will be returned.  */
5002
5003 enum insn_code
5004 can_extend_p (enum machine_mode to_mode, enum machine_mode from_mode,
5005               int unsignedp)
5006 {
5007   convert_optab tab;
5008 #ifdef HAVE_ptr_extend
5009   if (unsignedp < 0)
5010     return CODE_FOR_ptr_extend;
5011 #endif
5012
5013   tab = unsignedp ? zext_optab : sext_optab;
5014   return convert_optab_handler (tab, to_mode, from_mode)->insn_code;
5015 }
5016
5017 /* Generate the body of an insn to extend Y (with mode MFROM)
5018    into X (with mode MTO).  Do zero-extension if UNSIGNEDP is nonzero.  */
5019
5020 rtx
5021 gen_extend_insn (rtx x, rtx y, enum machine_mode mto,
5022                  enum machine_mode mfrom, int unsignedp)
5023 {
5024   enum insn_code icode = can_extend_p (mto, mfrom, unsignedp);
5025   return GEN_FCN (icode) (x, y);
5026 }
5027 \f
5028 /* can_fix_p and can_float_p say whether the target machine
5029    can directly convert a given fixed point type to
5030    a given floating point type, or vice versa.
5031    The returned value is the CODE_FOR_... value to use,
5032    or CODE_FOR_nothing if these modes cannot be directly converted.
5033
5034    *TRUNCP_PTR is set to 1 if it is necessary to output
5035    an explicit FTRUNC insn before the fix insn; otherwise 0.  */
5036
5037 static enum insn_code
5038 can_fix_p (enum machine_mode fixmode, enum machine_mode fltmode,
5039            int unsignedp, int *truncp_ptr)
5040 {
5041   convert_optab tab;
5042   enum insn_code icode;
5043
5044   tab = unsignedp ? ufixtrunc_optab : sfixtrunc_optab;
5045   icode = convert_optab_handler (tab, fixmode, fltmode)->insn_code;
5046   if (icode != CODE_FOR_nothing)
5047     {
5048       *truncp_ptr = 0;
5049       return icode;
5050     }
5051
5052   /* FIXME: This requires a port to define both FIX and FTRUNC pattern
5053      for this to work. We need to rework the fix* and ftrunc* patterns
5054      and documentation.  */
5055   tab = unsignedp ? ufix_optab : sfix_optab;
5056   icode = convert_optab_handler (tab, fixmode, fltmode)->insn_code;
5057   if (icode != CODE_FOR_nothing
5058       && optab_handler (ftrunc_optab, fltmode)->insn_code != CODE_FOR_nothing)
5059     {
5060       *truncp_ptr = 1;
5061       return icode;
5062     }
5063
5064   *truncp_ptr = 0;
5065   return CODE_FOR_nothing;
5066 }
5067
5068 static enum insn_code
5069 can_float_p (enum machine_mode fltmode, enum machine_mode fixmode,
5070              int unsignedp)
5071 {
5072   convert_optab tab;
5073
5074   tab = unsignedp ? ufloat_optab : sfloat_optab;
5075   return convert_optab_handler (tab, fltmode, fixmode)->insn_code;
5076 }
5077 \f
5078 /* Generate code to convert FROM to floating point
5079    and store in TO.  FROM must be fixed point and not VOIDmode.
5080    UNSIGNEDP nonzero means regard FROM as unsigned.
5081    Normally this is done by correcting the final value
5082    if it is negative.  */
5083
5084 void
5085 expand_float (rtx to, rtx from, int unsignedp)
5086 {
5087   enum insn_code icode;
5088   rtx target = to;
5089   enum machine_mode fmode, imode;
5090   bool can_do_signed = false;
5091
5092   /* Crash now, because we won't be able to decide which mode to use.  */
5093   gcc_assert (GET_MODE (from) != VOIDmode);
5094
5095   /* Look for an insn to do the conversion.  Do it in the specified
5096      modes if possible; otherwise convert either input, output or both to
5097      wider mode.  If the integer mode is wider than the mode of FROM,
5098      we can do the conversion signed even if the input is unsigned.  */
5099
5100   for (fmode = GET_MODE (to); fmode != VOIDmode;
5101        fmode = GET_MODE_WIDER_MODE (fmode))
5102     for (imode = GET_MODE (from); imode != VOIDmode;
5103          imode = GET_MODE_WIDER_MODE (imode))
5104       {
5105         int doing_unsigned = unsignedp;
5106
5107         if (fmode != GET_MODE (to)
5108             && significand_size (fmode) < GET_MODE_BITSIZE (GET_MODE (from)))
5109           continue;
5110
5111         icode = can_float_p (fmode, imode, unsignedp);
5112         if (icode == CODE_FOR_nothing && unsignedp)
5113           {
5114             enum insn_code scode = can_float_p (fmode, imode, 0);
5115             if (scode != CODE_FOR_nothing)
5116               can_do_signed = true;
5117             if (imode != GET_MODE (from))
5118               icode = scode, doing_unsigned = 0;
5119           }
5120
5121         if (icode != CODE_FOR_nothing)
5122           {
5123             if (imode != GET_MODE (from))
5124               from = convert_to_mode (imode, from, unsignedp);
5125
5126             if (fmode != GET_MODE (to))
5127               target = gen_reg_rtx (fmode);
5128
5129             emit_unop_insn (icode, target, from,
5130                             doing_unsigned ? UNSIGNED_FLOAT : FLOAT);
5131
5132             if (target != to)
5133               convert_move (to, target, 0);
5134             return;
5135           }
5136       }
5137
5138   /* Unsigned integer, and no way to convert directly.  For binary
5139      floating point modes, convert as signed, then conditionally adjust
5140      the result.  */
5141   if (unsignedp && can_do_signed && !DECIMAL_FLOAT_MODE_P (GET_MODE (to)))
5142     {
5143       rtx label = gen_label_rtx ();
5144       rtx temp;
5145       REAL_VALUE_TYPE offset;
5146
5147       /* Look for a usable floating mode FMODE wider than the source and at
5148          least as wide as the target.  Using FMODE will avoid rounding woes
5149          with unsigned values greater than the signed maximum value.  */
5150
5151       for (fmode = GET_MODE (to);  fmode != VOIDmode;
5152            fmode = GET_MODE_WIDER_MODE (fmode))
5153         if (GET_MODE_BITSIZE (GET_MODE (from)) < GET_MODE_BITSIZE (fmode)
5154             && can_float_p (fmode, GET_MODE (from), 0) != CODE_FOR_nothing)
5155           break;
5156
5157       if (fmode == VOIDmode)
5158         {
5159           /* There is no such mode.  Pretend the target is wide enough.  */
5160           fmode = GET_MODE (to);
5161
5162           /* Avoid double-rounding when TO is narrower than FROM.  */
5163           if ((significand_size (fmode) + 1)
5164               < GET_MODE_BITSIZE (GET_MODE (from)))
5165             {
5166               rtx temp1;
5167               rtx neglabel = gen_label_rtx ();
5168
5169               /* Don't use TARGET if it isn't a register, is a hard register,
5170                  or is the wrong mode.  */
5171               if (!REG_P (target)
5172                   || REGNO (target) < FIRST_PSEUDO_REGISTER
5173                   || GET_MODE (target) != fmode)
5174                 target = gen_reg_rtx (fmode);
5175
5176               imode = GET_MODE (from);
5177               do_pending_stack_adjust ();
5178
5179               /* Test whether the sign bit is set.  */
5180               emit_cmp_and_jump_insns (from, const0_rtx, LT, NULL_RTX, imode,
5181                                        0, neglabel);
5182
5183               /* The sign bit is not set.  Convert as signed.  */
5184               expand_float (target, from, 0);
5185               emit_jump_insn (gen_jump (label));
5186               emit_barrier ();
5187
5188               /* The sign bit is set.
5189                  Convert to a usable (positive signed) value by shifting right
5190                  one bit, while remembering if a nonzero bit was shifted
5191                  out; i.e., compute  (from & 1) | (from >> 1).  */
5192
5193               emit_label (neglabel);
5194               temp = expand_binop (imode, and_optab, from, const1_rtx,
5195                                    NULL_RTX, 1, OPTAB_LIB_WIDEN);
5196               temp1 = expand_shift (RSHIFT_EXPR, imode, from, integer_one_node,
5197                                     NULL_RTX, 1);
5198               temp = expand_binop (imode, ior_optab, temp, temp1, temp, 1,
5199                                    OPTAB_LIB_WIDEN);
5200               expand_float (target, temp, 0);
5201
5202               /* Multiply by 2 to undo the shift above.  */
5203               temp = expand_binop (fmode, add_optab, target, target,
5204                                    target, 0, OPTAB_LIB_WIDEN);
5205               if (temp != target)
5206                 emit_move_insn (target, temp);
5207
5208               do_pending_stack_adjust ();
5209               emit_label (label);
5210               goto done;
5211             }
5212         }
5213
5214       /* If we are about to do some arithmetic to correct for an
5215          unsigned operand, do it in a pseudo-register.  */
5216
5217       if (GET_MODE (to) != fmode
5218           || !REG_P (to) || REGNO (to) < FIRST_PSEUDO_REGISTER)
5219         target = gen_reg_rtx (fmode);
5220
5221       /* Convert as signed integer to floating.  */
5222       expand_float (target, from, 0);
5223
5224       /* If FROM is negative (and therefore TO is negative),
5225          correct its value by 2**bitwidth.  */
5226
5227       do_pending_stack_adjust ();
5228       emit_cmp_and_jump_insns (from, const0_rtx, GE, NULL_RTX, GET_MODE (from),
5229                                0, label);
5230
5231
5232       real_2expN (&offset, GET_MODE_BITSIZE (GET_MODE (from)));
5233       temp = expand_binop (fmode, add_optab, target,
5234                            CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode),
5235                            target, 0, OPTAB_LIB_WIDEN);
5236       if (temp != target)
5237         emit_move_insn (target, temp);
5238
5239       do_pending_stack_adjust ();
5240       emit_label (label);
5241       goto done;
5242     }
5243
5244   /* No hardware instruction available; call a library routine.  */
5245     {
5246       rtx libfunc;
5247       rtx insns;
5248       rtx value;
5249       convert_optab tab = unsignedp ? ufloat_optab : sfloat_optab;
5250
5251       if (GET_MODE_SIZE (GET_MODE (from)) < GET_MODE_SIZE (SImode))
5252         from = convert_to_mode (SImode, from, unsignedp);
5253
5254       libfunc = convert_optab_libfunc (tab, GET_MODE (to), GET_MODE (from));
5255       gcc_assert (libfunc);
5256
5257       start_sequence ();
5258
5259       value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
5260                                        GET_MODE (to), 1, from,
5261                                        GET_MODE (from));
5262       insns = get_insns ();
5263       end_sequence ();
5264
5265       emit_libcall_block (insns, target, value,
5266                           gen_rtx_FLOAT (GET_MODE (to), from));
5267     }
5268
5269  done:
5270
5271   /* Copy result to requested destination
5272      if we have been computing in a temp location.  */
5273
5274   if (target != to)
5275     {
5276       if (GET_MODE (target) == GET_MODE (to))
5277         emit_move_insn (to, target);
5278       else
5279         convert_move (to, target, 0);
5280     }
5281 }
5282 \f
5283 /* Generate code to convert FROM to fixed point and store in TO.  FROM
5284    must be floating point.  */
5285
5286 void
5287 expand_fix (rtx to, rtx from, int unsignedp)
5288 {
5289   enum insn_code icode;
5290   rtx target = to;
5291   enum machine_mode fmode, imode;
5292   int must_trunc = 0;
5293
5294   /* We first try to find a pair of modes, one real and one integer, at
5295      least as wide as FROM and TO, respectively, in which we can open-code
5296      this conversion.  If the integer mode is wider than the mode of TO,
5297      we can do the conversion either signed or unsigned.  */
5298
5299   for (fmode = GET_MODE (from); fmode != VOIDmode;
5300        fmode = GET_MODE_WIDER_MODE (fmode))
5301     for (imode = GET_MODE (to); imode != VOIDmode;
5302          imode = GET_MODE_WIDER_MODE (imode))
5303       {
5304         int doing_unsigned = unsignedp;
5305
5306         icode = can_fix_p (imode, fmode, unsignedp, &must_trunc);
5307         if (icode == CODE_FOR_nothing && imode != GET_MODE (to) && unsignedp)
5308           icode = can_fix_p (imode, fmode, 0, &must_trunc), doing_unsigned = 0;
5309
5310         if (icode != CODE_FOR_nothing)
5311           {
5312             if (fmode != GET_MODE (from))
5313               from = convert_to_mode (fmode, from, 0);
5314
5315             if (must_trunc)
5316               {
5317                 rtx temp = gen_reg_rtx (GET_MODE (from));
5318                 from = expand_unop (GET_MODE (from), ftrunc_optab, from,
5319                                     temp, 0);
5320               }
5321
5322             if (imode != GET_MODE (to))
5323               target = gen_reg_rtx (imode);
5324
5325             emit_unop_insn (icode, target, from,
5326                             doing_unsigned ? UNSIGNED_FIX : FIX);
5327             if (target != to)
5328               convert_move (to, target, unsignedp);
5329             return;
5330           }
5331       }
5332
5333   /* For an unsigned conversion, there is one more way to do it.
5334      If we have a signed conversion, we generate code that compares
5335      the real value to the largest representable positive number.  If if
5336      is smaller, the conversion is done normally.  Otherwise, subtract
5337      one plus the highest signed number, convert, and add it back.
5338
5339      We only need to check all real modes, since we know we didn't find
5340      anything with a wider integer mode.
5341
5342      This code used to extend FP value into mode wider than the destination.
5343      This is not needed.  Consider, for instance conversion from SFmode
5344      into DImode.
5345
5346      The hot path through the code is dealing with inputs smaller than 2^63
5347      and doing just the conversion, so there is no bits to lose.
5348
5349      In the other path we know the value is positive in the range 2^63..2^64-1
5350      inclusive.  (as for other imput overflow happens and result is undefined)
5351      So we know that the most important bit set in mantissa corresponds to
5352      2^63.  The subtraction of 2^63 should not generate any rounding as it
5353      simply clears out that bit.  The rest is trivial.  */
5354
5355   if (unsignedp && GET_MODE_BITSIZE (GET_MODE (to)) <= HOST_BITS_PER_WIDE_INT)
5356     for (fmode = GET_MODE (from); fmode != VOIDmode;
5357          fmode = GET_MODE_WIDER_MODE (fmode))
5358       if (CODE_FOR_nothing != can_fix_p (GET_MODE (to), fmode, 0,
5359                                          &must_trunc))
5360         {
5361           int bitsize;
5362           REAL_VALUE_TYPE offset;
5363           rtx limit, lab1, lab2, insn;
5364
5365           bitsize = GET_MODE_BITSIZE (GET_MODE (to));
5366           real_2expN (&offset, bitsize - 1);
5367           limit = CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode);
5368           lab1 = gen_label_rtx ();
5369           lab2 = gen_label_rtx ();
5370
5371           if (fmode != GET_MODE (from))
5372             from = convert_to_mode (fmode, from, 0);
5373
5374           /* See if we need to do the subtraction.  */
5375           do_pending_stack_adjust ();
5376           emit_cmp_and_jump_insns (from, limit, GE, NULL_RTX, GET_MODE (from),
5377                                    0, lab1);
5378
5379           /* If not, do the signed "fix" and branch around fixup code.  */
5380           expand_fix (to, from, 0);
5381           emit_jump_insn (gen_jump (lab2));
5382           emit_barrier ();
5383
5384           /* Otherwise, subtract 2**(N-1), convert to signed number,
5385              then add 2**(N-1).  Do the addition using XOR since this
5386              will often generate better code.  */
5387           emit_label (lab1);
5388           target = expand_binop (GET_MODE (from), sub_optab, from, limit,
5389                                  NULL_RTX, 0, OPTAB_LIB_WIDEN);
5390           expand_fix (to, target, 0);
5391           target = expand_binop (GET_MODE (to), xor_optab, to,
5392                                  gen_int_mode
5393                                  ((HOST_WIDE_INT) 1 << (bitsize - 1),
5394                                   GET_MODE (to)),
5395                                  to, 1, OPTAB_LIB_WIDEN);
5396
5397           if (target != to)
5398             emit_move_insn (to, target);
5399
5400           emit_label (lab2);
5401
5402           if (optab_handler (mov_optab, GET_MODE (to))->insn_code
5403               != CODE_FOR_nothing)
5404             {
5405               /* Make a place for a REG_NOTE and add it.  */
5406               insn = emit_move_insn (to, to);
5407               set_unique_reg_note (insn,
5408                                    REG_EQUAL,
5409                                    gen_rtx_fmt_e (UNSIGNED_FIX,
5410                                                   GET_MODE (to),
5411                                                   copy_rtx (from)));
5412             }
5413
5414           return;
5415         }
5416
5417   /* We can't do it with an insn, so use a library call.  But first ensure
5418      that the mode of TO is at least as wide as SImode, since those are the
5419      only library calls we know about.  */
5420
5421   if (GET_MODE_SIZE (GET_MODE (to)) < GET_MODE_SIZE (SImode))
5422     {
5423       target = gen_reg_rtx (SImode);
5424
5425       expand_fix (target, from, unsignedp);
5426     }
5427   else
5428     {
5429       rtx insns;
5430       rtx value;
5431       rtx libfunc;
5432
5433       convert_optab tab = unsignedp ? ufix_optab : sfix_optab;
5434       libfunc = convert_optab_libfunc (tab, GET_MODE (to), GET_MODE (from));
5435       gcc_assert (libfunc);
5436
5437       start_sequence ();
5438
5439       value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
5440                                        GET_MODE (to), 1, from,
5441                                        GET_MODE (from));
5442       insns = get_insns ();
5443       end_sequence ();
5444
5445       emit_libcall_block (insns, target, value,
5446                           gen_rtx_fmt_e (unsignedp ? UNSIGNED_FIX : FIX,
5447                                          GET_MODE (to), from));
5448     }
5449
5450   if (target != to)
5451     {
5452       if (GET_MODE (to) == GET_MODE (target))
5453         emit_move_insn (to, target);
5454       else
5455         convert_move (to, target, 0);
5456     }
5457 }
5458
5459 /* Generate code to convert FROM or TO a fixed-point.
5460    If UINTP is true, either TO or FROM is an unsigned integer.
5461    If SATP is true, we need to saturate the result.  */
5462
5463 void
5464 expand_fixed_convert (rtx to, rtx from, int uintp, int satp)
5465 {
5466   enum machine_mode to_mode = GET_MODE (to);
5467   enum machine_mode from_mode = GET_MODE (from);
5468   convert_optab tab;
5469   enum rtx_code this_code;
5470   enum insn_code code;
5471   rtx insns, value;
5472   rtx libfunc;
5473
5474   if (to_mode == from_mode)
5475     {
5476       emit_move_insn (to, from);
5477       return;
5478     }
5479
5480   if (uintp)
5481     {
5482       tab = satp ? satfractuns_optab : fractuns_optab;
5483       this_code = satp ? UNSIGNED_SAT_FRACT : UNSIGNED_FRACT_CONVERT;
5484     }
5485   else
5486     {
5487       tab = satp ? satfract_optab : fract_optab;
5488       this_code = satp ? SAT_FRACT : FRACT_CONVERT;
5489     }
5490   code = tab->handlers[to_mode][from_mode].insn_code;
5491   if (code != CODE_FOR_nothing)
5492     {
5493       emit_unop_insn (code, to, from, this_code);
5494       return;
5495     }
5496
5497   libfunc = convert_optab_libfunc (tab, to_mode, from_mode);
5498   gcc_assert (libfunc);
5499
5500   start_sequence ();
5501   value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST, to_mode,
5502                                    1, from, from_mode);
5503   insns = get_insns ();
5504   end_sequence ();
5505
5506   emit_libcall_block (insns, to, value,
5507                       gen_rtx_fmt_e (tab->code, to_mode, from));
5508 }
5509
5510 /* Generate code to convert FROM to fixed point and store in TO.  FROM
5511    must be floating point, TO must be signed.  Use the conversion optab
5512    TAB to do the conversion.  */
5513
5514 bool
5515 expand_sfix_optab (rtx to, rtx from, convert_optab tab)
5516 {
5517   enum insn_code icode;
5518   rtx target = to;
5519   enum machine_mode fmode, imode;
5520
5521   /* We first try to find a pair of modes, one real and one integer, at
5522      least as wide as FROM and TO, respectively, in which we can open-code
5523      this conversion.  If the integer mode is wider than the mode of TO,
5524      we can do the conversion either signed or unsigned.  */
5525
5526   for (fmode = GET_MODE (from); fmode != VOIDmode;
5527        fmode = GET_MODE_WIDER_MODE (fmode))
5528     for (imode = GET_MODE (to); imode != VOIDmode;
5529          imode = GET_MODE_WIDER_MODE (imode))
5530       {
5531         icode = convert_optab_handler (tab, imode, fmode)->insn_code;
5532         if (icode != CODE_FOR_nothing)
5533           {
5534             if (fmode != GET_MODE (from))
5535               from = convert_to_mode (fmode, from, 0);
5536
5537             if (imode != GET_MODE (to))
5538               target = gen_reg_rtx (imode);
5539
5540             emit_unop_insn (icode, target, from, UNKNOWN);
5541             if (target != to)
5542               convert_move (to, target, 0);
5543             return true;
5544           }
5545       }
5546
5547   return false;
5548 }
5549 \f
5550 /* Report whether we have an instruction to perform the operation
5551    specified by CODE on operands of mode MODE.  */
5552 int
5553 have_insn_for (enum rtx_code code, enum machine_mode mode)
5554 {
5555   return (code_to_optab[(int) code] != 0
5556           && (optab_handler (code_to_optab[(int) code], mode)->insn_code
5557               != CODE_FOR_nothing));
5558 }
5559
5560 /* Create a blank optab.  */
5561 static optab
5562 new_optab (void)
5563 {
5564   int i;
5565   optab op = xcalloc (sizeof (struct optab), 1);
5566
5567   for (i = 0; i < NUM_MACHINE_MODES; i++)
5568     optab_handler (op, i)->insn_code = CODE_FOR_nothing;
5569
5570   return op;
5571 }
5572
5573 static convert_optab
5574 new_convert_optab (void)
5575 {
5576   int i, j;
5577   convert_optab op = xcalloc (sizeof (struct convert_optab), 1);
5578
5579   for (i = 0; i < NUM_MACHINE_MODES; i++)
5580     for (j = 0; j < NUM_MACHINE_MODES; j++)
5581       convert_optab_handler (op, i, j)->insn_code = CODE_FOR_nothing;
5582
5583   return op;
5584 }
5585
5586 /* Same, but fill in its code as CODE, and write it into the
5587    code_to_optab table.  */
5588 static inline optab
5589 init_optab (enum rtx_code code)
5590 {
5591   optab op = new_optab ();
5592   op->code = code;
5593   code_to_optab[(int) code] = op;
5594   return op;
5595 }
5596
5597 /* Same, but fill in its code as CODE, and do _not_ write it into
5598    the code_to_optab table.  */
5599 static inline optab
5600 init_optabv (enum rtx_code code)
5601 {
5602   optab op = new_optab ();
5603   op->code = code;
5604   return op;
5605 }
5606
5607 /* Conversion optabs never go in the code_to_optab table.  */
5608 static inline convert_optab
5609 init_convert_optab (enum rtx_code code)
5610 {
5611   convert_optab op = new_convert_optab ();
5612   op->code = code;
5613   return op;
5614 }
5615
5616 /* Initialize the libfunc fields of an entire group of entries in some
5617    optab.  Each entry is set equal to a string consisting of a leading
5618    pair of underscores followed by a generic operation name followed by
5619    a mode name (downshifted to lowercase) followed by a single character
5620    representing the number of operands for the given operation (which is
5621    usually one of the characters '2', '3', or '4').
5622
5623    OPTABLE is the table in which libfunc fields are to be initialized.
5624    OPNAME is the generic (string) name of the operation.
5625    SUFFIX is the character which specifies the number of operands for
5626      the given generic operation.
5627    MODE is the mode to generate for.
5628 */
5629
5630 static void
5631 gen_libfunc (optab optable, const char *opname, int suffix, enum machine_mode mode)
5632 {
5633   unsigned opname_len = strlen (opname);
5634   const char *mname = GET_MODE_NAME (mode);
5635   unsigned mname_len = strlen (mname);
5636   char *libfunc_name = alloca (2 + opname_len + mname_len + 1 + 1);
5637   char *p;
5638   const char *q;
5639
5640   p = libfunc_name;
5641   *p++ = '_';
5642   *p++ = '_';
5643   for (q = opname; *q; )
5644     *p++ = *q++;
5645   for (q = mname; *q; q++)
5646     *p++ = TOLOWER (*q);
5647   *p++ = suffix;
5648   *p = '\0';
5649
5650   set_optab_libfunc (optable, mode,
5651                      ggc_alloc_string (libfunc_name, p - libfunc_name));
5652 }
5653
5654 /* Like gen_libfunc, but verify that integer operation is involved.  */
5655
5656 static void
5657 gen_int_libfunc (optab optable, const char *opname, char suffix,
5658                  enum machine_mode mode)
5659 {
5660   int maxsize = 2 * BITS_PER_WORD;
5661
5662   if (GET_MODE_CLASS (mode) != MODE_INT)
5663     return;
5664   if (maxsize < LONG_LONG_TYPE_SIZE)
5665     maxsize = LONG_LONG_TYPE_SIZE;
5666   if (GET_MODE_CLASS (mode) != MODE_INT
5667       || mode < word_mode || GET_MODE_BITSIZE (mode) > maxsize)
5668     return;
5669   gen_libfunc (optable, opname, suffix, mode);
5670 }
5671
5672 /* Like gen_libfunc, but verify that FP and set decimal prefix if needed.  */
5673
5674 static void
5675 gen_fp_libfunc (optab optable, const char *opname, char suffix,
5676                 enum machine_mode mode)
5677 {
5678   char *dec_opname;
5679
5680   if (GET_MODE_CLASS (mode) == MODE_FLOAT)
5681     gen_libfunc (optable, opname, suffix, mode);
5682   if (DECIMAL_FLOAT_MODE_P (mode))
5683     {
5684       dec_opname = alloca (sizeof (DECIMAL_PREFIX) + strlen (opname));
5685       /* For BID support, change the name to have either a bid_ or dpd_ prefix
5686          depending on the low level floating format used.  */
5687       memcpy (dec_opname, DECIMAL_PREFIX, sizeof (DECIMAL_PREFIX) - 1);
5688       strcpy (dec_opname + sizeof (DECIMAL_PREFIX) - 1, opname);
5689       gen_libfunc (optable, dec_opname, suffix, mode);
5690     }
5691 }
5692
5693 /* Like gen_libfunc, but verify that fixed-point operation is involved.  */
5694
5695 static void
5696 gen_fixed_libfunc (optab optable, const char *opname, char suffix,
5697                    enum machine_mode mode)
5698 {
5699   if (!ALL_FIXED_POINT_MODE_P (mode))
5700     return;
5701   gen_libfunc (optable, opname, suffix, mode);
5702 }
5703
5704 /* Like gen_libfunc, but verify that signed fixed-point operation is
5705    involved.  */
5706
5707 static void
5708 gen_signed_fixed_libfunc (optab optable, const char *opname, char suffix,
5709                           enum machine_mode mode)
5710 {
5711   if (!SIGNED_FIXED_POINT_MODE_P (mode))
5712     return;
5713   gen_libfunc (optable, opname, suffix, mode);
5714 }
5715
5716 /* Like gen_libfunc, but verify that unsigned fixed-point operation is
5717    involved.  */
5718
5719 static void
5720 gen_unsigned_fixed_libfunc (optab optable, const char *opname, char suffix,
5721                             enum machine_mode mode)
5722 {
5723   if (!UNSIGNED_FIXED_POINT_MODE_P (mode))
5724     return;
5725   gen_libfunc (optable, opname, suffix, mode);
5726 }
5727
5728 /* Like gen_libfunc, but verify that FP or INT operation is involved.  */
5729
5730 static void
5731 gen_int_fp_libfunc (optab optable, const char *name, char suffix,
5732                     enum machine_mode mode)
5733 {
5734   if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
5735     gen_fp_libfunc (optable, name, suffix, mode);
5736   if (INTEGRAL_MODE_P (mode))
5737     gen_int_libfunc (optable, name, suffix, mode);
5738 }
5739
5740 /* Like gen_libfunc, but verify that FP or INT operation is involved
5741    and add 'v' suffix for integer operation.  */
5742
5743 static void
5744 gen_intv_fp_libfunc (optab optable, const char *name, char suffix,
5745                      enum machine_mode mode)
5746 {
5747   if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
5748     gen_fp_libfunc (optable, name, suffix, mode);
5749   if (GET_MODE_CLASS (mode) == MODE_INT)
5750     {
5751       int len = strlen (name);
5752       char *v_name = alloca (len + 2);
5753       strcpy (v_name, name);
5754       v_name[len] = 'v';
5755       v_name[len + 1] = 0;
5756       gen_int_libfunc (optable, v_name, suffix, mode);
5757     }
5758 }
5759
5760 /* Like gen_libfunc, but verify that FP or INT or FIXED operation is
5761    involved.  */
5762
5763 static void
5764 gen_int_fp_fixed_libfunc (optab optable, const char *name, char suffix,
5765                           enum machine_mode mode)
5766 {
5767   if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
5768     gen_fp_libfunc (optable, name, suffix, mode);
5769   if (INTEGRAL_MODE_P (mode))
5770     gen_int_libfunc (optable, name, suffix, mode);
5771   if (ALL_FIXED_POINT_MODE_P (mode))
5772     gen_fixed_libfunc (optable, name, suffix, mode);
5773 }
5774
5775 /* Like gen_libfunc, but verify that FP or INT or signed FIXED operation is
5776    involved.  */
5777
5778 static void
5779 gen_int_fp_signed_fixed_libfunc (optab optable, const char *name, char suffix,
5780                                  enum machine_mode mode)
5781 {
5782   if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
5783     gen_fp_libfunc (optable, name, suffix, mode);
5784   if (INTEGRAL_MODE_P (mode))
5785     gen_int_libfunc (optable, name, suffix, mode);
5786   if (SIGNED_FIXED_POINT_MODE_P (mode))
5787     gen_signed_fixed_libfunc (optable, name, suffix, mode);
5788 }
5789
5790 /* Like gen_libfunc, but verify that INT or FIXED operation is
5791    involved.  */
5792
5793 static void
5794 gen_int_fixed_libfunc (optab optable, const char *name, char suffix,
5795                        enum machine_mode mode)
5796 {
5797   if (INTEGRAL_MODE_P (mode))
5798     gen_int_libfunc (optable, name, suffix, mode);
5799   if (ALL_FIXED_POINT_MODE_P (mode))
5800     gen_fixed_libfunc (optable, name, suffix, mode);
5801 }
5802
5803 /* Like gen_libfunc, but verify that INT or signed FIXED operation is
5804    involved.  */
5805
5806 static void
5807 gen_int_signed_fixed_libfunc (optab optable, const char *name, char suffix,
5808                               enum machine_mode mode)
5809 {
5810   if (INTEGRAL_MODE_P (mode))
5811     gen_int_libfunc (optable, name, suffix, mode);
5812   if (SIGNED_FIXED_POINT_MODE_P (mode))
5813     gen_signed_fixed_libfunc (optable, name, suffix, mode);
5814 }
5815
5816 /* Like gen_libfunc, but verify that INT or unsigned FIXED operation is
5817    involved.  */
5818
5819 static void
5820 gen_int_unsigned_fixed_libfunc (optab optable, const char *name, char suffix,
5821                                 enum machine_mode mode)
5822 {
5823   if (INTEGRAL_MODE_P (mode))
5824     gen_int_libfunc (optable, name, suffix, mode);
5825   if (UNSIGNED_FIXED_POINT_MODE_P (mode))
5826     gen_unsigned_fixed_libfunc (optable, name, suffix, mode);
5827 }
5828
5829 /* Initialize the libfunc fields of an entire group of entries of an
5830    inter-mode-class conversion optab.  The string formation rules are
5831    similar to the ones for init_libfuncs, above, but instead of having
5832    a mode name and an operand count these functions have two mode names
5833    and no operand count.  */
5834
5835 static void
5836 gen_interclass_conv_libfunc (convert_optab tab,
5837                              const char *opname,
5838                              enum machine_mode tmode,
5839                              enum machine_mode fmode)
5840 {
5841   size_t opname_len = strlen (opname);
5842   size_t mname_len = 0;
5843
5844   const char *fname, *tname;
5845   const char *q;
5846   char *libfunc_name, *suffix;
5847   char *nondec_name, *dec_name, *nondec_suffix, *dec_suffix;
5848   char *p;
5849
5850   /* If this is a decimal conversion, add the current BID vs. DPD prefix that
5851      depends on which underlying decimal floating point format is used.  */
5852   const size_t dec_len = sizeof (DECIMAL_PREFIX) - 1;
5853
5854   mname_len = strlen (GET_MODE_NAME (tmode)) + strlen (GET_MODE_NAME (fmode));
5855
5856   nondec_name = alloca (2 + opname_len + mname_len + 1 + 1);
5857   nondec_name[0] = '_';
5858   nondec_name[1] = '_';
5859   memcpy (&nondec_name[2], opname, opname_len);
5860   nondec_suffix = nondec_name + opname_len + 2;
5861
5862   dec_name = alloca (2 + dec_len + opname_len + mname_len + 1 + 1);
5863   dec_name[0] = '_';
5864   dec_name[1] = '_';
5865   memcpy (&dec_name[2], DECIMAL_PREFIX, dec_len);
5866   memcpy (&dec_name[2+dec_len], opname, opname_len);
5867   dec_suffix = dec_name + dec_len + opname_len + 2;
5868
5869   fname = GET_MODE_NAME (fmode);
5870   tname = GET_MODE_NAME (tmode);
5871
5872   if (DECIMAL_FLOAT_MODE_P(fmode) || DECIMAL_FLOAT_MODE_P(tmode))
5873     {
5874       libfunc_name = dec_name;
5875       suffix = dec_suffix;
5876     }
5877   else
5878     {
5879       libfunc_name = nondec_name;
5880       suffix = nondec_suffix;
5881     }
5882
5883   p = suffix;
5884   for (q = fname; *q; p++, q++)
5885     *p = TOLOWER (*q);
5886   for (q = tname; *q; p++, q++)
5887     *p = TOLOWER (*q);
5888
5889   *p = '\0';
5890
5891   set_conv_libfunc (tab, tmode, fmode,
5892                     ggc_alloc_string (libfunc_name, p - libfunc_name));
5893 }
5894
5895 /* Same as gen_interclass_conv_libfunc but verify that we are producing
5896    int->fp conversion.  */
5897
5898 static void
5899 gen_int_to_fp_conv_libfunc (convert_optab tab,
5900                             const char *opname,
5901                             enum machine_mode tmode,
5902                             enum machine_mode fmode)
5903 {
5904   if (GET_MODE_CLASS (fmode) != MODE_INT)
5905     return;
5906   if (GET_MODE_CLASS (tmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (tmode))
5907     return;
5908   gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
5909 }
5910
5911 /* ufloat_optab is special by using floatun for FP and floatuns decimal fp
5912    naming scheme.  */
5913
5914 static void
5915 gen_ufloat_conv_libfunc (convert_optab tab,
5916                          const char *opname ATTRIBUTE_UNUSED,
5917                          enum machine_mode tmode,
5918                          enum machine_mode fmode)
5919 {
5920   if (DECIMAL_FLOAT_MODE_P (tmode))
5921     gen_int_to_fp_conv_libfunc (tab, "floatuns", tmode, fmode);
5922   else
5923     gen_int_to_fp_conv_libfunc (tab, "floatun", tmode, fmode);
5924 }
5925
5926 /* Same as gen_interclass_conv_libfunc but verify that we are producing
5927    fp->int conversion.  */
5928
5929 static void
5930 gen_int_to_fp_nondecimal_conv_libfunc (convert_optab tab,
5931                                        const char *opname,
5932                                        enum machine_mode tmode,
5933                                        enum machine_mode fmode)
5934 {
5935   if (GET_MODE_CLASS (fmode) != MODE_INT)
5936     return;
5937   if (GET_MODE_CLASS (tmode) != MODE_FLOAT)
5938     return;
5939   gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
5940 }
5941
5942 /* Same as gen_interclass_conv_libfunc but verify that we are producing
5943    fp->int conversion with no decimal floating point involved.  */
5944
5945 static void
5946 gen_fp_to_int_conv_libfunc (convert_optab tab,
5947                             const char *opname,
5948                             enum machine_mode tmode,
5949                             enum machine_mode fmode)
5950 {
5951   if (GET_MODE_CLASS (fmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (fmode))
5952     return;
5953   if (GET_MODE_CLASS (tmode) != MODE_INT)
5954     return;
5955   gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
5956 }
5957
5958 /* Initialize the libfunc fiels of an of an intra-mode-class conversion optab.
5959    The string formation rules are
5960    similar to the ones for init_libfunc, above.  */
5961
5962 static void
5963 gen_intraclass_conv_libfunc (convert_optab tab, const char *opname,
5964                              enum machine_mode tmode, enum machine_mode fmode)
5965 {
5966   size_t opname_len = strlen (opname);
5967   size_t mname_len = 0;
5968
5969   const char *fname, *tname;
5970   const char *q;
5971   char *nondec_name, *dec_name, *nondec_suffix, *dec_suffix;
5972   char *libfunc_name, *suffix;
5973   char *p;
5974
5975   /* If this is a decimal conversion, add the current BID vs. DPD prefix that
5976      depends on which underlying decimal floating point format is used.  */
5977   const size_t dec_len = sizeof (DECIMAL_PREFIX) - 1;
5978
5979   mname_len = strlen (GET_MODE_NAME (tmode)) + strlen (GET_MODE_NAME (fmode));
5980
5981   nondec_name = alloca (2 + opname_len + mname_len + 1 + 1);
5982   nondec_name[0] = '_';
5983   nondec_name[1] = '_';
5984   memcpy (&nondec_name[2], opname, opname_len);
5985   nondec_suffix = nondec_name + opname_len + 2;
5986
5987   dec_name = alloca (2 + dec_len + opname_len + mname_len + 1 + 1);
5988   dec_name[0] = '_';
5989   dec_name[1] = '_';
5990   memcpy (&dec_name[2], DECIMAL_PREFIX, dec_len);
5991   memcpy (&dec_name[2 + dec_len], opname, opname_len);
5992   dec_suffix = dec_name + dec_len + opname_len + 2;
5993
5994   fname = GET_MODE_NAME (fmode);
5995   tname = GET_MODE_NAME (tmode);
5996
5997   if (DECIMAL_FLOAT_MODE_P(fmode) || DECIMAL_FLOAT_MODE_P(tmode))
5998     {
5999       libfunc_name = dec_name;
6000       suffix = dec_suffix;
6001     }
6002   else
6003     {
6004       libfunc_name = nondec_name;
6005       suffix = nondec_suffix;
6006     }
6007
6008   p = suffix;
6009   for (q = fname; *q; p++, q++)
6010     *p = TOLOWER (*q);
6011   for (q = tname; *q; p++, q++)
6012     *p = TOLOWER (*q);
6013
6014   *p++ = '2';
6015   *p = '\0';
6016
6017   set_conv_libfunc (tab, tmode, fmode,
6018                     ggc_alloc_string (libfunc_name, p - libfunc_name));
6019 }
6020
6021 /* Pick proper libcall for trunc_optab.  We need to chose if we do
6022    truncation or extension and interclass or intraclass.  */
6023
6024 static void
6025 gen_trunc_conv_libfunc (convert_optab tab,
6026                          const char *opname,
6027                          enum machine_mode tmode,
6028                          enum machine_mode fmode)
6029 {
6030   if (GET_MODE_CLASS (tmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (tmode))
6031     return;
6032   if (GET_MODE_CLASS (fmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (fmode))
6033     return;
6034   if (tmode == fmode)
6035     return;
6036
6037   if ((GET_MODE_CLASS (tmode) == MODE_FLOAT && DECIMAL_FLOAT_MODE_P (fmode))
6038       || (GET_MODE_CLASS (fmode) == MODE_FLOAT && DECIMAL_FLOAT_MODE_P (tmode)))
6039      gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
6040   
6041   if (GET_MODE_PRECISION (fmode) <= GET_MODE_PRECISION (tmode))
6042     return;
6043
6044   if ((GET_MODE_CLASS (tmode) == MODE_FLOAT
6045        && GET_MODE_CLASS (fmode) == MODE_FLOAT)
6046       || (DECIMAL_FLOAT_MODE_P (fmode) && DECIMAL_FLOAT_MODE_P (tmode)))
6047     gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
6048 }
6049
6050 /* Pick proper libcall for extend_optab.  We need to chose if we do
6051    truncation or extension and interclass or intraclass.  */
6052
6053 static void
6054 gen_extend_conv_libfunc (convert_optab tab,
6055                          const char *opname ATTRIBUTE_UNUSED,
6056                          enum machine_mode tmode,
6057                          enum machine_mode fmode)
6058 {
6059   if (GET_MODE_CLASS (tmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (tmode))
6060     return;
6061   if (GET_MODE_CLASS (fmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (fmode))
6062     return;
6063   if (tmode == fmode)
6064     return;
6065
6066   if ((GET_MODE_CLASS (tmode) == MODE_FLOAT && DECIMAL_FLOAT_MODE_P (fmode))
6067       || (GET_MODE_CLASS (fmode) == MODE_FLOAT && DECIMAL_FLOAT_MODE_P (tmode)))
6068      gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
6069   
6070   if (GET_MODE_PRECISION (fmode) > GET_MODE_PRECISION (tmode))
6071     return;
6072
6073   if ((GET_MODE_CLASS (tmode) == MODE_FLOAT
6074        && GET_MODE_CLASS (fmode) == MODE_FLOAT)
6075       || (DECIMAL_FLOAT_MODE_P (fmode) && DECIMAL_FLOAT_MODE_P (tmode)))
6076     gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
6077 }
6078
6079 /* Pick proper libcall for fract_optab.  We need to chose if we do
6080    interclass or intraclass.  */
6081
6082 static void
6083 gen_fract_conv_libfunc (convert_optab tab,
6084                         const char *opname,
6085                         enum machine_mode tmode,
6086                         enum machine_mode fmode)
6087 {
6088   if (tmode == fmode)
6089     return;
6090   if (!(ALL_FIXED_POINT_MODE_P (tmode) || ALL_FIXED_POINT_MODE_P (fmode)))
6091     return;
6092
6093   if (GET_MODE_CLASS (tmode) == GET_MODE_CLASS (fmode))
6094     gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
6095   else
6096     gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
6097 }
6098
6099 /* Pick proper libcall for fractuns_optab.  */
6100
6101 static void
6102 gen_fractuns_conv_libfunc (convert_optab tab,
6103                            const char *opname,
6104                            enum machine_mode tmode,
6105                            enum machine_mode fmode)
6106 {
6107   if (tmode == fmode)
6108     return;
6109   /* One mode must be a fixed-point mode, and the other must be an integer
6110      mode. */
6111   if (!((ALL_FIXED_POINT_MODE_P (tmode) && GET_MODE_CLASS (fmode) == MODE_INT)
6112         || (ALL_FIXED_POINT_MODE_P (fmode)
6113             && GET_MODE_CLASS (tmode) == MODE_INT)))
6114     return;
6115
6116   gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
6117 }
6118
6119 /* Pick proper libcall for satfract_optab.  We need to chose if we do
6120    interclass or intraclass.  */
6121
6122 static void
6123 gen_satfract_conv_libfunc (convert_optab tab,
6124                            const char *opname,
6125                            enum machine_mode tmode,
6126                            enum machine_mode fmode)
6127 {
6128   if (tmode == fmode)
6129     return;
6130   /* TMODE must be a fixed-point mode.  */
6131   if (!ALL_FIXED_POINT_MODE_P (tmode))
6132     return;
6133
6134   if (GET_MODE_CLASS (tmode) == GET_MODE_CLASS (fmode))
6135     gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
6136   else
6137     gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
6138 }
6139
6140 /* Pick proper libcall for satfractuns_optab.  */
6141
6142 static void
6143 gen_satfractuns_conv_libfunc (convert_optab tab,
6144                               const char *opname,
6145                               enum machine_mode tmode,
6146                               enum machine_mode fmode)
6147 {
6148   if (tmode == fmode)
6149     return;
6150   /* TMODE must be a fixed-point mode, and FMODE must be an integer mode. */
6151   if (!(ALL_FIXED_POINT_MODE_P (tmode) && GET_MODE_CLASS (fmode) == MODE_INT))
6152     return;
6153
6154   gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
6155 }
6156
6157 rtx
6158 init_one_libfunc (const char *name)
6159 {
6160   rtx symbol;
6161
6162   /* Create a FUNCTION_DECL that can be passed to
6163      targetm.encode_section_info.  */
6164   /* ??? We don't have any type information except for this is
6165      a function.  Pretend this is "int foo()".  */
6166   tree decl = build_decl (FUNCTION_DECL, get_identifier (name),
6167                           build_function_type (integer_type_node, NULL_TREE));
6168   DECL_ARTIFICIAL (decl) = 1;
6169   DECL_EXTERNAL (decl) = 1;
6170   TREE_PUBLIC (decl) = 1;
6171
6172   symbol = XEXP (DECL_RTL (decl), 0);
6173
6174   /* Zap the nonsensical SYMBOL_REF_DECL for this.  What we're left with
6175      are the flags assigned by targetm.encode_section_info.  */
6176   SET_SYMBOL_REF_DECL (symbol, 0);
6177
6178   return symbol;
6179 }
6180
6181 /* Call this to reset the function entry for one optab (OPTABLE) in mode
6182    MODE to NAME, which should be either 0 or a string constant.  */
6183 void
6184 set_optab_libfunc (optab optable, enum machine_mode mode, const char *name)
6185 {
6186   rtx val;
6187   struct libfunc_entry e;
6188   struct libfunc_entry **slot;
6189   e.optab = (size_t) (optab_table[0] - optable);
6190   e.mode1 = mode;
6191   e.mode2 = VOIDmode;
6192
6193   if (name)
6194     val = init_one_libfunc (name);
6195   else
6196     val = 0;
6197   slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, INSERT);
6198   if (*slot == NULL)
6199     *slot = ggc_alloc (sizeof (struct libfunc_entry));
6200   (*slot)->optab = (size_t) (optab_table[0] - optable);
6201   (*slot)->mode1 = mode;
6202   (*slot)->mode2 = VOIDmode;
6203   (*slot)->libfunc = val;
6204 }
6205
6206 /* Call this to reset the function entry for one conversion optab
6207    (OPTABLE) from mode FMODE to mode TMODE to NAME, which should be
6208    either 0 or a string constant.  */
6209 void
6210 set_conv_libfunc (convert_optab optable, enum machine_mode tmode,
6211                   enum machine_mode fmode, const char *name)
6212 {
6213   rtx val;
6214   struct libfunc_entry e;
6215   struct libfunc_entry **slot;
6216   e.optab = (size_t) (convert_optab_table[0] - optable);
6217   e.mode1 = tmode;
6218   e.mode2 = fmode;
6219
6220   if (name)
6221     val = init_one_libfunc (name);
6222   else
6223     val = 0;
6224   slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, INSERT);
6225   if (*slot == NULL)
6226     *slot = ggc_alloc (sizeof (struct libfunc_entry));
6227   (*slot)->optab = (size_t) (convert_optab_table[0] - optable);
6228   (*slot)->mode1 = tmode;
6229   (*slot)->mode2 = fmode;
6230   (*slot)->libfunc = val;
6231 }
6232
6233 /* Call this to initialize the contents of the optabs
6234    appropriately for the current target machine.  */
6235
6236 void
6237 init_optabs (void)
6238 {
6239   unsigned int i;
6240   enum machine_mode int_mode;
6241
6242   libfunc_hash = htab_create_ggc (10, hash_libfunc, eq_libfunc, NULL);
6243   /* Start by initializing all tables to contain CODE_FOR_nothing.  */
6244
6245   for (i = 0; i < NUM_RTX_CODE; i++)
6246     setcc_gen_code[i] = CODE_FOR_nothing;
6247
6248 #ifdef HAVE_conditional_move
6249   for (i = 0; i < NUM_MACHINE_MODES; i++)
6250     movcc_gen_code[i] = CODE_FOR_nothing;
6251 #endif
6252
6253   for (i = 0; i < NUM_MACHINE_MODES; i++)
6254     {
6255       vcond_gen_code[i] = CODE_FOR_nothing;
6256       vcondu_gen_code[i] = CODE_FOR_nothing;
6257     }
6258
6259   add_optab = init_optab (PLUS);
6260   addv_optab = init_optabv (PLUS);
6261   sub_optab = init_optab (MINUS);
6262   subv_optab = init_optabv (MINUS);
6263   ssadd_optab = init_optab (SS_PLUS);
6264   usadd_optab = init_optab (US_PLUS);
6265   sssub_optab = init_optab (SS_MINUS);
6266   ussub_optab = init_optab (US_MINUS);
6267   smul_optab = init_optab (MULT);
6268   ssmul_optab = init_optab (SS_MULT);
6269   usmul_optab = init_optab (US_MULT);
6270   smulv_optab = init_optabv (MULT);
6271   smul_highpart_optab = init_optab (UNKNOWN);
6272   umul_highpart_optab = init_optab (UNKNOWN);
6273   smul_widen_optab = init_optab (UNKNOWN);
6274   umul_widen_optab = init_optab (UNKNOWN);
6275   usmul_widen_optab = init_optab (UNKNOWN);
6276   smadd_widen_optab = init_optab (UNKNOWN);
6277   umadd_widen_optab = init_optab (UNKNOWN);
6278   ssmadd_widen_optab = init_optab (UNKNOWN);
6279   usmadd_widen_optab = init_optab (UNKNOWN);
6280   smsub_widen_optab = init_optab (UNKNOWN);
6281   umsub_widen_optab = init_optab (UNKNOWN);
6282   ssmsub_widen_optab = init_optab (UNKNOWN);
6283   usmsub_widen_optab = init_optab (UNKNOWN);
6284   sdiv_optab = init_optab (DIV);
6285   ssdiv_optab = init_optab (SS_DIV);
6286   usdiv_optab = init_optab (US_DIV);
6287   sdivv_optab = init_optabv (DIV);
6288   sdivmod_optab = init_optab (UNKNOWN);
6289   udiv_optab = init_optab (UDIV);
6290   udivmod_optab = init_optab (UNKNOWN);
6291   smod_optab = init_optab (MOD);
6292   umod_optab = init_optab (UMOD);
6293   fmod_optab = init_optab (UNKNOWN);
6294   remainder_optab = init_optab (UNKNOWN);
6295   ftrunc_optab = init_optab (UNKNOWN);
6296   and_optab = init_optab (AND);
6297   ior_optab = init_optab (IOR);
6298   xor_optab = init_optab (XOR);
6299   ashl_optab = init_optab (ASHIFT);
6300   ssashl_optab = init_optab (SS_ASHIFT);
6301   usashl_optab = init_optab (US_ASHIFT);
6302   ashr_optab = init_optab (ASHIFTRT);
6303   lshr_optab = init_optab (LSHIFTRT);
6304   rotl_optab = init_optab (ROTATE);
6305   rotr_optab = init_optab (ROTATERT);
6306   smin_optab = init_optab (SMIN);
6307   smax_optab = init_optab (SMAX);
6308   umin_optab = init_optab (UMIN);
6309   umax_optab = init_optab (UMAX);
6310   pow_optab = init_optab (UNKNOWN);
6311   atan2_optab = init_optab (UNKNOWN);
6312
6313   /* These three have codes assigned exclusively for the sake of
6314      have_insn_for.  */
6315   mov_optab = init_optab (SET);
6316   movstrict_optab = init_optab (STRICT_LOW_PART);
6317   cmp_optab = init_optab (COMPARE);
6318
6319   storent_optab = init_optab (UNKNOWN);
6320
6321   ucmp_optab = init_optab (UNKNOWN);
6322   tst_optab = init_optab (UNKNOWN);
6323
6324   eq_optab = init_optab (EQ);
6325   ne_optab = init_optab (NE);
6326   gt_optab = init_optab (GT);
6327   ge_optab = init_optab (GE);
6328   lt_optab = init_optab (LT);
6329   le_optab = init_optab (LE);
6330   unord_optab = init_optab (UNORDERED);
6331
6332   neg_optab = init_optab (NEG);
6333   ssneg_optab = init_optab (SS_NEG);
6334   usneg_optab = init_optab (US_NEG);
6335   negv_optab = init_optabv (NEG);
6336   abs_optab = init_optab (ABS);
6337   absv_optab = init_optabv (ABS);
6338   addcc_optab = init_optab (UNKNOWN);
6339   one_cmpl_optab = init_optab (NOT);
6340   bswap_optab = init_optab (BSWAP);
6341   ffs_optab = init_optab (FFS);
6342   clz_optab = init_optab (CLZ);
6343   ctz_optab = init_optab (CTZ);
6344   popcount_optab = init_optab (POPCOUNT);
6345   parity_optab = init_optab (PARITY);
6346   sqrt_optab = init_optab (SQRT);
6347   floor_optab = init_optab (UNKNOWN);
6348   ceil_optab = init_optab (UNKNOWN);
6349   round_optab = init_optab (UNKNOWN);
6350   btrunc_optab = init_optab (UNKNOWN);
6351   nearbyint_optab = init_optab (UNKNOWN);
6352   rint_optab = init_optab (UNKNOWN);
6353   sincos_optab = init_optab (UNKNOWN);
6354   sin_optab = init_optab (UNKNOWN);
6355   asin_optab = init_optab (UNKNOWN);
6356   cos_optab = init_optab (UNKNOWN);
6357   acos_optab = init_optab (UNKNOWN);
6358   exp_optab = init_optab (UNKNOWN);
6359   exp10_optab = init_optab (UNKNOWN);
6360   exp2_optab = init_optab (UNKNOWN);
6361   expm1_optab = init_optab (UNKNOWN);
6362   ldexp_optab = init_optab (UNKNOWN);
6363   scalb_optab = init_optab (UNKNOWN);
6364   logb_optab = init_optab (UNKNOWN);
6365   ilogb_optab = init_optab (UNKNOWN);
6366   log_optab = init_optab (UNKNOWN);
6367   log10_optab = init_optab (UNKNOWN);
6368   log2_optab = init_optab (UNKNOWN);
6369   log1p_optab = init_optab (UNKNOWN);
6370   tan_optab = init_optab (UNKNOWN);
6371   atan_optab = init_optab (UNKNOWN);
6372   copysign_optab = init_optab (UNKNOWN);
6373   signbit_optab = init_optab (UNKNOWN);
6374
6375   isinf_optab = init_optab (UNKNOWN);
6376
6377   strlen_optab = init_optab (UNKNOWN);
6378   cbranch_optab = init_optab (UNKNOWN);
6379   cmov_optab = init_optab (UNKNOWN);
6380   cstore_optab = init_optab (UNKNOWN);
6381   push_optab = init_optab (UNKNOWN);
6382
6383   reduc_smax_optab = init_optab (UNKNOWN);
6384   reduc_umax_optab = init_optab (UNKNOWN);
6385   reduc_smin_optab = init_optab (UNKNOWN);
6386   reduc_umin_optab = init_optab (UNKNOWN);
6387   reduc_splus_optab = init_optab (UNKNOWN);
6388   reduc_uplus_optab = init_optab (UNKNOWN);
6389
6390   ssum_widen_optab = init_optab (UNKNOWN);
6391   usum_widen_optab = init_optab (UNKNOWN);
6392   sdot_prod_optab = init_optab (UNKNOWN); 
6393   udot_prod_optab = init_optab (UNKNOWN);
6394
6395   vec_extract_optab = init_optab (UNKNOWN);
6396   vec_extract_even_optab = init_optab (UNKNOWN);
6397   vec_extract_odd_optab = init_optab (UNKNOWN);
6398   vec_interleave_high_optab = init_optab (UNKNOWN);
6399   vec_interleave_low_optab = init_optab (UNKNOWN);
6400   vec_set_optab = init_optab (UNKNOWN);
6401   vec_init_optab = init_optab (UNKNOWN);
6402   vec_shl_optab = init_optab (UNKNOWN);
6403   vec_shr_optab = init_optab (UNKNOWN);
6404   vec_realign_load_optab = init_optab (UNKNOWN);
6405   movmisalign_optab = init_optab (UNKNOWN);
6406   vec_widen_umult_hi_optab = init_optab (UNKNOWN);
6407   vec_widen_umult_lo_optab = init_optab (UNKNOWN);
6408   vec_widen_smult_hi_optab = init_optab (UNKNOWN);
6409   vec_widen_smult_lo_optab = init_optab (UNKNOWN);
6410   vec_unpacks_hi_optab = init_optab (UNKNOWN);
6411   vec_unpacks_lo_optab = init_optab (UNKNOWN);
6412   vec_unpacku_hi_optab = init_optab (UNKNOWN);
6413   vec_unpacku_lo_optab = init_optab (UNKNOWN);
6414   vec_unpacks_float_hi_optab = init_optab (UNKNOWN);
6415   vec_unpacks_float_lo_optab = init_optab (UNKNOWN);
6416   vec_unpacku_float_hi_optab = init_optab (UNKNOWN);
6417   vec_unpacku_float_lo_optab = init_optab (UNKNOWN);
6418   vec_pack_trunc_optab = init_optab (UNKNOWN);
6419   vec_pack_usat_optab = init_optab (UNKNOWN);
6420   vec_pack_ssat_optab = init_optab (UNKNOWN);
6421   vec_pack_ufix_trunc_optab = init_optab (UNKNOWN);
6422   vec_pack_sfix_trunc_optab = init_optab (UNKNOWN);
6423
6424   powi_optab = init_optab (UNKNOWN);
6425
6426   /* Conversions.  */
6427   sext_optab = init_convert_optab (SIGN_EXTEND);
6428   zext_optab = init_convert_optab (ZERO_EXTEND);
6429   trunc_optab = init_convert_optab (TRUNCATE);
6430   sfix_optab = init_convert_optab (FIX);
6431   ufix_optab = init_convert_optab (UNSIGNED_FIX);
6432   sfixtrunc_optab = init_convert_optab (UNKNOWN);
6433   ufixtrunc_optab = init_convert_optab (UNKNOWN);
6434   sfloat_optab = init_convert_optab (FLOAT);
6435   ufloat_optab = init_convert_optab (UNSIGNED_FLOAT);
6436   lrint_optab = init_convert_optab (UNKNOWN);
6437   lround_optab = init_convert_optab (UNKNOWN);
6438   lfloor_optab = init_convert_optab (UNKNOWN);
6439   lceil_optab = init_convert_optab (UNKNOWN);
6440
6441   fract_optab = init_convert_optab (FRACT_CONVERT);
6442   fractuns_optab = init_convert_optab (UNSIGNED_FRACT_CONVERT);
6443   satfract_optab = init_convert_optab (SAT_FRACT);
6444   satfractuns_optab = init_convert_optab (UNSIGNED_SAT_FRACT);
6445
6446   for (i = 0; i < NUM_MACHINE_MODES; i++)
6447     {
6448       movmem_optab[i] = CODE_FOR_nothing;
6449       cmpstr_optab[i] = CODE_FOR_nothing;
6450       cmpstrn_optab[i] = CODE_FOR_nothing;
6451       cmpmem_optab[i] = CODE_FOR_nothing;
6452       setmem_optab[i] = CODE_FOR_nothing;
6453
6454       sync_add_optab[i] = CODE_FOR_nothing;
6455       sync_sub_optab[i] = CODE_FOR_nothing;
6456       sync_ior_optab[i] = CODE_FOR_nothing;
6457       sync_and_optab[i] = CODE_FOR_nothing;
6458       sync_xor_optab[i] = CODE_FOR_nothing;
6459       sync_nand_optab[i] = CODE_FOR_nothing;
6460       sync_old_add_optab[i] = CODE_FOR_nothing;
6461       sync_old_sub_optab[i] = CODE_FOR_nothing;
6462       sync_old_ior_optab[i] = CODE_FOR_nothing;
6463       sync_old_and_optab[i] = CODE_FOR_nothing;
6464       sync_old_xor_optab[i] = CODE_FOR_nothing;
6465       sync_old_nand_optab[i] = CODE_FOR_nothing;
6466       sync_new_add_optab[i] = CODE_FOR_nothing;
6467       sync_new_sub_optab[i] = CODE_FOR_nothing;
6468       sync_new_ior_optab[i] = CODE_FOR_nothing;
6469       sync_new_and_optab[i] = CODE_FOR_nothing;
6470       sync_new_xor_optab[i] = CODE_FOR_nothing;
6471       sync_new_nand_optab[i] = CODE_FOR_nothing;
6472       sync_compare_and_swap[i] = CODE_FOR_nothing;
6473       sync_compare_and_swap_cc[i] = CODE_FOR_nothing;
6474       sync_lock_test_and_set[i] = CODE_FOR_nothing;
6475       sync_lock_release[i] = CODE_FOR_nothing;
6476
6477       reload_in_optab[i] = reload_out_optab[i] = CODE_FOR_nothing;
6478     }
6479
6480   /* Fill in the optabs with the insns we support.  */
6481   init_all_optabs ();
6482
6483   /* Initialize the optabs with the names of the library functions.  */
6484   add_optab->libcall_basename = "add";
6485   add_optab->libcall_suffix = '3';
6486   add_optab->libcall_gen = gen_int_fp_fixed_libfunc;
6487   addv_optab->libcall_basename = "add";
6488   addv_optab->libcall_suffix = '3';
6489   addv_optab->libcall_gen = gen_intv_fp_libfunc;
6490   ssadd_optab->libcall_basename = "ssadd";
6491   ssadd_optab->libcall_suffix = '3';
6492   ssadd_optab->libcall_gen = gen_signed_fixed_libfunc;
6493   usadd_optab->libcall_basename = "usadd";
6494   usadd_optab->libcall_suffix = '3';
6495   usadd_optab->libcall_gen = gen_unsigned_fixed_libfunc;
6496   sub_optab->libcall_basename = "sub";
6497   sub_optab->libcall_suffix = '3';
6498   sub_optab->libcall_gen = gen_int_fp_fixed_libfunc;
6499   subv_optab->libcall_basename = "sub";
6500   subv_optab->libcall_suffix = '3';
6501   subv_optab->libcall_gen = gen_intv_fp_libfunc;
6502   sssub_optab->libcall_basename = "sssub";
6503   sssub_optab->libcall_suffix = '3';
6504   sssub_optab->libcall_gen = gen_signed_fixed_libfunc;
6505   ussub_optab->libcall_basename = "ussub";
6506   ussub_optab->libcall_suffix = '3';
6507   ussub_optab->libcall_gen = gen_unsigned_fixed_libfunc;
6508   smul_optab->libcall_basename = "mul";
6509   smul_optab->libcall_suffix = '3';
6510   smul_optab->libcall_gen = gen_int_fp_fixed_libfunc;
6511   smulv_optab->libcall_basename = "mul";
6512   smulv_optab->libcall_suffix = '3';
6513   smulv_optab->libcall_gen = gen_intv_fp_libfunc;
6514   ssmul_optab->libcall_basename = "ssmul";
6515   ssmul_optab->libcall_suffix = '3';
6516   ssmul_optab->libcall_gen = gen_signed_fixed_libfunc;
6517   usmul_optab->libcall_basename = "usmul";
6518   usmul_optab->libcall_suffix = '3';
6519   usmul_optab->libcall_gen = gen_unsigned_fixed_libfunc;
6520   sdiv_optab->libcall_basename = "div";
6521   sdiv_optab->libcall_suffix = '3';
6522   sdiv_optab->libcall_gen = gen_int_fp_signed_fixed_libfunc;
6523   sdivv_optab->libcall_basename = "divv";
6524   sdivv_optab->libcall_suffix = '3';
6525   sdivv_optab->libcall_gen = gen_int_libfunc;
6526   ssdiv_optab->libcall_basename = "ssdiv";
6527   ssdiv_optab->libcall_suffix = '3';
6528   ssdiv_optab->libcall_gen = gen_signed_fixed_libfunc;
6529   udiv_optab->libcall_basename = "udiv";
6530   udiv_optab->libcall_suffix = '3';
6531   udiv_optab->libcall_gen = gen_int_unsigned_fixed_libfunc;
6532   usdiv_optab->libcall_basename = "usdiv";
6533   usdiv_optab->libcall_suffix = '3';
6534   usdiv_optab->libcall_gen = gen_unsigned_fixed_libfunc;
6535   sdivmod_optab->libcall_basename = "divmod";
6536   sdivmod_optab->libcall_suffix = '4';
6537   sdivmod_optab->libcall_gen = gen_int_libfunc;
6538   udivmod_optab->libcall_basename = "udivmod";
6539   udivmod_optab->libcall_suffix = '4';
6540   udivmod_optab->libcall_gen = gen_int_libfunc;
6541   smod_optab->libcall_basename = "mod";
6542   smod_optab->libcall_suffix = '3';
6543   smod_optab->libcall_gen = gen_int_libfunc;
6544   umod_optab->libcall_basename = "umod";
6545   umod_optab->libcall_suffix = '3';
6546   umod_optab->libcall_gen = gen_int_libfunc;
6547   ftrunc_optab->libcall_basename = "ftrunc";
6548   ftrunc_optab->libcall_suffix = '2';
6549   ftrunc_optab->libcall_gen = gen_fp_libfunc;
6550   and_optab->libcall_basename = "and";
6551   and_optab->libcall_suffix = '3';
6552   and_optab->libcall_gen = gen_int_libfunc;
6553   ior_optab->libcall_basename = "ior";
6554   ior_optab->libcall_suffix = '3';
6555   ior_optab->libcall_gen = gen_int_libfunc;
6556   xor_optab->libcall_basename = "xor";
6557   xor_optab->libcall_suffix = '3';
6558   xor_optab->libcall_gen = gen_int_libfunc;
6559   ashl_optab->libcall_basename = "ashl";
6560   ashl_optab->libcall_suffix = '3';
6561   ashl_optab->libcall_gen = gen_int_fixed_libfunc;
6562   ssashl_optab->libcall_basename = "ssashl";
6563   ssashl_optab->libcall_suffix = '3';
6564   ssashl_optab->libcall_gen = gen_signed_fixed_libfunc;
6565   usashl_optab->libcall_basename = "usashl";
6566   usashl_optab->libcall_suffix = '3';
6567   usashl_optab->libcall_gen = gen_unsigned_fixed_libfunc;
6568   ashr_optab->libcall_basename = "ashr";
6569   ashr_optab->libcall_suffix = '3';
6570   ashr_optab->libcall_gen = gen_int_signed_fixed_libfunc;
6571   lshr_optab->libcall_basename = "lshr";
6572   lshr_optab->libcall_suffix = '3';
6573   lshr_optab->libcall_gen = gen_int_unsigned_fixed_libfunc;
6574   smin_optab->libcall_basename = "min";
6575   smin_optab->libcall_suffix = '3';
6576   smin_optab->libcall_gen = gen_int_fp_libfunc;
6577   smax_optab->libcall_basename = "max";
6578   smax_optab->libcall_suffix = '3';
6579   smax_optab->libcall_gen = gen_int_fp_libfunc;
6580   umin_optab->libcall_basename = "umin";
6581   umin_optab->libcall_suffix = '3';
6582   umin_optab->libcall_gen = gen_int_libfunc;
6583   umax_optab->libcall_basename = "umax";
6584   umax_optab->libcall_suffix = '3';
6585   umax_optab->libcall_gen = gen_int_libfunc;
6586   neg_optab->libcall_basename = "neg";
6587   neg_optab->libcall_suffix = '2';
6588   neg_optab->libcall_gen = gen_int_fp_fixed_libfunc;
6589   ssneg_optab->libcall_basename = "ssneg";
6590   ssneg_optab->libcall_suffix = '2';
6591   ssneg_optab->libcall_gen = gen_signed_fixed_libfunc;
6592   usneg_optab->libcall_basename = "usneg";
6593   usneg_optab->libcall_suffix = '2';
6594   usneg_optab->libcall_gen = gen_unsigned_fixed_libfunc;
6595   negv_optab->libcall_basename = "neg";
6596   negv_optab->libcall_suffix = '2';
6597   negv_optab->libcall_gen = gen_intv_fp_libfunc;
6598   one_cmpl_optab->libcall_basename = "one_cmpl";
6599   one_cmpl_optab->libcall_suffix = '2';
6600   one_cmpl_optab->libcall_gen = gen_int_libfunc;
6601   ffs_optab->libcall_basename = "ffs";
6602   ffs_optab->libcall_suffix = '2';
6603   ffs_optab->libcall_gen = gen_int_libfunc;
6604   clz_optab->libcall_basename = "clz";
6605   clz_optab->libcall_suffix = '2';
6606   clz_optab->libcall_gen = gen_int_libfunc;
6607   ctz_optab->libcall_basename = "ctz";
6608   ctz_optab->libcall_suffix = '2';
6609   ctz_optab->libcall_gen = gen_int_libfunc;
6610   popcount_optab->libcall_basename = "popcount";
6611   popcount_optab->libcall_suffix = '2';
6612   popcount_optab->libcall_gen = gen_int_libfunc;
6613   parity_optab->libcall_basename = "parity";
6614   parity_optab->libcall_suffix = '2';
6615   parity_optab->libcall_gen = gen_int_libfunc;
6616
6617   /* Comparison libcalls for integers MUST come in pairs,
6618      signed/unsigned.  */
6619   cmp_optab->libcall_basename = "cmp";
6620   cmp_optab->libcall_suffix = '2';
6621   cmp_optab->libcall_gen = gen_int_fp_fixed_libfunc;
6622   ucmp_optab->libcall_basename = "ucmp";
6623   ucmp_optab->libcall_suffix = '2';
6624   ucmp_optab->libcall_gen = gen_int_libfunc;
6625
6626   /* EQ etc are floating point only.  */
6627   eq_optab->libcall_basename = "eq";
6628   eq_optab->libcall_suffix = '2';
6629   eq_optab->libcall_gen = gen_fp_libfunc;
6630   ne_optab->libcall_basename = "ne";
6631   ne_optab->libcall_suffix = '2';
6632   ne_optab->libcall_gen = gen_fp_libfunc;
6633   gt_optab->libcall_basename = "gt";
6634   gt_optab->libcall_suffix = '2';
6635   gt_optab->libcall_gen = gen_fp_libfunc;
6636   ge_optab->libcall_basename = "ge";
6637   ge_optab->libcall_suffix = '2';
6638   ge_optab->libcall_gen = gen_fp_libfunc;
6639   lt_optab->libcall_basename = "lt";
6640   lt_optab->libcall_suffix = '2';
6641   lt_optab->libcall_gen = gen_fp_libfunc;
6642   le_optab->libcall_basename = "le";
6643   le_optab->libcall_suffix = '2';
6644   le_optab->libcall_gen = gen_fp_libfunc;
6645   unord_optab->libcall_basename = "unord";
6646   unord_optab->libcall_suffix = '2';
6647   unord_optab->libcall_gen = gen_fp_libfunc;
6648
6649   powi_optab->libcall_basename = "powi";
6650   powi_optab->libcall_suffix = '2';
6651   powi_optab->libcall_gen = gen_fp_libfunc;
6652
6653   /* Conversions.  */
6654   sfloat_optab->libcall_basename = "float";
6655   sfloat_optab->libcall_gen = gen_int_to_fp_conv_libfunc;
6656   ufloat_optab->libcall_gen = gen_ufloat_conv_libfunc;
6657   sfix_optab->libcall_basename = "fix";
6658   sfix_optab->libcall_gen = gen_fp_to_int_conv_libfunc;
6659   ufix_optab->libcall_basename = "fixuns";
6660   ufix_optab->libcall_gen = gen_fp_to_int_conv_libfunc;
6661   lrint_optab->libcall_basename = "lrint";
6662   lrint_optab->libcall_gen = gen_int_to_fp_nondecimal_conv_libfunc;
6663   lround_optab->libcall_basename = "lround";
6664   lround_optab->libcall_gen = gen_int_to_fp_nondecimal_conv_libfunc;
6665   lfloor_optab->libcall_basename = "lfloor";
6666   lfloor_optab->libcall_gen = gen_int_to_fp_nondecimal_conv_libfunc;
6667   lceil_optab->libcall_basename = "lceil";
6668   lceil_optab->libcall_gen = gen_int_to_fp_nondecimal_conv_libfunc;
6669
6670   /* trunc_optab is also used for FLOAT_EXTEND.  */
6671   sext_optab->libcall_basename = "extend";
6672   sext_optab->libcall_gen = gen_extend_conv_libfunc;
6673   trunc_optab->libcall_basename = "trunc";
6674   trunc_optab->libcall_gen = gen_trunc_conv_libfunc;
6675
6676   /* Conversions for fixed-point modes and other modes.  */
6677   fract_optab->libcall_basename = "fract";
6678   fract_optab->libcall_gen = gen_fract_conv_libfunc;
6679   satfract_optab->libcall_basename = "satfract";
6680   satfract_optab->libcall_gen = gen_satfract_conv_libfunc;
6681   fractuns_optab->libcall_basename = "fractuns";
6682   fractuns_optab->libcall_gen = gen_fractuns_conv_libfunc;
6683   satfractuns_optab->libcall_basename = "satfractuns";
6684   satfractuns_optab->libcall_gen = gen_satfractuns_conv_libfunc;
6685
6686   /* The ffs function operates on `int'.  Fall back on it if we do not
6687      have a libgcc2 function for that width.  */
6688   if (INT_TYPE_SIZE < BITS_PER_WORD)
6689     {
6690       int_mode = mode_for_size (INT_TYPE_SIZE, MODE_INT, 0);
6691       set_optab_libfunc (ffs_optab, mode_for_size (INT_TYPE_SIZE, MODE_INT, 0),
6692                          "ffs");
6693     }
6694
6695   /* Explicitly initialize the bswap libfuncs since we need them to be
6696      valid for things other than word_mode.  */
6697   set_optab_libfunc (bswap_optab, SImode, "__bswapsi2");
6698   set_optab_libfunc (bswap_optab, DImode, "__bswapdi2");
6699
6700   /* Use cabs for double complex abs, since systems generally have cabs.
6701      Don't define any libcall for float complex, so that cabs will be used.  */
6702   if (complex_double_type_node)
6703     set_optab_libfunc (abs_optab, TYPE_MODE (complex_double_type_node), "cabs");
6704
6705   abort_libfunc = init_one_libfunc ("abort");
6706   memcpy_libfunc = init_one_libfunc ("memcpy");
6707   memmove_libfunc = init_one_libfunc ("memmove");
6708   memcmp_libfunc = init_one_libfunc ("memcmp");
6709   memset_libfunc = init_one_libfunc ("memset");
6710   setbits_libfunc = init_one_libfunc ("__setbits");
6711
6712 #ifndef DONT_USE_BUILTIN_SETJMP
6713   setjmp_libfunc = init_one_libfunc ("__builtin_setjmp");
6714   longjmp_libfunc = init_one_libfunc ("__builtin_longjmp");
6715 #else
6716   setjmp_libfunc = init_one_libfunc ("setjmp");
6717   longjmp_libfunc = init_one_libfunc ("longjmp");
6718 #endif
6719   unwind_sjlj_register_libfunc = init_one_libfunc ("_Unwind_SjLj_Register");
6720   unwind_sjlj_unregister_libfunc
6721     = init_one_libfunc ("_Unwind_SjLj_Unregister");
6722
6723   /* For function entry/exit instrumentation.  */
6724   profile_function_entry_libfunc
6725     = init_one_libfunc ("__cyg_profile_func_enter");
6726   profile_function_exit_libfunc
6727     = init_one_libfunc ("__cyg_profile_func_exit");
6728
6729   gcov_flush_libfunc = init_one_libfunc ("__gcov_flush");
6730
6731   if (HAVE_conditional_trap)
6732     trap_rtx = gen_rtx_fmt_ee (EQ, VOIDmode, NULL_RTX, NULL_RTX);
6733
6734   /* Allow the target to add more libcalls or rename some, etc.  */
6735   targetm.init_libfuncs ();
6736 }
6737
6738 /* Print information about the current contents of the optabs on
6739    STDERR.  */
6740
6741 void
6742 debug_optab_libfuncs (void)
6743 {
6744   int i;
6745   int j;
6746   int k;
6747
6748   /* Dump the arithmetic optabs.  */
6749   for (i = 0; i != (int) OTI_MAX; i++)
6750     for (j = 0; j < NUM_MACHINE_MODES; ++j)
6751       {
6752         optab o;
6753         rtx l;
6754
6755         o = optab_table[i];
6756         l = optab_libfunc (optab_table[i], j);
6757         if (l)
6758           {
6759             gcc_assert (GET_CODE (l) == SYMBOL_REF);
6760             fprintf (stderr, "%s\t%s:\t%s\n",
6761                      GET_RTX_NAME (o->code),
6762                      GET_MODE_NAME (j),
6763                      XSTR (l, 0));
6764           }
6765       }
6766
6767   /* Dump the conversion optabs.  */
6768   for (i = 0; i < (int) COI_MAX; ++i)
6769     for (j = 0; j < NUM_MACHINE_MODES; ++j)
6770       for (k = 0; k < NUM_MACHINE_MODES; ++k)
6771         {
6772           convert_optab o;
6773           rtx l;
6774
6775           o = convert_optab_table[i];
6776           l = convert_optab_libfunc (o, j, k);
6777           if (l)
6778             {
6779               gcc_assert (GET_CODE (l) == SYMBOL_REF);
6780               fprintf (stderr, "%s\t%s\t%s:\t%s\n",
6781                        GET_RTX_NAME (o->code),
6782                        GET_MODE_NAME (j),
6783                        GET_MODE_NAME (k),
6784                        XSTR (l, 0));
6785             }
6786         }
6787 }
6788
6789 \f
6790 /* Generate insns to trap with code TCODE if OP1 and OP2 satisfy condition
6791    CODE.  Return 0 on failure.  */
6792
6793 rtx
6794 gen_cond_trap (enum rtx_code code ATTRIBUTE_UNUSED, rtx op1,
6795                rtx op2 ATTRIBUTE_UNUSED, rtx tcode ATTRIBUTE_UNUSED)
6796 {
6797   enum machine_mode mode = GET_MODE (op1);
6798   enum insn_code icode;
6799   rtx insn;
6800
6801   if (!HAVE_conditional_trap)
6802     return 0;
6803
6804   if (mode == VOIDmode)
6805     return 0;
6806
6807   icode = optab_handler (cmp_optab, mode)->insn_code;
6808   if (icode == CODE_FOR_nothing)
6809     return 0;
6810
6811   start_sequence ();
6812   op1 = prepare_operand (icode, op1, 0, mode, mode, 0);
6813   op2 = prepare_operand (icode, op2, 1, mode, mode, 0);
6814   if (!op1 || !op2)
6815     {
6816       end_sequence ();
6817       return 0;
6818     }
6819   emit_insn (GEN_FCN (icode) (op1, op2));
6820
6821   PUT_CODE (trap_rtx, code);
6822   gcc_assert (HAVE_conditional_trap);
6823   insn = gen_conditional_trap (trap_rtx, tcode);
6824   if (insn)
6825     {
6826       emit_insn (insn);
6827       insn = get_insns ();
6828     }
6829   end_sequence ();
6830
6831   return insn;
6832 }
6833
6834 /* Return rtx code for TCODE. Use UNSIGNEDP to select signed
6835    or unsigned operation code.  */
6836
6837 static enum rtx_code
6838 get_rtx_code (enum tree_code tcode, bool unsignedp)
6839 {
6840   enum rtx_code code;
6841   switch (tcode)
6842     {
6843     case EQ_EXPR:
6844       code = EQ;
6845       break;
6846     case NE_EXPR:
6847       code = NE;
6848       break;
6849     case LT_EXPR:
6850       code = unsignedp ? LTU : LT;
6851       break;
6852     case LE_EXPR:
6853       code = unsignedp ? LEU : LE;
6854       break;
6855     case GT_EXPR:
6856       code = unsignedp ? GTU : GT;
6857       break;
6858     case GE_EXPR:
6859       code = unsignedp ? GEU : GE;
6860       break;
6861
6862     case UNORDERED_EXPR:
6863       code = UNORDERED;
6864       break;
6865     case ORDERED_EXPR:
6866       code = ORDERED;
6867       break;
6868     case UNLT_EXPR:
6869       code = UNLT;
6870       break;
6871     case UNLE_EXPR:
6872       code = UNLE;
6873       break;
6874     case UNGT_EXPR:
6875       code = UNGT;
6876       break;
6877     case UNGE_EXPR:
6878       code = UNGE;
6879       break;
6880     case UNEQ_EXPR:
6881       code = UNEQ;
6882       break;
6883     case LTGT_EXPR:
6884       code = LTGT;
6885       break;
6886
6887     default:
6888       gcc_unreachable ();
6889     }
6890   return code;
6891 }
6892
6893 /* Return comparison rtx for COND. Use UNSIGNEDP to select signed or
6894    unsigned operators. Do not generate compare instruction.  */
6895
6896 static rtx
6897 vector_compare_rtx (tree cond, bool unsignedp, enum insn_code icode)
6898 {
6899   enum rtx_code rcode;
6900   tree t_op0, t_op1;
6901   rtx rtx_op0, rtx_op1;
6902
6903   /* This is unlikely. While generating VEC_COND_EXPR, auto vectorizer
6904      ensures that condition is a relational operation.  */
6905   gcc_assert (COMPARISON_CLASS_P (cond));
6906
6907   rcode = get_rtx_code (TREE_CODE (cond), unsignedp);
6908   t_op0 = TREE_OPERAND (cond, 0);
6909   t_op1 = TREE_OPERAND (cond, 1);
6910
6911   /* Expand operands.  */
6912   rtx_op0 = expand_expr (t_op0, NULL_RTX, TYPE_MODE (TREE_TYPE (t_op0)),
6913                          EXPAND_STACK_PARM);
6914   rtx_op1 = expand_expr (t_op1, NULL_RTX, TYPE_MODE (TREE_TYPE (t_op1)),
6915                          EXPAND_STACK_PARM);
6916
6917   if (!insn_data[icode].operand[4].predicate (rtx_op0, GET_MODE (rtx_op0))
6918       && GET_MODE (rtx_op0) != VOIDmode)
6919     rtx_op0 = force_reg (GET_MODE (rtx_op0), rtx_op0);
6920
6921   if (!insn_data[icode].operand[5].predicate (rtx_op1, GET_MODE (rtx_op1))
6922       && GET_MODE (rtx_op1) != VOIDmode)
6923     rtx_op1 = force_reg (GET_MODE (rtx_op1), rtx_op1);
6924
6925   return gen_rtx_fmt_ee (rcode, VOIDmode, rtx_op0, rtx_op1);
6926 }
6927
6928 /* Return insn code for VEC_COND_EXPR EXPR.  */
6929
6930 static inline enum insn_code
6931 get_vcond_icode (tree expr, enum machine_mode mode)
6932 {
6933   enum insn_code icode = CODE_FOR_nothing;
6934
6935   if (TYPE_UNSIGNED (TREE_TYPE (expr)))
6936     icode = vcondu_gen_code[mode];
6937   else
6938     icode = vcond_gen_code[mode];
6939   return icode;
6940 }
6941
6942 /* Return TRUE iff, appropriate vector insns are available
6943    for vector cond expr expr in VMODE mode.  */
6944
6945 bool
6946 expand_vec_cond_expr_p (tree expr, enum machine_mode vmode)
6947 {
6948   if (get_vcond_icode (expr, vmode) == CODE_FOR_nothing)
6949     return false;
6950   return true;
6951 }
6952
6953 /* Generate insns for VEC_COND_EXPR.  */
6954
6955 rtx
6956 expand_vec_cond_expr (tree vec_cond_expr, rtx target)
6957 {
6958   enum insn_code icode;
6959   rtx comparison, rtx_op1, rtx_op2, cc_op0, cc_op1;
6960   enum machine_mode mode = TYPE_MODE (TREE_TYPE (vec_cond_expr));
6961   bool unsignedp = TYPE_UNSIGNED (TREE_TYPE (vec_cond_expr));
6962
6963   icode = get_vcond_icode (vec_cond_expr, mode);
6964   if (icode == CODE_FOR_nothing)
6965     return 0;
6966
6967   if (!target || !insn_data[icode].operand[0].predicate (target, mode))
6968     target = gen_reg_rtx (mode);
6969
6970   /* Get comparison rtx.  First expand both cond expr operands.  */
6971   comparison = vector_compare_rtx (TREE_OPERAND (vec_cond_expr, 0),
6972                                    unsignedp, icode);
6973   cc_op0 = XEXP (comparison, 0);
6974   cc_op1 = XEXP (comparison, 1);
6975   /* Expand both operands and force them in reg, if required.  */
6976   rtx_op1 = expand_normal (TREE_OPERAND (vec_cond_expr, 1));
6977   if (!insn_data[icode].operand[1].predicate (rtx_op1, mode)
6978       && mode != VOIDmode)
6979     rtx_op1 = force_reg (mode, rtx_op1);
6980
6981   rtx_op2 = expand_normal (TREE_OPERAND (vec_cond_expr, 2));
6982   if (!insn_data[icode].operand[2].predicate (rtx_op2, mode)
6983       && mode != VOIDmode)
6984     rtx_op2 = force_reg (mode, rtx_op2);
6985
6986   /* Emit instruction! */
6987   emit_insn (GEN_FCN (icode) (target, rtx_op1, rtx_op2,
6988                               comparison, cc_op0,  cc_op1));
6989
6990   return target;
6991 }
6992
6993 \f
6994 /* This is an internal subroutine of the other compare_and_swap expanders.
6995    MEM, OLD_VAL and NEW_VAL are as you'd expect for a compare-and-swap
6996    operation.  TARGET is an optional place to store the value result of
6997    the operation.  ICODE is the particular instruction to expand.  Return
6998    the result of the operation.  */
6999
7000 static rtx
7001 expand_val_compare_and_swap_1 (rtx mem, rtx old_val, rtx new_val,
7002                                rtx target, enum insn_code icode)
7003 {
7004   enum machine_mode mode = GET_MODE (mem);
7005   rtx insn;
7006
7007   if (!target || !insn_data[icode].operand[0].predicate (target, mode))
7008     target = gen_reg_rtx (mode);
7009
7010   if (GET_MODE (old_val) != VOIDmode && GET_MODE (old_val) != mode)
7011     old_val = convert_modes (mode, GET_MODE (old_val), old_val, 1);
7012   if (!insn_data[icode].operand[2].predicate (old_val, mode))
7013     old_val = force_reg (mode, old_val);
7014
7015   if (GET_MODE (new_val) != VOIDmode && GET_MODE (new_val) != mode)
7016     new_val = convert_modes (mode, GET_MODE (new_val), new_val, 1);
7017   if (!insn_data[icode].operand[3].predicate (new_val, mode))
7018     new_val = force_reg (mode, new_val);
7019
7020   insn = GEN_FCN (icode) (target, mem, old_val, new_val);
7021   if (insn == NULL_RTX)
7022     return NULL_RTX;
7023   emit_insn (insn);
7024
7025   return target;
7026 }
7027
7028 /* Expand a compare-and-swap operation and return its value.  */
7029
7030 rtx
7031 expand_val_compare_and_swap (rtx mem, rtx old_val, rtx new_val, rtx target)
7032 {
7033   enum machine_mode mode = GET_MODE (mem);
7034   enum insn_code icode = sync_compare_and_swap[mode];
7035
7036   if (icode == CODE_FOR_nothing)
7037     return NULL_RTX;
7038
7039   return expand_val_compare_and_swap_1 (mem, old_val, new_val, target, icode);
7040 }
7041
7042 /* Expand a compare-and-swap operation and store true into the result if
7043    the operation was successful and false otherwise.  Return the result.
7044    Unlike other routines, TARGET is not optional.  */
7045
7046 rtx
7047 expand_bool_compare_and_swap (rtx mem, rtx old_val, rtx new_val, rtx target)
7048 {
7049   enum machine_mode mode = GET_MODE (mem);
7050   enum insn_code icode;
7051   rtx subtarget, label0, label1;
7052
7053   /* If the target supports a compare-and-swap pattern that simultaneously
7054      sets some flag for success, then use it.  Otherwise use the regular
7055      compare-and-swap and follow that immediately with a compare insn.  */
7056   icode = sync_compare_and_swap_cc[mode];
7057   switch (icode)
7058     {
7059     default:
7060       subtarget = expand_val_compare_and_swap_1 (mem, old_val, new_val,
7061                                                  NULL_RTX, icode);
7062       if (subtarget != NULL_RTX)
7063         break;
7064
7065       /* FALLTHRU */
7066     case CODE_FOR_nothing:
7067       icode = sync_compare_and_swap[mode];
7068       if (icode == CODE_FOR_nothing)
7069         return NULL_RTX;
7070
7071       /* Ensure that if old_val == mem, that we're not comparing
7072          against an old value.  */
7073       if (MEM_P (old_val))
7074         old_val = force_reg (mode, old_val);
7075
7076       subtarget = expand_val_compare_and_swap_1 (mem, old_val, new_val,
7077                                                  NULL_RTX, icode);
7078       if (subtarget == NULL_RTX)
7079         return NULL_RTX;
7080
7081       emit_cmp_insn (subtarget, old_val, EQ, const0_rtx, mode, true);
7082     }
7083
7084   /* If the target has a sane STORE_FLAG_VALUE, then go ahead and use a
7085      setcc instruction from the beginning.  We don't work too hard here,
7086      but it's nice to not be stupid about initial code gen either.  */
7087   if (STORE_FLAG_VALUE == 1)
7088     {
7089       icode = setcc_gen_code[EQ];
7090       if (icode != CODE_FOR_nothing)
7091         {
7092           enum machine_mode cmode = insn_data[icode].operand[0].mode;
7093           rtx insn;
7094
7095           subtarget = target;
7096           if (!insn_data[icode].operand[0].predicate (target, cmode))
7097             subtarget = gen_reg_rtx (cmode);
7098
7099           insn = GEN_FCN (icode) (subtarget);
7100           if (insn)
7101             {
7102               emit_insn (insn);
7103               if (GET_MODE (target) != GET_MODE (subtarget))
7104                 {
7105                   convert_move (target, subtarget, 1);
7106                   subtarget = target;
7107                 }
7108               return subtarget;
7109             }
7110         }
7111     }
7112
7113   /* Without an appropriate setcc instruction, use a set of branches to
7114      get 1 and 0 stored into target.  Presumably if the target has a
7115      STORE_FLAG_VALUE that isn't 1, then this will get cleaned up by ifcvt.  */
7116
7117   label0 = gen_label_rtx ();
7118   label1 = gen_label_rtx ();
7119
7120   emit_jump_insn (bcc_gen_fctn[EQ] (label0));
7121   emit_move_insn (target, const0_rtx);
7122   emit_jump_insn (gen_jump (label1));
7123   emit_barrier ();
7124   emit_label (label0);
7125   emit_move_insn (target, const1_rtx);
7126   emit_label (label1);
7127
7128   return target;
7129 }
7130
7131 /* This is a helper function for the other atomic operations.  This function
7132    emits a loop that contains SEQ that iterates until a compare-and-swap
7133    operation at the end succeeds.  MEM is the memory to be modified.  SEQ is
7134    a set of instructions that takes a value from OLD_REG as an input and
7135    produces a value in NEW_REG as an output.  Before SEQ, OLD_REG will be
7136    set to the current contents of MEM.  After SEQ, a compare-and-swap will
7137    attempt to update MEM with NEW_REG.  The function returns true when the
7138    loop was generated successfully.  */
7139
7140 static bool
7141 expand_compare_and_swap_loop (rtx mem, rtx old_reg, rtx new_reg, rtx seq)
7142 {
7143   enum machine_mode mode = GET_MODE (mem);
7144   enum insn_code icode;
7145   rtx label, cmp_reg, subtarget;
7146
7147   /* The loop we want to generate looks like
7148
7149         cmp_reg = mem;
7150       label:
7151         old_reg = cmp_reg;
7152         seq;
7153         cmp_reg = compare-and-swap(mem, old_reg, new_reg)
7154         if (cmp_reg != old_reg)
7155           goto label;
7156
7157      Note that we only do the plain load from memory once.  Subsequent
7158      iterations use the value loaded by the compare-and-swap pattern.  */
7159
7160   label = gen_label_rtx ();
7161   cmp_reg = gen_reg_rtx (mode);
7162
7163   emit_move_insn (cmp_reg, mem);
7164   emit_label (label);
7165   emit_move_insn (old_reg, cmp_reg);
7166   if (seq)
7167     emit_insn (seq);
7168
7169   /* If the target supports a compare-and-swap pattern that simultaneously
7170      sets some flag for success, then use it.  Otherwise use the regular
7171      compare-and-swap and follow that immediately with a compare insn.  */
7172   icode = sync_compare_and_swap_cc[mode];
7173   switch (icode)
7174     {
7175     default:
7176       subtarget = expand_val_compare_and_swap_1 (mem, old_reg, new_reg,
7177                                                  cmp_reg, icode);
7178       if (subtarget != NULL_RTX)
7179         {
7180           gcc_assert (subtarget == cmp_reg);
7181           break;
7182         }
7183
7184       /* FALLTHRU */
7185     case CODE_FOR_nothing:
7186       icode = sync_compare_and_swap[mode];
7187       if (icode == CODE_FOR_nothing)
7188         return false;
7189
7190       subtarget = expand_val_compare_and_swap_1 (mem, old_reg, new_reg,
7191                                                  cmp_reg, icode);
7192       if (subtarget == NULL_RTX)
7193         return false;
7194       if (subtarget != cmp_reg)
7195         emit_move_insn (cmp_reg, subtarget);
7196
7197       emit_cmp_insn (cmp_reg, old_reg, EQ, const0_rtx, mode, true);
7198     }
7199
7200   /* ??? Mark this jump predicted not taken?  */
7201   emit_jump_insn (bcc_gen_fctn[NE] (label));
7202
7203   return true;
7204 }
7205
7206 /* This function generates the atomic operation MEM CODE= VAL.  In this
7207    case, we do not care about any resulting value.  Returns NULL if we
7208    cannot generate the operation.  */
7209
7210 rtx
7211 expand_sync_operation (rtx mem, rtx val, enum rtx_code code)
7212 {
7213   enum machine_mode mode = GET_MODE (mem);
7214   enum insn_code icode;
7215   rtx insn;
7216
7217   /* Look to see if the target supports the operation directly.  */
7218   switch (code)
7219     {
7220     case PLUS:
7221       icode = sync_add_optab[mode];
7222       break;
7223     case IOR:
7224       icode = sync_ior_optab[mode];
7225       break;
7226     case XOR:
7227       icode = sync_xor_optab[mode];
7228       break;
7229     case AND:
7230       icode = sync_and_optab[mode];
7231       break;
7232     case NOT:
7233       icode = sync_nand_optab[mode];
7234       break;
7235
7236     case MINUS:
7237       icode = sync_sub_optab[mode];
7238       if (icode == CODE_FOR_nothing)
7239         {
7240           icode = sync_add_optab[mode];
7241           if (icode != CODE_FOR_nothing)
7242             {
7243               val = expand_simple_unop (mode, NEG, val, NULL_RTX, 1);
7244               code = PLUS;
7245             }
7246         }
7247       break;
7248
7249     default:
7250       gcc_unreachable ();
7251     }
7252
7253   /* Generate the direct operation, if present.  */
7254   if (icode != CODE_FOR_nothing)
7255     {
7256       if (GET_MODE (val) != VOIDmode && GET_MODE (val) != mode)
7257         val = convert_modes (mode, GET_MODE (val), val, 1);
7258       if (!insn_data[icode].operand[1].predicate (val, mode))
7259         val = force_reg (mode, val);
7260
7261       insn = GEN_FCN (icode) (mem, val);
7262       if (insn)
7263         {
7264           emit_insn (insn);
7265           return const0_rtx;
7266         }
7267     }
7268
7269   /* Failing that, generate a compare-and-swap loop in which we perform the
7270      operation with normal arithmetic instructions.  */
7271   if (sync_compare_and_swap[mode] != CODE_FOR_nothing)
7272     {
7273       rtx t0 = gen_reg_rtx (mode), t1;
7274
7275       start_sequence ();
7276
7277       t1 = t0;
7278       if (code == NOT)
7279         {
7280           t1 = expand_simple_unop (mode, NOT, t1, NULL_RTX, true);
7281           code = AND;
7282         }
7283       t1 = expand_simple_binop (mode, code, t1, val, NULL_RTX,
7284                                 true, OPTAB_LIB_WIDEN);
7285
7286       insn = get_insns ();
7287       end_sequence ();
7288
7289       if (t1 != NULL && expand_compare_and_swap_loop (mem, t0, t1, insn))
7290         return const0_rtx;
7291     }
7292
7293   return NULL_RTX;
7294 }
7295
7296 /* This function generates the atomic operation MEM CODE= VAL.  In this
7297    case, we do care about the resulting value: if AFTER is true then
7298    return the value MEM holds after the operation, if AFTER is false
7299    then return the value MEM holds before the operation.  TARGET is an
7300    optional place for the result value to be stored.  */
7301
7302 rtx
7303 expand_sync_fetch_operation (rtx mem, rtx val, enum rtx_code code,
7304                              bool after, rtx target)
7305 {
7306   enum machine_mode mode = GET_MODE (mem);
7307   enum insn_code old_code, new_code, icode;
7308   bool compensate;
7309   rtx insn;
7310
7311   /* Look to see if the target supports the operation directly.  */
7312   switch (code)
7313     {
7314     case PLUS:
7315       old_code = sync_old_add_optab[mode];
7316       new_code = sync_new_add_optab[mode];
7317       break;
7318     case IOR:
7319       old_code = sync_old_ior_optab[mode];
7320       new_code = sync_new_ior_optab[mode];
7321       break;
7322     case XOR:
7323       old_code = sync_old_xor_optab[mode];
7324       new_code = sync_new_xor_optab[mode];
7325       break;
7326     case AND:
7327       old_code = sync_old_and_optab[mode];
7328       new_code = sync_new_and_optab[mode];
7329       break;
7330     case NOT:
7331       old_code = sync_old_nand_optab[mode];
7332       new_code = sync_new_nand_optab[mode];
7333       break;
7334
7335     case MINUS:
7336       old_code = sync_old_sub_optab[mode];
7337       new_code = sync_new_sub_optab[mode];
7338       if (old_code == CODE_FOR_nothing && new_code == CODE_FOR_nothing)
7339         {
7340           old_code = sync_old_add_optab[mode];
7341           new_code = sync_new_add_optab[mode];
7342           if (old_code != CODE_FOR_nothing || new_code != CODE_FOR_nothing)
7343             {
7344               val = expand_simple_unop (mode, NEG, val, NULL_RTX, 1);
7345               code = PLUS;
7346             }
7347         }
7348       break;
7349
7350     default:
7351       gcc_unreachable ();
7352     }
7353
7354   /* If the target does supports the proper new/old operation, great.  But
7355      if we only support the opposite old/new operation, check to see if we
7356      can compensate.  In the case in which the old value is supported, then
7357      we can always perform the operation again with normal arithmetic.  In
7358      the case in which the new value is supported, then we can only handle
7359      this in the case the operation is reversible.  */
7360   compensate = false;
7361   if (after)
7362     {
7363       icode = new_code;
7364       if (icode == CODE_FOR_nothing)
7365         {
7366           icode = old_code;
7367           if (icode != CODE_FOR_nothing)
7368             compensate = true;
7369         }
7370     }
7371   else
7372     {
7373       icode = old_code;
7374       if (icode == CODE_FOR_nothing
7375           && (code == PLUS || code == MINUS || code == XOR))
7376         {
7377           icode = new_code;
7378           if (icode != CODE_FOR_nothing)
7379             compensate = true;
7380         }
7381     }
7382
7383   /* If we found something supported, great.  */
7384   if (icode != CODE_FOR_nothing)
7385     {
7386       if (!target || !insn_data[icode].operand[0].predicate (target, mode))
7387         target = gen_reg_rtx (mode);
7388
7389       if (GET_MODE (val) != VOIDmode && GET_MODE (val) != mode)
7390         val = convert_modes (mode, GET_MODE (val), val, 1);
7391       if (!insn_data[icode].operand[2].predicate (val, mode))
7392         val = force_reg (mode, val);
7393
7394       insn = GEN_FCN (icode) (target, mem, val);
7395       if (insn)
7396         {
7397           emit_insn (insn);
7398
7399           /* If we need to compensate for using an operation with the
7400              wrong return value, do so now.  */
7401           if (compensate)
7402             {
7403               if (!after)
7404                 {
7405                   if (code == PLUS)
7406                     code = MINUS;
7407                   else if (code == MINUS)
7408                     code = PLUS;
7409                 }
7410
7411               if (code == NOT)
7412                 target = expand_simple_unop (mode, NOT, target, NULL_RTX, true);
7413               target = expand_simple_binop (mode, code, target, val, NULL_RTX,
7414                                             true, OPTAB_LIB_WIDEN);
7415             }
7416
7417           return target;
7418         }
7419     }
7420
7421   /* Failing that, generate a compare-and-swap loop in which we perform the
7422      operation with normal arithmetic instructions.  */
7423   if (sync_compare_and_swap[mode] != CODE_FOR_nothing)
7424     {
7425       rtx t0 = gen_reg_rtx (mode), t1;
7426
7427       if (!target || !register_operand (target, mode))
7428         target = gen_reg_rtx (mode);
7429
7430       start_sequence ();
7431
7432       if (!after)
7433         emit_move_insn (target, t0);
7434       t1 = t0;
7435       if (code == NOT)
7436         {
7437           t1 = expand_simple_unop (mode, NOT, t1, NULL_RTX, true);
7438           code = AND;
7439         }
7440       t1 = expand_simple_binop (mode, code, t1, val, NULL_RTX,
7441                                 true, OPTAB_LIB_WIDEN);
7442       if (after)
7443         emit_move_insn (target, t1);
7444
7445       insn = get_insns ();
7446       end_sequence ();
7447
7448       if (t1 != NULL && expand_compare_and_swap_loop (mem, t0, t1, insn))
7449         return target;
7450     }
7451
7452   return NULL_RTX;
7453 }
7454
7455 /* This function expands a test-and-set operation.  Ideally we atomically
7456    store VAL in MEM and return the previous value in MEM.  Some targets
7457    may not support this operation and only support VAL with the constant 1;
7458    in this case while the return value will be 0/1, but the exact value
7459    stored in MEM is target defined.  TARGET is an option place to stick
7460    the return value.  */
7461
7462 rtx
7463 expand_sync_lock_test_and_set (rtx mem, rtx val, rtx target)
7464 {
7465   enum machine_mode mode = GET_MODE (mem);
7466   enum insn_code icode;
7467   rtx insn;
7468
7469   /* If the target supports the test-and-set directly, great.  */
7470   icode = sync_lock_test_and_set[mode];
7471   if (icode != CODE_FOR_nothing)
7472     {
7473       if (!target || !insn_data[icode].operand[0].predicate (target, mode))
7474         target = gen_reg_rtx (mode);
7475
7476       if (GET_MODE (val) != VOIDmode && GET_MODE (val) != mode)
7477         val = convert_modes (mode, GET_MODE (val), val, 1);
7478       if (!insn_data[icode].operand[2].predicate (val, mode))
7479         val = force_reg (mode, val);
7480
7481       insn = GEN_FCN (icode) (target, mem, val);
7482       if (insn)
7483         {
7484           emit_insn (insn);
7485           return target;
7486         }
7487     }
7488
7489   /* Otherwise, use a compare-and-swap loop for the exchange.  */
7490   if (sync_compare_and_swap[mode] != CODE_FOR_nothing)
7491     {
7492       if (!target || !register_operand (target, mode))
7493         target = gen_reg_rtx (mode);
7494       if (GET_MODE (val) != VOIDmode && GET_MODE (val) != mode)
7495         val = convert_modes (mode, GET_MODE (val), val, 1);
7496       if (expand_compare_and_swap_loop (mem, target, val, NULL_RTX))
7497         return target;
7498     }
7499
7500   return NULL_RTX;
7501 }
7502
7503 #include "gt-optabs.h"