OSDN Git Service

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