OSDN Git Service

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