OSDN Git Service

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