OSDN Git Service

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