OSDN Git Service

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