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