OSDN Git Service

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