OSDN Git Service

(atoi): Remove declaration.
[pf3gnuchains/gcc-fork.git] / gcc / optabs.c
1 /* Expand the basic unary and binary arithmetic operations, for GNU compiler.
2    Copyright (C) 1987, 1988, 1992, 1993, 1994 Free Software Foundation, Inc.
3
4 This file is part of GNU CC.
5
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING.  If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
19
20
21 #include "config.h"
22 #include "rtl.h"
23 #include "tree.h"
24 #include "flags.h"
25 #include "insn-flags.h"
26 #include "insn-codes.h"
27 #include "expr.h"
28 #include "insn-config.h"
29 #include "recog.h"
30 #include "reload.h"
31 #include <ctype.h>
32
33 /* Each optab contains info on how this target machine
34    can perform a particular operation
35    for all sizes and kinds of operands.
36
37    The operation to be performed is often specified
38    by passing one of these optabs as an argument.
39
40    See expr.h for documentation of these optabs.  */
41
42 optab add_optab;
43 optab sub_optab;
44 optab smul_optab;
45 optab smul_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 routine 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       rtx value;
3568
3569       to = protect_from_queue (to, 1);
3570       from = protect_from_queue (from, 0);
3571
3572       if (flag_force_mem)
3573         from = force_not_mem (from);
3574
3575       start_sequence ();
3576
3577       value = emit_library_call_value (libfcn, NULL_RTX, 1, GET_MODE (to),
3578
3579                                        1, from, GET_MODE (from));
3580       insns = get_insns ();
3581       end_sequence ();
3582
3583       emit_libcall_block (insns, target, value,
3584                           gen_rtx (unsignedp ? FIX : UNSIGNED_FIX,
3585                                    GET_MODE (to), from));
3586     }
3587       
3588   if (GET_MODE (to) == GET_MODE (target))
3589     emit_move_insn (to, target);
3590   else
3591     convert_move (to, target, 0);
3592 }
3593 \f
3594 static optab
3595 init_optab (code)
3596      enum rtx_code code;
3597 {
3598   int i;
3599   optab op = (optab) xmalloc (sizeof (struct optab));
3600   op->code = code;
3601   for (i = 0; i < NUM_MACHINE_MODES; i++)
3602     {
3603       op->handlers[i].insn_code = CODE_FOR_nothing;
3604       op->handlers[i].libfunc = 0;
3605     }
3606
3607   if (code != UNKNOWN)
3608     code_to_optab[(int) code] = op;
3609
3610   return op;
3611 }
3612
3613 /* Initialize the libfunc fields of an entire group of entries in some
3614    optab.  Each entry is set equal to a string consisting of a leading
3615    pair of underscores followed by a generic operation name followed by
3616    a mode name (downshifted to lower case) followed by a single character
3617    representing the number of operands for the given operation (which is
3618    usually one of the characters '2', '3', or '4').
3619
3620    OPTABLE is the table in which libfunc fields are to be initialized.
3621    FIRST_MODE is the first machine mode index in the given optab to
3622      initialize.
3623    LAST_MODE is the last machine mode index in the given optab to
3624      initialize.
3625    OPNAME is the generic (string) name of the operation.
3626    SUFFIX is the character which specifies the number of operands for
3627      the given generic operation.
3628 */
3629
3630 static void
3631 init_libfuncs (optable, first_mode, last_mode, opname, suffix)
3632     register optab optable;
3633     register int first_mode;
3634     register int last_mode;
3635     register char *opname;
3636     register char suffix;
3637 {
3638   register int mode;
3639   register unsigned opname_len = strlen (opname);
3640
3641   for (mode = first_mode; (int) mode <= (int) last_mode;
3642        mode = (enum machine_mode) ((int) mode + 1))
3643     {
3644       register char *mname = mode_name[(int) mode];
3645       register unsigned mname_len = strlen (mname);
3646       register char *libfunc_name
3647         = (char *) xmalloc (2 + opname_len + mname_len + 1 + 1);
3648       register char *p;
3649       register char *q;
3650
3651       p = libfunc_name;
3652       *p++ = '_';
3653       *p++ = '_';
3654       for (q = opname; *q; )
3655         *p++ = *q++;
3656       for (q = mname; *q; q++)
3657         *p++ = tolower (*q);
3658       *p++ = suffix;
3659       *p++ = '\0';
3660       optable->handlers[(int) mode].libfunc
3661         = gen_rtx (SYMBOL_REF, Pmode, libfunc_name);
3662     }
3663 }
3664
3665 /* Initialize the libfunc fields of an entire group of entries in some
3666    optab which correspond to all integer mode operations.  The parameters
3667    have the same meaning as similarly named ones for the `init_libfuncs'
3668    routine.  (See above).  */
3669
3670 static void
3671 init_integral_libfuncs (optable, opname, suffix)
3672     register optab optable;
3673     register char *opname;
3674     register char suffix;
3675 {
3676   init_libfuncs (optable, SImode, TImode, opname, suffix);
3677 }
3678
3679 /* Initialize the libfunc fields of an entire group of entries in some
3680    optab which correspond to all real mode operations.  The parameters
3681    have the same meaning as similarly named ones for the `init_libfuncs'
3682    routine.  (See above).  */
3683
3684 static void
3685 init_floating_libfuncs (optable, opname, suffix)
3686     register optab optable;
3687     register char *opname;
3688     register char suffix;
3689 {
3690   init_libfuncs (optable, SFmode, TFmode, opname, suffix);
3691 }
3692
3693 /* Initialize the libfunc fields of an entire group of entries in some
3694    optab which correspond to all complex floating modes.  The parameters
3695    have the same meaning as similarly named ones for the `init_libfuncs'
3696    routine.  (See above).  */
3697
3698 static void
3699 init_complex_libfuncs (optable, opname, suffix)
3700     register optab optable;
3701     register char *opname;
3702     register char suffix;
3703 {
3704   init_libfuncs (optable, SCmode, TCmode, opname, suffix);
3705 }
3706
3707 /* Call this once to initialize the contents of the optabs
3708    appropriately for the current target machine.  */
3709
3710 void
3711 init_optabs ()
3712 {
3713   int i, j;
3714   enum insn_code *p;
3715
3716   /* Start by initializing all tables to contain CODE_FOR_nothing.  */
3717
3718   for (p = fixtab[0][0];
3719        p < fixtab[0][0] + sizeof fixtab / sizeof (fixtab[0][0][0]); 
3720        p++)
3721     *p = CODE_FOR_nothing;
3722
3723   for (p = fixtrunctab[0][0];
3724        p < fixtrunctab[0][0] + sizeof fixtrunctab / sizeof (fixtrunctab[0][0][0]); 
3725        p++)
3726     *p = CODE_FOR_nothing;
3727
3728   for (p = floattab[0][0];
3729        p < floattab[0][0] + sizeof floattab / sizeof (floattab[0][0][0]); 
3730        p++)
3731     *p = CODE_FOR_nothing;
3732
3733   for (p = extendtab[0][0];
3734        p < extendtab[0][0] + sizeof extendtab / sizeof extendtab[0][0][0];
3735        p++)
3736     *p = CODE_FOR_nothing;
3737
3738   for (i = 0; i < NUM_RTX_CODE; i++)
3739     setcc_gen_code[i] = CODE_FOR_nothing;
3740
3741   add_optab = init_optab (PLUS);
3742   sub_optab = init_optab (MINUS);
3743   smul_optab = init_optab (MULT);
3744   smul_highpart_optab = init_optab (UNKNOWN);
3745   umul_highpart_optab = init_optab (UNKNOWN);
3746   smul_widen_optab = init_optab (UNKNOWN);
3747   umul_widen_optab = init_optab (UNKNOWN);
3748   sdiv_optab = init_optab (DIV);
3749   sdivmod_optab = init_optab (UNKNOWN);
3750   udiv_optab = init_optab (UDIV);
3751   udivmod_optab = init_optab (UNKNOWN);
3752   smod_optab = init_optab (MOD);
3753   umod_optab = init_optab (UMOD);
3754   flodiv_optab = init_optab (DIV);
3755   ftrunc_optab = init_optab (UNKNOWN);
3756   and_optab = init_optab (AND);
3757   ior_optab = init_optab (IOR);
3758   xor_optab = init_optab (XOR);
3759   ashl_optab = init_optab (ASHIFT);
3760   ashr_optab = init_optab (ASHIFTRT);
3761   lshr_optab = init_optab (LSHIFTRT);
3762   rotl_optab = init_optab (ROTATE);
3763   rotr_optab = init_optab (ROTATERT);
3764   smin_optab = init_optab (SMIN);
3765   smax_optab = init_optab (SMAX);
3766   umin_optab = init_optab (UMIN);
3767   umax_optab = init_optab (UMAX);
3768   mov_optab = init_optab (UNKNOWN);
3769   movstrict_optab = init_optab (UNKNOWN);
3770   cmp_optab = init_optab (UNKNOWN);
3771   ucmp_optab = init_optab (UNKNOWN);
3772   tst_optab = init_optab (UNKNOWN);
3773   neg_optab = init_optab (NEG);
3774   abs_optab = init_optab (ABS);
3775   one_cmpl_optab = init_optab (NOT);
3776   ffs_optab = init_optab (FFS);
3777   sqrt_optab = init_optab (SQRT);
3778   sin_optab = init_optab (UNKNOWN);
3779   cos_optab = init_optab (UNKNOWN);
3780   strlen_optab = init_optab (UNKNOWN);
3781
3782   for (i = 0; i < NUM_MACHINE_MODES; i++)
3783     {
3784       movstr_optab[i] = CODE_FOR_nothing;
3785
3786 #ifdef HAVE_SECONDARY_RELOADS
3787       reload_in_optab[i] = reload_out_optab[i] = CODE_FOR_nothing;
3788 #endif
3789     }
3790
3791   /* Fill in the optabs with the insns we support.  */
3792   init_all_optabs ();
3793
3794 #ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC
3795   /* This flag says the same insns that convert to a signed fixnum
3796      also convert validly to an unsigned one.  */
3797   for (i = 0; i < NUM_MACHINE_MODES; i++)
3798     for (j = 0; j < NUM_MACHINE_MODES; j++)
3799       fixtrunctab[i][j][1] = fixtrunctab[i][j][0];
3800 #endif
3801
3802 #ifdef EXTRA_CC_MODES
3803   init_mov_optab ();
3804 #endif
3805
3806   /* Initialize the optabs with the names of the library functions.  */
3807   init_integral_libfuncs (add_optab, "add", '3');
3808   init_floating_libfuncs (add_optab, "add", '3');
3809   init_integral_libfuncs (sub_optab, "sub", '3');
3810   init_floating_libfuncs (sub_optab, "sub", '3');
3811   init_integral_libfuncs (smul_optab, "mul", '3');
3812   init_floating_libfuncs (smul_optab, "mul", '3');
3813   init_integral_libfuncs (sdiv_optab, "div", '3');
3814   init_integral_libfuncs (udiv_optab, "udiv", '3');
3815   init_integral_libfuncs (sdivmod_optab, "divmod", '4');
3816   init_integral_libfuncs (udivmod_optab, "udivmod", '4');
3817   init_integral_libfuncs (smod_optab, "mod", '3');
3818   init_integral_libfuncs (umod_optab, "umod", '3');
3819   init_floating_libfuncs (flodiv_optab, "div", '3');
3820   init_floating_libfuncs (ftrunc_optab, "ftrunc", '2');
3821   init_integral_libfuncs (and_optab, "and", '3');
3822   init_integral_libfuncs (ior_optab, "ior", '3');
3823   init_integral_libfuncs (xor_optab, "xor", '3');
3824   init_integral_libfuncs (ashl_optab, "ashl", '3');
3825   init_integral_libfuncs (ashr_optab, "ashr", '3');
3826   init_integral_libfuncs (lshr_optab, "lshr", '3');
3827   init_integral_libfuncs (rotl_optab, "rotl", '3');
3828   init_integral_libfuncs (rotr_optab, "rotr", '3');
3829   init_integral_libfuncs (smin_optab, "min", '3');
3830   init_floating_libfuncs (smin_optab, "min", '3');
3831   init_integral_libfuncs (smax_optab, "max", '3');
3832   init_floating_libfuncs (smax_optab, "max", '3');
3833   init_integral_libfuncs (umin_optab, "umin", '3');
3834   init_integral_libfuncs (umax_optab, "umax", '3');
3835   init_integral_libfuncs (neg_optab, "neg", '2');
3836   init_floating_libfuncs (neg_optab, "neg", '2');
3837   init_integral_libfuncs (one_cmpl_optab, "one_cmpl", '2');
3838   init_integral_libfuncs (ffs_optab, "ffs", '2');
3839
3840   /* Comparison libcalls for integers MUST come in pairs, signed/unsigned.  */
3841   init_integral_libfuncs (cmp_optab, "cmp", '2');
3842   init_integral_libfuncs (ucmp_optab, "ucmp", '2');
3843   init_floating_libfuncs (cmp_optab, "cmp", '2');
3844
3845 #ifdef MULSI3_LIBCALL
3846   smul_optab->handlers[(int) SImode].libfunc
3847     = gen_rtx (SYMBOL_REF, Pmode, MULSI3_LIBCALL);
3848 #endif
3849 #ifdef MULDI3_LIBCALL
3850   smul_optab->handlers[(int) DImode].libfunc
3851     = gen_rtx (SYMBOL_REF, Pmode, MULDI3_LIBCALL);
3852 #endif
3853 #ifdef MULTI3_LIBCALL
3854   smul_optab->handlers[(int) TImode].libfunc
3855     = gen_rtx (SYMBOL_REF, Pmode, MULTI3_LIBCALL);
3856 #endif
3857
3858 #ifdef DIVSI3_LIBCALL
3859   sdiv_optab->handlers[(int) SImode].libfunc
3860     = gen_rtx (SYMBOL_REF, Pmode, DIVSI3_LIBCALL);
3861 #endif
3862 #ifdef DIVDI3_LIBCALL
3863   sdiv_optab->handlers[(int) DImode].libfunc
3864     = gen_rtx (SYMBOL_REF, Pmode, DIVDI3_LIBCALL);
3865 #endif
3866 #ifdef DIVTI3_LIBCALL
3867   sdiv_optab->handlers[(int) TImode].libfunc
3868     = gen_rtx (SYMBOL_REF, Pmode, DIVTI3_LIBCALL);
3869 #endif
3870
3871 #ifdef UDIVSI3_LIBCALL
3872   udiv_optab->handlers[(int) SImode].libfunc
3873     = gen_rtx (SYMBOL_REF, Pmode, UDIVSI3_LIBCALL);
3874 #endif
3875 #ifdef UDIVDI3_LIBCALL
3876   udiv_optab->handlers[(int) DImode].libfunc
3877     = gen_rtx (SYMBOL_REF, Pmode, UDIVDI3_LIBCALL);
3878 #endif
3879 #ifdef UDIVTI3_LIBCALL
3880   udiv_optab->handlers[(int) TImode].libfunc
3881     = gen_rtx (SYMBOL_REF, Pmode, UDIVTI3_LIBCALL);
3882 #endif
3883
3884
3885 #ifdef MODSI3_LIBCALL
3886   smod_optab->handlers[(int) SImode].libfunc
3887     = gen_rtx (SYMBOL_REF, Pmode, MODSI3_LIBCALL);
3888 #endif
3889 #ifdef MODDI3_LIBCALL
3890   smod_optab->handlers[(int) DImode].libfunc
3891     = gen_rtx (SYMBOL_REF, Pmode, MODDI3_LIBCALL);
3892 #endif
3893 #ifdef MODTI3_LIBCALL
3894   smod_optab->handlers[(int) TImode].libfunc
3895     = gen_rtx (SYMBOL_REF, Pmode, MODTI3_LIBCALL);
3896 #endif
3897
3898
3899 #ifdef UMODSI3_LIBCALL
3900   umod_optab->handlers[(int) SImode].libfunc
3901     = gen_rtx (SYMBOL_REF, Pmode, UMODSI3_LIBCALL);
3902 #endif
3903 #ifdef UMODDI3_LIBCALL
3904   umod_optab->handlers[(int) DImode].libfunc
3905     = gen_rtx (SYMBOL_REF, Pmode, UMODDI3_LIBCALL);
3906 #endif
3907 #ifdef UMODTI3_LIBCALL
3908   umod_optab->handlers[(int) TImode].libfunc
3909     = gen_rtx (SYMBOL_REF, Pmode, UMODTI3_LIBCALL);
3910 #endif
3911
3912 /* Define library calls for quad FP instructions */
3913 #ifdef ADDTF3_LIBCALL
3914   add_optab->handlers[(int) TFmode].libfunc
3915     = gen_rtx (SYMBOL_REF, Pmode, ADDTF3_LIBCALL);
3916 #endif
3917 #ifdef SUBTF3_LIBCALL
3918   sub_optab->handlers[(int) TFmode].libfunc
3919     = gen_rtx (SYMBOL_REF, Pmode, SUBTF3_LIBCALL);
3920 #endif
3921 #ifdef MULTF3_LIBCALL
3922   smul_optab->handlers[(int) TFmode].libfunc
3923     = gen_rtx (SYMBOL_REF, Pmode, MULTF3_LIBCALL);
3924 #endif
3925 #ifdef DIVTF3_LIBCALL
3926   flodiv_optab->handlers[(int) TFmode].libfunc
3927     = gen_rtx (SYMBOL_REF, Pmode, DIVTF3_LIBCALL);
3928 #endif
3929 #ifdef SQRTTF2_LIBCALL
3930   sqrt_optab->handlers[(int) TFmode].libfunc
3931     = gen_rtx (SYMBOL_REF, Pmode, SQRTTF2_LIBCALL);
3932 #endif
3933
3934   /* Use cabs for DC complex abs, since systems generally have cabs.
3935      Don't define any libcall for SCmode, so that cabs will be used.  */
3936   abs_optab->handlers[(int) DCmode].libfunc
3937     = gen_rtx (SYMBOL_REF, Pmode, "cabs");
3938
3939   /* The ffs function operates on `int'.  */
3940 #ifndef INT_TYPE_SIZE
3941 #define INT_TYPE_SIZE BITS_PER_WORD
3942 #endif
3943   ffs_optab->handlers[(int) mode_for_size (INT_TYPE_SIZE, MODE_INT, 0)] .libfunc
3944     = gen_rtx (SYMBOL_REF, Pmode, "ffs");
3945
3946   extendsfdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extendsfdf2");
3947   extendsfxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extendsfxf2");
3948   extendsftf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extendsftf2");
3949   extenddfxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extenddfxf2");
3950   extenddftf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extenddftf2");
3951
3952   truncdfsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__truncdfsf2");
3953   truncxfsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__truncxfsf2");
3954   trunctfsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__trunctfsf2");
3955   truncxfdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__truncxfdf2");
3956   trunctfdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__trunctfdf2");
3957
3958   memcpy_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memcpy");
3959   bcopy_libfunc = gen_rtx (SYMBOL_REF, Pmode, "bcopy");
3960   memcmp_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memcmp");
3961   bcmp_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gcc_bcmp");
3962   memset_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memset");
3963   bzero_libfunc = gen_rtx (SYMBOL_REF, Pmode, "bzero");
3964
3965   eqsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqsf2");
3966   nesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nesf2");
3967   gtsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gtsf2");
3968   gesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gesf2");
3969   ltsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ltsf2");
3970   lesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__lesf2");
3971
3972   eqdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqdf2");
3973   nedf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nedf2");
3974   gtdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gtdf2");
3975   gedf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gedf2");
3976   ltdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ltdf2");
3977   ledf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ledf2");
3978
3979   eqxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqxf2");
3980   nexf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nexf2");
3981   gtxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gtxf2");
3982   gexf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gexf2");
3983   ltxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ltxf2");
3984   lexf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__lexf2");
3985
3986   eqtf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqtf2");
3987   netf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__netf2");
3988   gttf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gttf2");
3989   getf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__getf2");
3990   lttf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__lttf2");
3991   letf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__letf2");
3992
3993 /* Define library calls for quad FP instructions */
3994 #ifdef EQTF2_LIBCALL
3995   eqtf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, EQTF2_LIBCALL);
3996 #endif
3997 #ifdef NETF2_LIBCALL
3998   netf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, NETF2_LIBCALL);
3999 #endif
4000 #ifdef GTTF2_LIBCALL
4001   gttf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, GTTF2_LIBCALL);
4002 #endif
4003 #ifdef GETF2_LIBCALL
4004   getf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, GETF2_LIBCALL);
4005 #endif
4006 #ifdef LTTF2_LIBCALL
4007   lttf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, LTTF2_LIBCALL);
4008 #endif
4009 #ifdef LETF2_LIBCALL
4010   letf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, LETF2_LIBCALL);
4011 #endif
4012
4013   floatsisf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsisf");
4014   floatdisf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatdisf");
4015   floattisf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floattisf");
4016
4017   floatsidf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsidf");
4018   floatdidf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatdidf");
4019   floattidf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floattidf");
4020
4021   floatsixf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsixf");
4022   floatdixf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatdixf");
4023   floattixf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floattixf");
4024
4025   floatsitf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsitf");
4026   floatditf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatditf");
4027   floattitf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floattitf");
4028
4029   fixsfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixsfsi");
4030   fixsfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixsfdi");
4031   fixsfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixsfti");
4032
4033   fixdfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixdfsi");
4034   fixdfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixdfdi");
4035   fixdfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixdfti");
4036
4037   fixxfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixxfsi");
4038   fixxfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixxfdi");
4039   fixxfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixxfti");
4040
4041   fixtfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixtfsi");
4042   fixtfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixtfdi");
4043   fixtfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixtfti");
4044
4045   fixunssfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunssfsi");
4046   fixunssfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunssfdi");
4047   fixunssfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunssfti");
4048
4049   fixunsdfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsdfsi");
4050   fixunsdfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsdfdi");
4051   fixunsdfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsdfti");
4052
4053   fixunsxfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsxfsi");
4054   fixunsxfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsxfdi");
4055   fixunsxfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsxfti");
4056
4057   fixunstfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunstfsi");
4058   fixunstfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunstfdi");
4059   fixunstfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunstfti");
4060
4061 /* Define library calls for quad FP instructions */
4062 #ifdef TRUNCTFSF2_LIBCALL
4063   trunctfsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, TRUNCTFSF2_LIBCALL);
4064 #endif
4065 #ifdef TRUNCTFDF2_LIBCALL
4066   trunctfdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, TRUNCTFDF2_LIBCALL);
4067 #endif
4068 #ifdef EXTENDSFTF2_LIBCALL
4069   extendsftf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, EXTENDSFTF2_LIBCALL);
4070 #endif
4071 #ifdef EXTENDDFTF2_LIBCALL
4072   extenddftf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, EXTENDDFTF2_LIBCALL);
4073 #endif
4074 #ifdef FLOATSITF2_LIBCALL
4075   floatsitf_libfunc = gen_rtx (SYMBOL_REF, Pmode, FLOATSITF2_LIBCALL);
4076 #endif
4077 #ifdef FIX_TRUNCTFSI2_LIBCALL
4078   fixtfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, FIX_TRUNCTFSI2_LIBCALL);
4079 #endif
4080 #ifdef FIXUNS_TRUNCTFSI2_LIBCALL
4081   fixunstfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, FIXUNS_TRUNCTFSI2_LIBCALL);
4082 #endif
4083
4084 #ifdef INIT_TARGET_OPTABS
4085   /* Allow the target to add more libcalls or rename some, etc.  */
4086   INIT_TARGET_OPTABS;
4087 #endif
4088 }
4089 \f
4090 #ifdef BROKEN_LDEXP
4091
4092 /* SCO 3.2 apparently has a broken ldexp. */
4093
4094 double
4095 ldexp(x,n)
4096      double x;
4097      int n;
4098 {
4099   if (n > 0)
4100     while (n--)
4101       x *= 2;
4102
4103   return x;
4104 }
4105 #endif /* BROKEN_LDEXP */