OSDN Git Service

(expand_float): Fix error in last change.
[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, 0, 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                                      0, 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                                       0, 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, 0, unsignedp, methods),
1184                                   expand_binop (submode, binoptab, imag0,
1185                                                 imag1, 0, unsignedp, methods),
1186                                   realr, unsignedp, methods);
1187
1188               if (res != realr)
1189                 emit_move_insn (realr, res);
1190
1191               res = expand_binop (submode, add_optab,
1192                                   expand_binop (submode, binoptab,
1193                                                 real0, imag1,
1194                                                 0, unsignedp, methods),
1195                                   expand_binop (submode, binoptab,
1196                                                 real1, imag0,
1197                                                 0, unsignedp, methods),
1198                                   imagr, unsignedp, methods);
1199               if (res != imagr)
1200                 emit_move_insn (imagr, res);
1201             }
1202           else
1203             {
1204               /* Don't fetch these from memory more than once.  */
1205               real0 = force_reg (submode, real0);
1206               real1 = force_reg (submode, real1);
1207
1208               res = expand_binop (submode, binoptab, real0, real1,
1209                                   realr, unsignedp, methods);
1210               if (res != realr)
1211                 emit_move_insn (realr, res);
1212
1213               if (imag0)
1214                 res = expand_binop (submode, binoptab,
1215                                     real1, imag0, imagr, unsignedp, methods);
1216               else
1217                 res = expand_binop (submode, binoptab,
1218                                     real0, imag1, imagr, unsignedp, methods);
1219               if (res != imagr)
1220                 emit_move_insn (imagr, res);
1221             }
1222           break;
1223
1224         case DIV:
1225           /* (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd)) */
1226           
1227           if (! imag1)
1228             {   /* (a+ib) / (c+i0) = (a/c) + i(b/c) */
1229
1230               /* Don't fetch these from memory more than once.  */
1231               real1 = force_reg (submode, real1);
1232
1233               /* Simply divide the real and imaginary parts by `c' */
1234               if (class == MODE_COMPLEX_FLOAT)
1235                 res = expand_binop (submode, binoptab, real0, real1,
1236                                     realr, unsignedp, methods);
1237               else
1238                 res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
1239                                      real0, real1, realr, unsignedp);
1240
1241               if (res != realr)
1242                 emit_move_insn (realr, res);
1243
1244               if (class == MODE_COMPLEX_FLOAT)
1245                 res = expand_binop (submode, binoptab, imag0, real1,
1246                                     imagr, unsignedp, methods);
1247               else
1248                 res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
1249                                      imag0, real1, imagr, unsignedp);
1250
1251               if (res != imagr)
1252                 emit_move_insn (imagr, res);
1253             }
1254           else                  /* Divisor is of complex type */
1255             {                   /* X/(a+ib) */
1256
1257               rtx divisor;
1258               rtx real_t;
1259               rtx imag_t;
1260               rtx lhs, rhs;
1261               
1262               /* Don't fetch these from memory more than once.  */
1263               real0 = force_reg (submode, real0);
1264               real1 = force_reg (submode, real1);
1265               if (imag0)
1266                 imag0 = force_reg (submode, imag0);
1267               imag1 = force_reg (submode, imag1);
1268
1269               /* Divisor: c*c + d*d */
1270               divisor = expand_binop (submode, add_optab,
1271                                       expand_binop (submode, smul_optab,
1272                                                     real1, real1,
1273                                                     0, unsignedp, methods),
1274                                       expand_binop (submode, smul_optab,
1275                                                     imag1, imag1,
1276                                                     0, unsignedp, methods),
1277                                       0, unsignedp, methods);
1278
1279               if (! imag0)      /* ((a)(c-id))/divisor */
1280                 {       /* (a+i0) / (c+id) = (ac/(cc+dd)) + i(-ad/(cc+dd)) */
1281                   /* Calculate the dividend */
1282                   real_t = expand_binop (submode, smul_optab, real0, real1,
1283                                          0, unsignedp, methods);
1284                   
1285                   imag_t
1286                     = expand_unop (submode, neg_optab,
1287                                    expand_binop (submode, smul_optab, real0,
1288                                                  imag1, 0, unsignedp, methods),
1289                                    0, unsignedp);
1290                 }
1291               else              /* ((a+ib)(c-id))/divider */
1292                 {
1293                   /* Calculate the dividend */
1294                   real_t = expand_binop (submode, add_optab,
1295                                          expand_binop (submode, smul_optab,
1296                                                        real0, real1,
1297                                                        0, unsignedp, methods),
1298                                          expand_binop (submode, smul_optab,
1299                                                        imag0, imag1,
1300                                                        0, unsignedp, methods),
1301                                          0, unsignedp, methods);
1302                   
1303                   imag_t = expand_binop (submode, sub_optab,
1304                                          expand_binop (submode, smul_optab,
1305                                                        imag0, real1,
1306                                                        0, unsignedp, methods),
1307                                          expand_binop (submode, smul_optab,
1308                                                        real0, imag1,
1309                                                        0, unsignedp, methods),
1310                                          0, unsignedp, methods);
1311
1312                 }
1313
1314               if (class == MODE_COMPLEX_FLOAT)
1315                 res = expand_binop (submode, binoptab, real_t, divisor,
1316                                     realr, unsignedp, methods);
1317               else
1318                 res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
1319                                      real_t, divisor, realr, unsignedp);
1320
1321               if (res != realr)
1322                 emit_move_insn (realr, res);
1323
1324               if (class == MODE_COMPLEX_FLOAT)
1325                 res = expand_binop (submode, binoptab, imag_t, divisor,
1326                                     imagr, unsignedp, methods);
1327               else
1328                 res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
1329                                      imag_t, divisor, imagr, unsignedp);
1330
1331               if (res != imagr)
1332                 emit_move_insn (imagr, res);
1333             }
1334           break;
1335           
1336         default:
1337           abort ();
1338         }
1339
1340       seq = get_insns ();
1341       end_sequence ();
1342
1343       if (binoptab->code != UNKNOWN)
1344         equiv_value
1345           = gen_rtx (binoptab->code, mode, copy_rtx (op0), copy_rtx (op1));
1346       else
1347         equiv_value = 0;
1348           
1349       emit_no_conflict_block (seq, target, op0, op1, equiv_value);
1350       
1351       return target;
1352     }
1353
1354   /* It can't be open-coded in this mode.
1355      Use a library call if one is available and caller says that's ok.  */
1356
1357   if (binoptab->handlers[(int) mode].libfunc
1358       && (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN))
1359     {
1360       rtx insns;
1361       rtx funexp = binoptab->handlers[(int) mode].libfunc;
1362       rtx op1x = op1;
1363       enum machine_mode op1_mode = mode;
1364       rtx value;
1365
1366       start_sequence ();
1367
1368       if (shift_op)
1369         {
1370           op1_mode = word_mode;
1371           /* Specify unsigned here,
1372              since negative shift counts are meaningless.  */
1373           op1x = convert_to_mode (word_mode, op1, 1);
1374         }
1375
1376       /* Pass 1 for NO_QUEUE so we don't lose any increments
1377          if the libcall is cse'd or moved.  */
1378       value = emit_library_call_value (binoptab->handlers[(int) mode].libfunc,
1379                                        NULL_RTX, 1, mode, 2,
1380                                        op0, mode, op1x, op1_mode);
1381
1382       insns = get_insns ();
1383       end_sequence ();
1384
1385       target = gen_reg_rtx (mode);
1386       emit_libcall_block (insns, target, value,
1387                           gen_rtx (binoptab->code, mode, op0, op1));
1388
1389       return target;
1390     }
1391
1392   delete_insns_since (last);
1393
1394   /* It can't be done in this mode.  Can we do it in a wider mode?  */
1395
1396   if (! (methods == OPTAB_WIDEN || methods == OPTAB_LIB_WIDEN
1397          || methods == OPTAB_MUST_WIDEN))
1398     {
1399       /* Caller says, don't even try.  */
1400       delete_insns_since (entry_last);
1401       return 0;
1402     }
1403
1404   /* Compute the value of METHODS to pass to recursive calls.
1405      Don't allow widening to be tried recursively.  */
1406
1407   methods = (methods == OPTAB_LIB_WIDEN ? OPTAB_LIB : OPTAB_DIRECT);
1408
1409   /* Look for a wider mode of the same class for which it appears we can do
1410      the operation.  */
1411
1412   if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
1413     {
1414       for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
1415            wider_mode = GET_MODE_WIDER_MODE (wider_mode))
1416         {
1417           if ((binoptab->handlers[(int) wider_mode].insn_code
1418                != CODE_FOR_nothing)
1419               || (methods == OPTAB_LIB
1420                   && binoptab->handlers[(int) wider_mode].libfunc))
1421             {
1422               rtx xop0 = op0, xop1 = op1;
1423               int no_extend = 0;
1424
1425               /* For certain integer operations, we need not actually extend
1426                  the narrow operands, as long as we will truncate
1427                  the results to the same narrowness.  */
1428
1429               if ((binoptab == ior_optab || binoptab == and_optab
1430                    || binoptab == xor_optab
1431                    || binoptab == add_optab || binoptab == sub_optab
1432                    || binoptab == smul_optab || binoptab == ashl_optab)
1433                   && class == MODE_INT)
1434                 no_extend = 1;
1435
1436               xop0 = widen_operand (xop0, wider_mode, mode,
1437                                     unsignedp, no_extend);
1438
1439               /* The second operand of a shift must always be extended.  */
1440               xop1 = widen_operand (xop1, wider_mode, mode, unsignedp,
1441                                     no_extend && binoptab != ashl_optab);
1442
1443               temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX,
1444                                    unsignedp, methods);
1445               if (temp)
1446                 {
1447                   if (class != MODE_INT)
1448                     {
1449                       if (target == 0)
1450                         target = gen_reg_rtx (mode);
1451                       convert_move (target, temp, 0);
1452                       return target;
1453                     }
1454                   else
1455                     return gen_lowpart (mode, temp);
1456                 }
1457               else
1458                 delete_insns_since (last);
1459             }
1460         }
1461     }
1462
1463   delete_insns_since (entry_last);
1464   return 0;
1465 }
1466 \f
1467 /* Expand a binary operator which has both signed and unsigned forms.
1468    UOPTAB is the optab for unsigned operations, and SOPTAB is for
1469    signed operations.
1470
1471    If we widen unsigned operands, we may use a signed wider operation instead
1472    of an unsigned wider operation, since the result would be the same.  */
1473
1474 rtx
1475 sign_expand_binop (mode, uoptab, soptab, op0, op1, target, unsignedp, methods)
1476     enum machine_mode mode;
1477     optab uoptab, soptab;
1478     rtx op0, op1, target;
1479     int unsignedp;
1480     enum optab_methods methods;
1481 {
1482   register rtx temp;
1483   optab direct_optab = unsignedp ? uoptab : soptab;
1484   struct optab wide_soptab;
1485
1486   /* Do it without widening, if possible.  */
1487   temp = expand_binop (mode, direct_optab, op0, op1, target,
1488                        unsignedp, OPTAB_DIRECT);
1489   if (temp || methods == OPTAB_DIRECT)
1490     return temp;
1491
1492   /* Try widening to a signed int.  Make a fake signed optab that
1493      hides any signed insn for direct use.  */
1494   wide_soptab = *soptab;
1495   wide_soptab.handlers[(int) mode].insn_code = CODE_FOR_nothing;
1496   wide_soptab.handlers[(int) mode].libfunc = 0;
1497
1498   temp = expand_binop (mode, &wide_soptab, op0, op1, target,
1499                        unsignedp, OPTAB_WIDEN);
1500
1501   /* For unsigned operands, try widening to an unsigned int.  */
1502   if (temp == 0 && unsignedp)
1503     temp = expand_binop (mode, uoptab, op0, op1, target,
1504                          unsignedp, OPTAB_WIDEN);
1505   if (temp || methods == OPTAB_WIDEN)
1506     return temp;
1507
1508   /* Use the right width lib call if that exists.  */
1509   temp = expand_binop (mode, direct_optab, op0, op1, target, unsignedp, OPTAB_LIB);
1510   if (temp || methods == OPTAB_LIB)
1511     return temp;
1512
1513   /* Must widen and use a lib call, use either signed or unsigned.  */
1514   temp = expand_binop (mode, &wide_soptab, op0, op1, target,
1515                        unsignedp, methods);
1516   if (temp != 0)
1517     return temp;
1518   if (unsignedp)
1519     return expand_binop (mode, uoptab, op0, op1, target,
1520                          unsignedp, methods);
1521   return 0;
1522 }
1523 \f
1524 /* Generate code to perform an operation specified by BINOPTAB
1525    on operands OP0 and OP1, with two results to TARG1 and TARG2.
1526    We assume that the order of the operands for the instruction
1527    is TARG0, OP0, OP1, TARG1, which would fit a pattern like
1528    [(set TARG0 (operate OP0 OP1)) (set TARG1 (operate ...))].
1529
1530    Either TARG0 or TARG1 may be zero, but what that means is that
1531    that result is not actually wanted.  We will generate it into
1532    a dummy pseudo-reg and discard it.  They may not both be zero.
1533
1534    Returns 1 if this operation can be performed; 0 if not.  */
1535
1536 int
1537 expand_twoval_binop (binoptab, op0, op1, targ0, targ1, unsignedp)
1538      optab binoptab;
1539      rtx op0, op1;
1540      rtx targ0, targ1;
1541      int unsignedp;
1542 {
1543   enum machine_mode mode = GET_MODE (targ0 ? targ0 : targ1);
1544   enum mode_class class;
1545   enum machine_mode wider_mode;
1546   rtx entry_last = get_last_insn ();
1547   rtx last;
1548
1549   class = GET_MODE_CLASS (mode);
1550
1551   op0 = protect_from_queue (op0, 0);
1552   op1 = protect_from_queue (op1, 0);
1553
1554   if (flag_force_mem)
1555     {
1556       op0 = force_not_mem (op0);
1557       op1 = force_not_mem (op1);
1558     }
1559
1560   /* If we are inside an appropriately-short loop and one operand is an
1561      expensive constant, force it into a register.  */
1562   if (CONSTANT_P (op0) && preserve_subexpressions_p ()
1563       && rtx_cost (op0, binoptab->code) > 2)
1564     op0 = force_reg (mode, op0);
1565
1566   if (CONSTANT_P (op1) && preserve_subexpressions_p ()
1567       && rtx_cost (op1, binoptab->code) > 2)
1568     op1 = force_reg (mode, op1);
1569
1570   if (targ0)
1571     targ0 = protect_from_queue (targ0, 1);
1572   else
1573     targ0 = gen_reg_rtx (mode);
1574   if (targ1)
1575     targ1 = protect_from_queue (targ1, 1);
1576   else
1577     targ1 = gen_reg_rtx (mode);
1578
1579   /* Record where to go back to if we fail.  */
1580   last = get_last_insn ();
1581
1582   if (binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1583     {
1584       int icode = (int) binoptab->handlers[(int) mode].insn_code;
1585       enum machine_mode mode0 = insn_operand_mode[icode][1];
1586       enum machine_mode mode1 = insn_operand_mode[icode][2];
1587       rtx pat;
1588       rtx xop0 = op0, xop1 = op1;
1589
1590       /* In case this insn wants input operands in modes different from the
1591          result, convert the operands.  */
1592       if (GET_MODE (op0) != VOIDmode && GET_MODE (op0) != mode0)
1593         xop0 = convert_to_mode (mode0, xop0, unsignedp);
1594
1595       if (GET_MODE (op1) != VOIDmode && GET_MODE (op1) != mode1)
1596         xop1 = convert_to_mode (mode1, xop1, unsignedp);
1597
1598       /* Now, if insn doesn't accept these operands, put them into pseudos.  */
1599       if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))
1600         xop0 = copy_to_mode_reg (mode0, xop0);
1601
1602       if (! (*insn_operand_predicate[icode][2]) (xop1, mode1))
1603         xop1 = copy_to_mode_reg (mode1, xop1);
1604
1605       /* We could handle this, but we should always be called with a pseudo
1606          for our targets and all insns should take them as outputs.  */
1607       if (! (*insn_operand_predicate[icode][0]) (targ0, mode)
1608           || ! (*insn_operand_predicate[icode][3]) (targ1, mode))
1609         abort ();
1610         
1611       pat = GEN_FCN (icode) (targ0, xop0, xop1, targ1);
1612       if (pat)
1613         {
1614           emit_insn (pat);
1615           return 1;
1616         }
1617       else
1618         delete_insns_since (last);
1619     }
1620
1621   /* It can't be done in this mode.  Can we do it in a wider mode?  */
1622
1623   if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
1624     {
1625       for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
1626            wider_mode = GET_MODE_WIDER_MODE (wider_mode))
1627         {
1628           if (binoptab->handlers[(int) wider_mode].insn_code
1629               != CODE_FOR_nothing)
1630             {
1631               register rtx t0 = gen_reg_rtx (wider_mode);
1632               register rtx t1 = gen_reg_rtx (wider_mode);
1633
1634               if (expand_twoval_binop (binoptab,
1635                                        convert_modes (wider_mode, mode, op0,
1636                                                       unsignedp),
1637                                        convert_modes (wider_mode, mode, op1,
1638                                                       unsignedp),
1639                                        t0, t1, unsignedp))
1640                 {
1641                   convert_move (targ0, t0, unsignedp);
1642                   convert_move (targ1, t1, unsignedp);
1643                   return 1;
1644                 }
1645               else
1646                 delete_insns_since (last);
1647             }
1648         }
1649     }
1650
1651   delete_insns_since (entry_last);
1652   return 0;
1653 }
1654 \f
1655 /* Generate code to perform an operation specified by UNOPTAB
1656    on operand OP0, with result having machine-mode MODE.
1657
1658    UNSIGNEDP is for the case where we have to widen the operands
1659    to perform the operation.  It says to use zero-extension.
1660
1661    If TARGET is nonzero, the value
1662    is generated there, if it is convenient to do so.
1663    In all cases an rtx is returned for the locus of the value;
1664    this may or may not be TARGET.  */
1665
1666 rtx
1667 expand_unop (mode, unoptab, op0, target, unsignedp)
1668      enum machine_mode mode;
1669      optab unoptab;
1670      rtx op0;
1671      rtx target;
1672      int unsignedp;
1673 {
1674   enum mode_class class;
1675   enum machine_mode wider_mode;
1676   register rtx temp;
1677   rtx last = get_last_insn ();
1678   rtx pat;
1679
1680   class = GET_MODE_CLASS (mode);
1681
1682   op0 = protect_from_queue (op0, 0);
1683
1684   if (flag_force_mem)
1685     {
1686       op0 = force_not_mem (op0);
1687     }
1688
1689   if (target)
1690     target = protect_from_queue (target, 1);
1691
1692   if (unoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1693     {
1694       int icode = (int) unoptab->handlers[(int) mode].insn_code;
1695       enum machine_mode mode0 = insn_operand_mode[icode][1];
1696       rtx xop0 = op0;
1697
1698       if (target)
1699         temp = target;
1700       else
1701         temp = gen_reg_rtx (mode);
1702
1703       if (GET_MODE (xop0) != VOIDmode
1704           && GET_MODE (xop0) != mode0)
1705         xop0 = convert_to_mode (mode0, xop0, unsignedp);
1706
1707       /* Now, if insn doesn't accept our operand, put it into a pseudo.  */
1708
1709       if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))
1710         xop0 = copy_to_mode_reg (mode0, xop0);
1711
1712       if (! (*insn_operand_predicate[icode][0]) (temp, mode))
1713         temp = gen_reg_rtx (mode);
1714
1715       pat = GEN_FCN (icode) (temp, xop0);
1716       if (pat)
1717         {
1718           if (GET_CODE (pat) == SEQUENCE
1719               && ! add_equal_note (pat, temp, unoptab->code, xop0, NULL_RTX))
1720             {
1721               delete_insns_since (last);
1722               return expand_unop (mode, unoptab, op0, NULL_RTX, unsignedp);
1723             }
1724
1725           emit_insn (pat);
1726           
1727           return temp;
1728         }
1729       else
1730         delete_insns_since (last);
1731     }
1732
1733   /* It can't be done in this mode.  Can we open-code it in a wider mode?  */
1734
1735   if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
1736     for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
1737          wider_mode = GET_MODE_WIDER_MODE (wider_mode))
1738       {
1739         if (unoptab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing)
1740           {
1741             rtx xop0 = op0;
1742
1743             /* For certain operations, we need not actually extend
1744                the narrow operand, as long as we will truncate the
1745                results to the same narrowness.  */
1746
1747             xop0 = widen_operand (xop0, wider_mode, mode, unsignedp,
1748                                   (unoptab == neg_optab
1749                                    || unoptab == one_cmpl_optab)
1750                                   && class == MODE_INT);
1751               
1752             temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
1753                                 unsignedp);
1754
1755             if (temp)
1756               {
1757                 if (class != MODE_INT)
1758                   {
1759                     if (target == 0)
1760                       target = gen_reg_rtx (mode);
1761                     convert_move (target, temp, 0);
1762                     return target;
1763                   }
1764                 else
1765                   return gen_lowpart (mode, temp);
1766               }
1767             else
1768               delete_insns_since (last);
1769           }
1770       }
1771
1772   /* These can be done a word at a time.  */
1773   if (unoptab == one_cmpl_optab
1774       && class == MODE_INT
1775       && GET_MODE_SIZE (mode) > UNITS_PER_WORD
1776       && unoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
1777     {
1778       int i;
1779       rtx insns;
1780
1781       if (target == 0 || target == op0)
1782         target = gen_reg_rtx (mode);
1783
1784       start_sequence ();
1785
1786       /* Do the actual arithmetic.  */
1787       for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)
1788         {
1789           rtx target_piece = operand_subword (target, i, 1, mode);
1790           rtx x = expand_unop (word_mode, unoptab,
1791                                operand_subword_force (op0, i, mode),
1792                                target_piece, unsignedp);
1793           if (target_piece != x)
1794             emit_move_insn (target_piece, x);
1795         }
1796
1797       insns = get_insns ();
1798       end_sequence ();
1799
1800       emit_no_conflict_block (insns, target, op0, NULL_RTX,
1801                               gen_rtx (unoptab->code, mode, copy_rtx (op0)));
1802       return target;
1803     }
1804
1805   /* Open-code the complex negation operation.  */
1806   else if (unoptab == neg_optab
1807            && (class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT))
1808     {
1809       rtx target_piece;
1810       rtx x;
1811       rtx seq;
1812
1813       /* Find the correct mode for the real and imaginary parts */
1814       enum machine_mode submode
1815         = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT,
1816                          class == MODE_COMPLEX_INT ? MODE_INT : MODE_FLOAT,
1817                          0);
1818
1819       if (submode == BLKmode)
1820         abort ();
1821
1822       if (target == 0)
1823         target = gen_reg_rtx (mode);
1824       
1825       start_sequence ();
1826
1827       target_piece = gen_imagpart (submode, target);
1828       x = expand_unop (submode, unoptab,
1829                        gen_imagpart (submode, op0),
1830                        target_piece, unsignedp);
1831       if (target_piece != x)
1832         emit_move_insn (target_piece, x);
1833
1834       target_piece = gen_realpart (submode, target);
1835       x = expand_unop (submode, unoptab,
1836                        gen_realpart (submode, op0),
1837                        target_piece, unsignedp);
1838       if (target_piece != x)
1839         emit_move_insn (target_piece, x);
1840
1841       seq = get_insns ();
1842       end_sequence ();
1843
1844       emit_no_conflict_block (seq, target, op0, 0,
1845                               gen_rtx (unoptab->code, mode, copy_rtx (op0)));
1846       return target;
1847     }
1848
1849   /* Now try a library call in this mode.  */
1850   if (unoptab->handlers[(int) mode].libfunc)
1851     {
1852       rtx insns;
1853       rtx funexp = unoptab->handlers[(int) mode].libfunc;
1854       rtx value;
1855
1856       start_sequence ();
1857
1858       /* Pass 1 for NO_QUEUE so we don't lose any increments
1859          if the libcall is cse'd or moved.  */
1860       value = emit_library_call_value (unoptab->handlers[(int) mode].libfunc,
1861                                        NULL_RTX, 1, mode, 1, op0, mode);
1862       insns = get_insns ();
1863       end_sequence ();
1864
1865       target = gen_reg_rtx (mode);
1866       emit_libcall_block (insns, target, value,
1867                           gen_rtx (unoptab->code, mode, op0));
1868
1869       return target;
1870     }
1871
1872   /* It can't be done in this mode.  Can we do it in a wider mode?  */
1873
1874   if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
1875     {
1876       for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
1877            wider_mode = GET_MODE_WIDER_MODE (wider_mode))
1878         {
1879           if ((unoptab->handlers[(int) wider_mode].insn_code
1880                != CODE_FOR_nothing)
1881               || unoptab->handlers[(int) wider_mode].libfunc)
1882             {
1883               rtx xop0 = op0;
1884
1885               /* For certain operations, we need not actually extend
1886                  the narrow operand, as long as we will truncate the
1887                  results to the same narrowness.  */
1888
1889               xop0 = widen_operand (xop0, wider_mode, mode, unsignedp,
1890                                     (unoptab == neg_optab
1891                                      || unoptab == one_cmpl_optab)
1892                                     && class == MODE_INT);
1893               
1894               temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
1895                                   unsignedp);
1896
1897               if (temp)
1898                 {
1899                   if (class != MODE_INT)
1900                     {
1901                       if (target == 0)
1902                         target = gen_reg_rtx (mode);
1903                       convert_move (target, temp, 0);
1904                       return target;
1905                     }
1906                   else
1907                     return gen_lowpart (mode, temp);
1908                 }
1909               else
1910                 delete_insns_since (last);
1911             }
1912         }
1913     }
1914
1915   return 0;
1916 }
1917 \f
1918 /* Emit code to compute the absolute value of OP0, with result to
1919    TARGET if convenient.  (TARGET may be 0.)  The return value says
1920    where the result actually is to be found.
1921
1922    MODE is the mode of the operand; the mode of the result is
1923    different but can be deduced from MODE.
1924
1925    UNSIGNEDP is relevant for complex integer modes.  */
1926
1927 rtx
1928 expand_complex_abs (mode, op0, target, unsignedp)
1929      enum machine_mode mode;
1930      rtx op0;
1931      rtx target;
1932      int unsignedp;
1933 {
1934   enum mode_class class = GET_MODE_CLASS (mode);
1935   enum machine_mode wider_mode;
1936   register rtx temp;
1937   rtx entry_last = get_last_insn ();
1938   rtx last;
1939   rtx pat;
1940
1941   /* Find the correct mode for the real and imaginary parts.  */
1942   enum machine_mode submode
1943     = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT,
1944                      class == MODE_COMPLEX_INT ? MODE_INT : MODE_FLOAT,
1945                      0);
1946
1947   if (submode == BLKmode)
1948     abort ();
1949
1950   op0 = protect_from_queue (op0, 0);
1951
1952   if (flag_force_mem)
1953     {
1954       op0 = force_not_mem (op0);
1955     }
1956
1957   last = get_last_insn ();
1958
1959   if (target)
1960     target = protect_from_queue (target, 1);
1961
1962   if (abs_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1963     {
1964       int icode = (int) abs_optab->handlers[(int) mode].insn_code;
1965       enum machine_mode mode0 = insn_operand_mode[icode][1];
1966       rtx xop0 = op0;
1967
1968       if (target)
1969         temp = target;
1970       else
1971         temp = gen_reg_rtx (submode);
1972
1973       if (GET_MODE (xop0) != VOIDmode
1974           && GET_MODE (xop0) != mode0)
1975         xop0 = convert_to_mode (mode0, xop0, unsignedp);
1976
1977       /* Now, if insn doesn't accept our operand, put it into a pseudo.  */
1978
1979       if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))
1980         xop0 = copy_to_mode_reg (mode0, xop0);
1981
1982       if (! (*insn_operand_predicate[icode][0]) (temp, submode))
1983         temp = gen_reg_rtx (submode);
1984
1985       pat = GEN_FCN (icode) (temp, xop0);
1986       if (pat)
1987         {
1988           if (GET_CODE (pat) == SEQUENCE
1989               && ! add_equal_note (pat, temp, abs_optab->code, xop0, NULL_RTX))
1990             {
1991               delete_insns_since (last);
1992               return expand_unop (mode, abs_optab, op0, NULL_RTX, unsignedp);
1993             }
1994
1995           emit_insn (pat);
1996           
1997           return temp;
1998         }
1999       else
2000         delete_insns_since (last);
2001     }
2002
2003   /* It can't be done in this mode.  Can we open-code it in a wider mode?  */
2004
2005   for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
2006        wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2007     {
2008       if (abs_optab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing)
2009         {
2010           rtx xop0 = op0;
2011
2012           xop0 = convert_modes (wider_mode, mode, xop0, unsignedp);
2013           temp = expand_complex_abs (wider_mode, xop0, NULL_RTX, unsignedp);
2014
2015           if (temp)
2016             {
2017               if (class != MODE_COMPLEX_INT)
2018                 {
2019                   if (target == 0)
2020                     target = gen_reg_rtx (submode);
2021                   convert_move (target, temp, 0);
2022                   return target;
2023                 }
2024               else
2025                 return gen_lowpart (submode, temp);
2026             }
2027           else
2028             delete_insns_since (last);
2029         }
2030     }
2031
2032   /* Open-code the complex absolute-value operation
2033      if we can open-code sqrt.  Otherwise it's not worth while.  */
2034   if (sqrt_optab->handlers[(int) submode].insn_code != CODE_FOR_nothing)
2035     {
2036       rtx real, imag, total;
2037
2038       real = gen_realpart (submode, op0);
2039       imag = gen_imagpart (submode, op0);
2040
2041       /* Square both parts.  */
2042       real = expand_mult (submode, real, real, NULL_RTX, 0);
2043       imag = expand_mult (submode, imag, imag, NULL_RTX, 0);
2044
2045       /* Sum the parts.  */
2046       total = expand_binop (submode, add_optab, real, imag, 0,
2047                             0, OPTAB_LIB_WIDEN);
2048
2049       /* Get sqrt in TARGET.  Set TARGET to where the result is.  */
2050       target = expand_unop (submode, sqrt_optab, total, target, 0);
2051       if (target == 0)
2052         delete_insns_since (last);
2053       else
2054         return target;
2055     }
2056
2057   /* Now try a library call in this mode.  */
2058   if (abs_optab->handlers[(int) mode].libfunc)
2059     {
2060       rtx insns;
2061       rtx funexp = abs_optab->handlers[(int) mode].libfunc;
2062       rtx value;
2063
2064       start_sequence ();
2065
2066       /* Pass 1 for NO_QUEUE so we don't lose any increments
2067          if the libcall is cse'd or moved.  */
2068       value = emit_library_call_value (abs_optab->handlers[(int) mode].libfunc,
2069                                        NULL_RTX, 1, submode, 1, op0, mode);
2070       insns = get_insns ();
2071       end_sequence ();
2072
2073       target = gen_reg_rtx (submode);
2074       emit_libcall_block (insns, target, value,
2075                           gen_rtx (abs_optab->code, mode, op0));
2076
2077       return target;
2078     }
2079
2080   /* It can't be done in this mode.  Can we do it in a wider mode?  */
2081
2082   for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
2083        wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2084     {
2085       if ((abs_optab->handlers[(int) wider_mode].insn_code
2086            != CODE_FOR_nothing)
2087           || abs_optab->handlers[(int) wider_mode].libfunc)
2088         {
2089           rtx xop0 = op0;
2090
2091           xop0 = convert_modes (wider_mode, mode, xop0, unsignedp);
2092
2093           temp = expand_complex_abs (wider_mode, xop0, NULL_RTX, unsignedp);
2094
2095           if (temp)
2096             {
2097               if (class != MODE_COMPLEX_INT)
2098                 {
2099                   if (target == 0)
2100                     target = gen_reg_rtx (submode);
2101                   convert_move (target, temp, 0);
2102                   return target;
2103                 }
2104               else
2105                 return gen_lowpart (submode, temp);
2106             }
2107           else
2108             delete_insns_since (last);
2109         }
2110     }
2111
2112   delete_insns_since (entry_last);
2113   return 0;
2114 }
2115 \f
2116 /* Generate an instruction whose insn-code is INSN_CODE,
2117    with two operands: an output TARGET and an input OP0.
2118    TARGET *must* be nonzero, and the output is always stored there.
2119    CODE is an rtx code such that (CODE OP0) is an rtx that describes
2120    the value that is stored into TARGET.  */
2121
2122 void
2123 emit_unop_insn (icode, target, op0, code)
2124      int icode;
2125      rtx target;
2126      rtx op0;
2127      enum rtx_code code;
2128 {
2129   register rtx temp;
2130   enum machine_mode mode0 = insn_operand_mode[icode][1];
2131   rtx pat;
2132
2133   temp = target = protect_from_queue (target, 1);
2134
2135   op0 = protect_from_queue (op0, 0);
2136
2137   if (flag_force_mem)
2138     op0 = force_not_mem (op0);
2139
2140   /* Now, if insn does not accept our operands, put them into pseudos.  */
2141
2142   if (! (*insn_operand_predicate[icode][1]) (op0, mode0))
2143     op0 = copy_to_mode_reg (mode0, op0);
2144
2145   if (! (*insn_operand_predicate[icode][0]) (temp, GET_MODE (temp))
2146       || (flag_force_mem && GET_CODE (temp) == MEM))
2147     temp = gen_reg_rtx (GET_MODE (temp));
2148
2149   pat = GEN_FCN (icode) (temp, op0);
2150
2151   if (GET_CODE (pat) == SEQUENCE && code != UNKNOWN)
2152     add_equal_note (pat, temp, code, op0, NULL_RTX);
2153   
2154   emit_insn (pat);
2155
2156   if (temp != target)
2157     emit_move_insn (target, temp);
2158 }
2159 \f
2160 /* Emit code to perform a series of operations on a multi-word quantity, one
2161    word at a time.
2162
2163    Such a block is preceded by a CLOBBER of the output, consists of multiple
2164    insns, each setting one word of the output, and followed by a SET copying
2165    the output to itself.
2166
2167    Each of the insns setting words of the output receives a REG_NO_CONFLICT
2168    note indicating that it doesn't conflict with the (also multi-word)
2169    inputs.  The entire block is surrounded by REG_LIBCALL and REG_RETVAL
2170    notes.
2171
2172    INSNS is a block of code generated to perform the operation, not including
2173    the CLOBBER and final copy.  All insns that compute intermediate values
2174    are first emitted, followed by the block as described above.  Only
2175    INSNs are allowed in the block; no library calls or jumps may be
2176    present.
2177
2178    TARGET, OP0, and OP1 are the output and inputs of the operations,
2179    respectively.  OP1 may be zero for a unary operation.
2180
2181    EQUIV, if non-zero, is an expression to be placed into a REG_EQUAL note
2182    on the last insn.
2183
2184    If TARGET is not a register, INSNS is simply emitted with no special
2185    processing.
2186
2187    The final insn emitted is returned.  */
2188
2189 rtx
2190 emit_no_conflict_block (insns, target, op0, op1, equiv)
2191      rtx insns;
2192      rtx target;
2193      rtx op0, op1;
2194      rtx equiv;
2195 {
2196   rtx prev, next, first, last, insn;
2197
2198   if (GET_CODE (target) != REG || reload_in_progress)
2199     return emit_insns (insns);
2200
2201   /* First emit all insns that do not store into words of the output and remove
2202      these from the list.  */
2203   for (insn = insns; insn; insn = next)
2204     {
2205       rtx set = 0;
2206       int i;
2207
2208       next = NEXT_INSN (insn);
2209
2210       if (GET_CODE (insn) != INSN)
2211         abort ();
2212
2213       if (GET_CODE (PATTERN (insn)) == SET)
2214         set = PATTERN (insn);
2215       else if (GET_CODE (PATTERN (insn)) == PARALLEL)
2216         {
2217           for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
2218             if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET)
2219               {
2220                 set = XVECEXP (PATTERN (insn), 0, i);
2221                 break;
2222               }
2223         }
2224
2225       if (set == 0)
2226         abort ();
2227
2228       if (! reg_overlap_mentioned_p (target, SET_DEST (set)))
2229         {
2230           if (PREV_INSN (insn))
2231             NEXT_INSN (PREV_INSN (insn)) = next;
2232           else
2233             insns = next;
2234
2235           if (next)
2236             PREV_INSN (next) = PREV_INSN (insn);
2237
2238           add_insn (insn);
2239         }
2240     }
2241
2242   prev = get_last_insn ();
2243
2244   /* Now write the CLOBBER of the output, followed by the setting of each
2245      of the words, followed by the final copy.  */
2246   if (target != op0 && target != op1)
2247     emit_insn (gen_rtx (CLOBBER, VOIDmode, target));
2248
2249   for (insn = insns; insn; insn = next)
2250     {
2251       next = NEXT_INSN (insn);
2252       add_insn (insn);
2253
2254       if (op1 && GET_CODE (op1) == REG)
2255         REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_NO_CONFLICT, op1,
2256                                     REG_NOTES (insn));
2257
2258       if (op0 && GET_CODE (op0) == REG)
2259         REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_NO_CONFLICT, op0,
2260                                     REG_NOTES (insn));
2261     }
2262
2263   if (mov_optab->handlers[(int) GET_MODE (target)].insn_code
2264       != CODE_FOR_nothing)
2265     {
2266       last = emit_move_insn (target, target);
2267       if (equiv)
2268         REG_NOTES (last)
2269           = gen_rtx (EXPR_LIST, REG_EQUAL, equiv, REG_NOTES (last));
2270     }
2271   else
2272     last = get_last_insn ();
2273
2274   if (prev == 0)
2275     first = get_insns ();
2276   else
2277     first = NEXT_INSN (prev);
2278
2279   /* Encapsulate the block so it gets manipulated as a unit.  */
2280   REG_NOTES (first) = gen_rtx (INSN_LIST, REG_LIBCALL, last,
2281                                REG_NOTES (first));
2282   REG_NOTES (last) = gen_rtx (INSN_LIST, REG_RETVAL, first, REG_NOTES (last));
2283
2284   return last;
2285 }
2286 \f
2287 /* Emit code to make a call to a constant function or a library call.
2288
2289    INSNS is a list containing all insns emitted in the call.
2290    These insns leave the result in RESULT.  Our block is to copy RESULT
2291    to TARGET, which is logically equivalent to EQUIV.
2292
2293    We first emit any insns that set a pseudo on the assumption that these are
2294    loading constants into registers; doing so allows them to be safely cse'ed
2295    between blocks.  Then we emit all the other insns in the block, followed by
2296    an insn to move RESULT to TARGET.  This last insn will have a REQ_EQUAL
2297    note with an operand of EQUIV.
2298
2299    Moving assignments to pseudos outside of the block is done to improve
2300    the generated code, but is not required to generate correct code,
2301    hence being unable to move an assignment is not grounds for not making
2302    a libcall block.  There are two reasons why it is safe to leave these
2303    insns inside the block: First, we know that these pseudos cannot be
2304    used in generated RTL outside the block since they are created for
2305    temporary purposes within the block.  Second, CSE will not record the
2306    values of anything set inside a libcall block, so we know they must
2307    be dead at the end of the block.
2308
2309    Except for the first group of insns (the ones setting pseudos), the
2310    block is delimited by REG_RETVAL and REG_LIBCALL notes.  */
2311
2312 void
2313 emit_libcall_block (insns, target, result, equiv)
2314      rtx insns;
2315      rtx target;
2316      rtx result;
2317      rtx equiv;
2318 {
2319   rtx prev, next, first, last, insn;
2320
2321   /* First emit all insns that set pseudos.  Remove them from the list as
2322      we go.  Avoid insns that set pseudos which were referenced in previous
2323      insns.  These can be generated by move_by_pieces, for example,
2324      to update an address.  Similarly, avoid insns that reference things
2325      set in previous insns.  */
2326
2327   for (insn = insns; insn; insn = next)
2328     {
2329       rtx set = single_set (insn);
2330
2331       next = NEXT_INSN (insn);
2332
2333       if (set != 0 && GET_CODE (SET_DEST (set)) == REG
2334           && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER
2335           && (insn == insns
2336               || (! reg_mentioned_p (SET_DEST (set), PATTERN (insns))
2337                   && ! reg_used_between_p (SET_DEST (set), insns, insn)
2338                   && ! modified_in_p (SET_SRC (set), insns)
2339                   && ! modified_between_p (SET_SRC (set), insns, insn))))
2340         {
2341           if (PREV_INSN (insn))
2342             NEXT_INSN (PREV_INSN (insn)) = next;
2343           else
2344             insns = next;
2345
2346           if (next)
2347             PREV_INSN (next) = PREV_INSN (insn);
2348
2349           add_insn (insn);
2350         }
2351     }
2352
2353   prev = get_last_insn ();
2354
2355   /* Write the remaining insns followed by the final copy.  */
2356
2357   for (insn = insns; insn; insn = next)
2358     {
2359       next = NEXT_INSN (insn);
2360
2361       add_insn (insn);
2362     }
2363
2364   last = emit_move_insn (target, result);
2365   REG_NOTES (last) = gen_rtx (EXPR_LIST,
2366                               REG_EQUAL, copy_rtx (equiv), REG_NOTES (last));
2367
2368   if (prev == 0)
2369     first = get_insns ();
2370   else
2371     first = NEXT_INSN (prev);
2372
2373   /* Encapsulate the block so it gets manipulated as a unit.  */
2374   REG_NOTES (first) = gen_rtx (INSN_LIST, REG_LIBCALL, last,
2375                                REG_NOTES (first));
2376   REG_NOTES (last) = gen_rtx (INSN_LIST, REG_RETVAL, first, REG_NOTES (last));
2377 }
2378 \f
2379 /* Generate code to store zero in X.  */
2380
2381 void
2382 emit_clr_insn (x)
2383      rtx x;
2384 {
2385   emit_move_insn (x, const0_rtx);
2386 }
2387
2388 /* Generate code to store 1 in X
2389    assuming it contains zero beforehand.  */
2390
2391 void
2392 emit_0_to_1_insn (x)
2393      rtx x;
2394 {
2395   emit_move_insn (x, const1_rtx);
2396 }
2397
2398 /* Generate code to compare X with Y
2399    so that the condition codes are set.
2400
2401    MODE is the mode of the inputs (in case they are const_int).
2402    UNSIGNEDP nonzero says that X and Y are unsigned;
2403    this matters if they need to be widened.
2404
2405    If they have mode BLKmode, then SIZE specifies the size of both X and Y,
2406    and ALIGN specifies the known shared alignment of X and Y.
2407
2408    COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).
2409    It is ignored for fixed-point and block comparisons;
2410    it is used only for floating-point comparisons.  */
2411
2412 void
2413 emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align)
2414      rtx x, y;
2415      enum rtx_code comparison;
2416      rtx size;
2417      enum machine_mode mode;
2418      int unsignedp;
2419      int align;
2420 {
2421   enum mode_class class;
2422   enum machine_mode wider_mode;
2423
2424   class = GET_MODE_CLASS (mode);
2425
2426   /* They could both be VOIDmode if both args are immediate constants,
2427      but we should fold that at an earlier stage.
2428      With no special code here, this will call abort,
2429      reminding the programmer to implement such folding.  */
2430
2431   if (mode != BLKmode && flag_force_mem)
2432     {
2433       x = force_not_mem (x);
2434       y = force_not_mem (y);
2435     }
2436
2437   /* If we are inside an appropriately-short loop and one operand is an
2438      expensive constant, force it into a register.  */
2439   if (CONSTANT_P (x) && preserve_subexpressions_p () && rtx_cost (x, COMPARE) > 2)
2440     x = force_reg (mode, x);
2441
2442   if (CONSTANT_P (y) && preserve_subexpressions_p () && rtx_cost (y, COMPARE) > 2)
2443     y = force_reg (mode, y);
2444
2445   /* Don't let both operands fail to indicate the mode.  */
2446   if (GET_MODE (x) == VOIDmode && GET_MODE (y) == VOIDmode)
2447     x = force_reg (mode, x);
2448
2449   /* Handle all BLKmode compares.  */
2450
2451   if (mode == BLKmode)
2452     {
2453       emit_queue ();
2454       x = protect_from_queue (x, 0);
2455       y = protect_from_queue (y, 0);
2456
2457       if (size == 0)
2458         abort ();
2459 #ifdef HAVE_cmpstrqi
2460       if (HAVE_cmpstrqi
2461           && GET_CODE (size) == CONST_INT
2462           && INTVAL (size) < (1 << GET_MODE_BITSIZE (QImode)))
2463         {
2464           enum machine_mode result_mode
2465             = insn_operand_mode[(int) CODE_FOR_cmpstrqi][0];
2466           rtx result = gen_reg_rtx (result_mode);
2467           emit_insn (gen_cmpstrqi (result, x, y, size, GEN_INT (align)));
2468           emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX,
2469                          result_mode, 0, 0);
2470         }
2471       else
2472 #endif
2473 #ifdef HAVE_cmpstrhi
2474       if (HAVE_cmpstrhi
2475           && GET_CODE (size) == CONST_INT
2476           && INTVAL (size) < (1 << GET_MODE_BITSIZE (HImode)))
2477         {
2478           enum machine_mode result_mode
2479             = insn_operand_mode[(int) CODE_FOR_cmpstrhi][0];
2480           rtx result = gen_reg_rtx (result_mode);
2481           emit_insn (gen_cmpstrhi (result, x, y, size, GEN_INT (align)));
2482           emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX,
2483                          result_mode, 0, 0);
2484         }
2485       else
2486 #endif
2487 #ifdef HAVE_cmpstrsi
2488       if (HAVE_cmpstrsi)
2489         {
2490           enum machine_mode result_mode
2491             = insn_operand_mode[(int) CODE_FOR_cmpstrsi][0];
2492           rtx result = gen_reg_rtx (result_mode);
2493           size = protect_from_queue (size, 0);
2494           emit_insn (gen_cmpstrsi (result, x, y,
2495                                    convert_to_mode (SImode, size, 1),
2496                                    GEN_INT (align)));
2497           emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX,
2498                          result_mode, 0, 0);
2499         }
2500       else
2501 #endif
2502         {
2503 #ifdef TARGET_MEM_FUNCTIONS
2504           emit_library_call (memcmp_libfunc, 0,
2505                              TYPE_MODE (integer_type_node), 3,
2506                              XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
2507                              size, Pmode);
2508 #else
2509           emit_library_call (bcmp_libfunc, 0,
2510                              TYPE_MODE (integer_type_node), 3,
2511                              XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
2512                              size, Pmode);
2513 #endif
2514           emit_cmp_insn (hard_libcall_value (TYPE_MODE (integer_type_node)),
2515                          const0_rtx, comparison, NULL_RTX,
2516                          TYPE_MODE (integer_type_node), 0, 0);
2517         }
2518       return;
2519     }
2520
2521   /* Handle some compares against zero.  */
2522
2523   if (y == CONST0_RTX (mode)
2524       && tst_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
2525     {
2526       int icode = (int) tst_optab->handlers[(int) mode].insn_code;
2527
2528       emit_queue ();
2529       x = protect_from_queue (x, 0);
2530       y = protect_from_queue (y, 0);
2531
2532       /* Now, if insn does accept these operands, put them into pseudos.  */
2533       if (! (*insn_operand_predicate[icode][0])
2534           (x, insn_operand_mode[icode][0]))
2535         x = copy_to_mode_reg (insn_operand_mode[icode][0], x);
2536
2537       emit_insn (GEN_FCN (icode) (x));
2538       return;
2539     }
2540
2541   /* Handle compares for which there is a directly suitable insn.  */
2542
2543   if (cmp_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
2544     {
2545       int icode = (int) cmp_optab->handlers[(int) mode].insn_code;
2546
2547       emit_queue ();
2548       x = protect_from_queue (x, 0);
2549       y = protect_from_queue (y, 0);
2550
2551       /* Now, if insn doesn't accept these operands, put them into pseudos.  */
2552       if (! (*insn_operand_predicate[icode][0])
2553           (x, insn_operand_mode[icode][0]))
2554         x = copy_to_mode_reg (insn_operand_mode[icode][0], x);
2555
2556       if (! (*insn_operand_predicate[icode][1])
2557           (y, insn_operand_mode[icode][1]))
2558         y = copy_to_mode_reg (insn_operand_mode[icode][1], y);
2559
2560       emit_insn (GEN_FCN (icode) (x, y));
2561       return;
2562     }
2563
2564   /* Try widening if we can find a direct insn that way.  */
2565
2566   if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
2567     {
2568       for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
2569            wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2570         {
2571           if (cmp_optab->handlers[(int) wider_mode].insn_code
2572               != CODE_FOR_nothing)
2573             {
2574               x = protect_from_queue (x, 0);
2575               y = protect_from_queue (y, 0);
2576               x = convert_modes (wider_mode, mode, x, unsignedp);
2577               y = convert_modes (wider_mode, mode, y, unsignedp);
2578               emit_cmp_insn (x, y, comparison, NULL_RTX,
2579                              wider_mode, unsignedp, align);
2580               return;
2581             }
2582         }
2583     }
2584
2585   /* Handle a lib call just for the mode we are using.  */
2586
2587   if (cmp_optab->handlers[(int) mode].libfunc
2588       && class != MODE_FLOAT)
2589     {
2590       rtx libfunc = cmp_optab->handlers[(int) mode].libfunc;
2591       /* If we want unsigned, and this mode has a distinct unsigned
2592          comparison routine, use that.  */
2593       if (unsignedp && ucmp_optab->handlers[(int) mode].libfunc)
2594         libfunc = ucmp_optab->handlers[(int) mode].libfunc;
2595
2596       emit_library_call (libfunc, 1,
2597                          word_mode, 2, x, mode, y, mode);
2598
2599       /* Integer comparison returns a result that must be compared against 1,
2600          so that even if we do an unsigned compare afterward,
2601          there is still a value that can represent the result "less than".  */
2602
2603       emit_cmp_insn (hard_libcall_value (word_mode), const1_rtx,
2604                      comparison, NULL_RTX, word_mode, unsignedp, 0);
2605       return;
2606     }
2607
2608   if (class == MODE_FLOAT)
2609     emit_float_lib_cmp (x, y, comparison);
2610
2611   else
2612     abort ();
2613 }
2614
2615 /* Nonzero if a compare of mode MODE can be done straightforwardly
2616    (without splitting it into pieces).  */
2617
2618 int
2619 can_compare_p (mode)
2620      enum machine_mode mode;
2621 {
2622   do
2623     {
2624       if (cmp_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)
2625         return 1;
2626       mode = GET_MODE_WIDER_MODE (mode);
2627     } while (mode != VOIDmode);
2628
2629   return 0;
2630 }
2631 \f
2632 /* Emit a library call comparison between floating point X and Y.
2633    COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).  */
2634
2635 void
2636 emit_float_lib_cmp (x, y, comparison)
2637      rtx x, y;
2638      enum rtx_code comparison;
2639 {
2640   enum machine_mode mode = GET_MODE (x);
2641   rtx libfunc = 0;
2642
2643   if (mode == SFmode)
2644     switch (comparison)
2645       {
2646       case EQ:
2647         libfunc = eqsf2_libfunc;
2648         break;
2649
2650       case NE:
2651         libfunc = nesf2_libfunc;
2652         break;
2653
2654       case GT:
2655         libfunc = gtsf2_libfunc;
2656         break;
2657
2658       case GE:
2659         libfunc = gesf2_libfunc;
2660         break;
2661
2662       case LT:
2663         libfunc = ltsf2_libfunc;
2664         break;
2665
2666       case LE:
2667         libfunc = lesf2_libfunc;
2668         break;
2669       }
2670   else if (mode == DFmode)
2671     switch (comparison)
2672       {
2673       case EQ:
2674         libfunc = eqdf2_libfunc;
2675         break;
2676
2677       case NE:
2678         libfunc = nedf2_libfunc;
2679         break;
2680
2681       case GT:
2682         libfunc = gtdf2_libfunc;
2683         break;
2684
2685       case GE:
2686         libfunc = gedf2_libfunc;
2687         break;
2688
2689       case LT:
2690         libfunc = ltdf2_libfunc;
2691         break;
2692
2693       case LE:
2694         libfunc = ledf2_libfunc;
2695         break;
2696       }
2697   else if (mode == XFmode)
2698     switch (comparison)
2699       {
2700       case EQ:
2701         libfunc = eqxf2_libfunc;
2702         break;
2703
2704       case NE:
2705         libfunc = nexf2_libfunc;
2706         break;
2707
2708       case GT:
2709         libfunc = gtxf2_libfunc;
2710         break;
2711
2712       case GE:
2713         libfunc = gexf2_libfunc;
2714         break;
2715
2716       case LT:
2717         libfunc = ltxf2_libfunc;
2718         break;
2719
2720       case LE:
2721         libfunc = lexf2_libfunc;
2722         break;
2723       }
2724   else if (mode == TFmode)
2725     switch (comparison)
2726       {
2727       case EQ:
2728         libfunc = eqtf2_libfunc;
2729         break;
2730
2731       case NE:
2732         libfunc = netf2_libfunc;
2733         break;
2734
2735       case GT:
2736         libfunc = gttf2_libfunc;
2737         break;
2738
2739       case GE:
2740         libfunc = getf2_libfunc;
2741         break;
2742
2743       case LT:
2744         libfunc = lttf2_libfunc;
2745         break;
2746
2747       case LE:
2748         libfunc = letf2_libfunc;
2749         break;
2750       }
2751   else
2752     {
2753       enum machine_mode wider_mode;
2754
2755       for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
2756            wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2757         {
2758           if ((cmp_optab->handlers[(int) wider_mode].insn_code
2759                != CODE_FOR_nothing)
2760               || (cmp_optab->handlers[(int) wider_mode].libfunc != 0))
2761             {
2762               x = protect_from_queue (x, 0);
2763               y = protect_from_queue (y, 0);
2764               x = convert_to_mode (wider_mode, x, 0);
2765               y = convert_to_mode (wider_mode, y, 0);
2766               emit_float_lib_cmp (x, y, comparison);
2767               return;
2768             }
2769         }
2770       abort ();
2771     }
2772
2773   if (libfunc == 0)
2774     abort ();
2775
2776   emit_library_call (libfunc, 1,
2777                      word_mode, 2, x, mode, y, mode);
2778
2779   emit_cmp_insn (hard_libcall_value (word_mode), const0_rtx, comparison,
2780                  NULL_RTX, word_mode, 0, 0);
2781 }
2782 \f
2783 /* Generate code to indirectly jump to a location given in the rtx LOC.  */
2784
2785 void
2786 emit_indirect_jump (loc)
2787      rtx loc;
2788 {
2789   if (! ((*insn_operand_predicate[(int)CODE_FOR_indirect_jump][0])
2790          (loc, Pmode)))
2791     loc = copy_to_mode_reg (Pmode, loc);
2792
2793   emit_jump_insn (gen_indirect_jump (loc));
2794   emit_barrier ();
2795 }
2796 \f
2797 /* These three functions generate an insn body and return it
2798    rather than emitting the insn.
2799
2800    They do not protect from queued increments,
2801    because they may be used 1) in protect_from_queue itself
2802    and 2) in other passes where there is no queue.  */
2803
2804 /* Generate and return an insn body to add Y to X.  */
2805
2806 rtx
2807 gen_add2_insn (x, y)
2808      rtx x, y;
2809 {
2810   int icode = (int) add_optab->handlers[(int) GET_MODE (x)].insn_code; 
2811
2812   if (! (*insn_operand_predicate[icode][0]) (x, insn_operand_mode[icode][0])
2813       || ! (*insn_operand_predicate[icode][1]) (x, insn_operand_mode[icode][1])
2814       || ! (*insn_operand_predicate[icode][2]) (y, insn_operand_mode[icode][2]))
2815     abort ();
2816
2817   return (GEN_FCN (icode) (x, x, y));
2818 }
2819
2820 int
2821 have_add2_insn (mode)
2822      enum machine_mode mode;
2823 {
2824   return add_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing;
2825 }
2826
2827 /* Generate and return an insn body to subtract Y from X.  */
2828
2829 rtx
2830 gen_sub2_insn (x, y)
2831      rtx x, y;
2832 {
2833   int icode = (int) sub_optab->handlers[(int) GET_MODE (x)].insn_code; 
2834
2835   if (! (*insn_operand_predicate[icode][0]) (x, insn_operand_mode[icode][0])
2836       || ! (*insn_operand_predicate[icode][1]) (x, insn_operand_mode[icode][1])
2837       || ! (*insn_operand_predicate[icode][2]) (y, insn_operand_mode[icode][2]))
2838     abort ();
2839
2840   return (GEN_FCN (icode) (x, x, y));
2841 }
2842
2843 int
2844 have_sub2_insn (mode)
2845      enum machine_mode mode;
2846 {
2847   return sub_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing;
2848 }
2849
2850 /* Generate the body of an instruction to copy Y into X.
2851    It may be a SEQUENCE, if one insn isn't enough.  */
2852
2853 rtx
2854 gen_move_insn (x, y)
2855      rtx x, y;
2856 {
2857   register enum machine_mode mode = GET_MODE (x);
2858   enum insn_code insn_code;
2859   rtx seq;
2860
2861   if (mode == VOIDmode)
2862     mode = GET_MODE (y); 
2863
2864   insn_code = mov_optab->handlers[(int) mode].insn_code;
2865
2866   /* Handle MODE_CC modes:  If we don't have a special move insn for this mode,
2867      find a mode to do it in.  If we have a movcc, use it.  Otherwise,
2868      find the MODE_INT mode of the same width.  */
2869
2870   if (GET_MODE_CLASS (mode) == MODE_CC && insn_code == CODE_FOR_nothing)
2871     {
2872       enum machine_mode tmode = VOIDmode;
2873       rtx x1 = x, y1 = y;
2874
2875       if (mode != CCmode
2876           && mov_optab->handlers[(int) CCmode].insn_code != CODE_FOR_nothing)
2877         tmode = CCmode;
2878       else
2879         for (tmode = QImode; tmode != VOIDmode;
2880              tmode = GET_MODE_WIDER_MODE (tmode))
2881           if (GET_MODE_SIZE (tmode) == GET_MODE_SIZE (mode))
2882             break;
2883
2884       if (tmode == VOIDmode)
2885         abort ();
2886
2887       /* Get X and Y in TMODE.  We can't use gen_lowpart here because it
2888          may call change_address which is not appropriate if we were
2889          called when a reload was in progress.  We don't have to worry
2890          about changing the address since the size in bytes is supposed to
2891          be the same.  Copy the MEM to change the mode and move any
2892          substitutions from the old MEM to the new one.  */
2893
2894       if (reload_in_progress)
2895         {
2896           x = gen_lowpart_common (tmode, x1);
2897           if (x == 0 && GET_CODE (x1) == MEM)
2898             {
2899               x = gen_rtx (MEM, tmode, XEXP (x1, 0));
2900               RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (x1);
2901               MEM_IN_STRUCT_P (x) = MEM_IN_STRUCT_P (x1);
2902               MEM_VOLATILE_P (x) = MEM_VOLATILE_P (x1);
2903               copy_replacements (x1, x);
2904             }
2905
2906           y = gen_lowpart_common (tmode, y1);
2907           if (y == 0 && GET_CODE (y1) == MEM)
2908             {
2909               y = gen_rtx (MEM, tmode, XEXP (y1, 0));
2910               RTX_UNCHANGING_P (y) = RTX_UNCHANGING_P (y1);
2911               MEM_IN_STRUCT_P (y) = MEM_IN_STRUCT_P (y1);
2912               MEM_VOLATILE_P (y) = MEM_VOLATILE_P (y1);
2913               copy_replacements (y1, y);
2914             }
2915         }
2916       else
2917         {
2918           x = gen_lowpart (tmode, x);
2919           y = gen_lowpart (tmode, y);
2920         }
2921           
2922       insn_code = mov_optab->handlers[(int) tmode].insn_code;
2923       return (GEN_FCN (insn_code) (x, y));
2924     }
2925
2926   start_sequence ();
2927   emit_move_insn_1 (x, y);
2928   seq = gen_sequence ();
2929   end_sequence ();
2930   return seq;
2931 }
2932 \f
2933 /* Return the insn code used to extend FROM_MODE to TO_MODE.
2934    UNSIGNEDP specifies zero-extension instead of sign-extension.  If
2935    no such operation exists, CODE_FOR_nothing will be returned.  */
2936
2937 enum insn_code
2938 can_extend_p (to_mode, from_mode, unsignedp)
2939      enum machine_mode to_mode, from_mode;
2940      int unsignedp;
2941 {
2942   return extendtab[(int) to_mode][(int) from_mode][unsignedp];
2943 }
2944
2945 /* Generate the body of an insn to extend Y (with mode MFROM)
2946    into X (with mode MTO).  Do zero-extension if UNSIGNEDP is nonzero.  */
2947
2948 rtx
2949 gen_extend_insn (x, y, mto, mfrom, unsignedp)
2950      rtx x, y;
2951      enum machine_mode mto, mfrom;
2952      int unsignedp;
2953 {
2954   return (GEN_FCN (extendtab[(int) mto][(int) mfrom][unsignedp]) (x, y));
2955 }
2956 \f
2957 /* can_fix_p and can_float_p say whether the target machine
2958    can directly convert a given fixed point type to
2959    a given floating point type, or vice versa.
2960    The returned value is the CODE_FOR_... value to use,
2961    or CODE_FOR_nothing if these modes cannot be directly converted.
2962
2963    *TRUNCP_PTR is set to 1 if it is necessary to output
2964    an explicit FTRUNC insn before the fix insn; otherwise 0.  */
2965
2966 static enum insn_code
2967 can_fix_p (fixmode, fltmode, unsignedp, truncp_ptr)
2968      enum machine_mode fltmode, fixmode;
2969      int unsignedp;
2970      int *truncp_ptr;
2971 {
2972   *truncp_ptr = 0;
2973   if (fixtrunctab[(int) fltmode][(int) fixmode][unsignedp] != CODE_FOR_nothing)
2974     return fixtrunctab[(int) fltmode][(int) fixmode][unsignedp];
2975
2976   if (ftrunc_optab->handlers[(int) fltmode].insn_code != CODE_FOR_nothing)
2977     {
2978       *truncp_ptr = 1;
2979       return fixtab[(int) fltmode][(int) fixmode][unsignedp];
2980     }
2981   return CODE_FOR_nothing;
2982 }
2983
2984 static enum insn_code
2985 can_float_p (fltmode, fixmode, unsignedp)
2986      enum machine_mode fixmode, fltmode;
2987      int unsignedp;
2988 {
2989   return floattab[(int) fltmode][(int) fixmode][unsignedp];
2990 }
2991 \f
2992 /* Generate code to convert FROM to floating point
2993    and store in TO.  FROM must be fixed point and not VOIDmode.
2994    UNSIGNEDP nonzero means regard FROM as unsigned.
2995    Normally this is done by correcting the final value
2996    if it is negative.  */
2997
2998 void
2999 expand_float (to, from, unsignedp)
3000      rtx to, from;
3001      int unsignedp;
3002 {
3003   enum insn_code icode;
3004   register rtx target = to;
3005   enum machine_mode fmode, imode;
3006
3007   /* Crash now, because we won't be able to decide which mode to use.  */
3008   if (GET_MODE (from) == VOIDmode)
3009     abort ();
3010
3011   /* Look for an insn to do the conversion.  Do it in the specified
3012      modes if possible; otherwise convert either input, output or both to
3013      wider mode.  If the integer mode is wider than the mode of FROM,
3014      we can do the conversion signed even if the input is unsigned.  */
3015
3016   for (imode = GET_MODE (from); imode != VOIDmode;
3017        imode = GET_MODE_WIDER_MODE (imode))
3018     for (fmode = GET_MODE (to); fmode != VOIDmode;
3019          fmode = GET_MODE_WIDER_MODE (fmode))
3020       {
3021         int doing_unsigned = unsignedp;
3022
3023         icode = can_float_p (fmode, imode, unsignedp);
3024         if (icode == CODE_FOR_nothing && imode != GET_MODE (from) && unsignedp)
3025           icode = can_float_p (fmode, imode, 0), doing_unsigned = 0;
3026
3027         if (icode != CODE_FOR_nothing)
3028           {
3029             to = protect_from_queue (to, 1);
3030             from = protect_from_queue (from, 0);
3031
3032             if (imode != GET_MODE (from))
3033               from = convert_to_mode (imode, from, unsignedp);
3034
3035             if (fmode != GET_MODE (to))
3036               target = gen_reg_rtx (fmode);
3037
3038             emit_unop_insn (icode, target, from,
3039                             doing_unsigned ? UNSIGNED_FLOAT : FLOAT);
3040
3041             if (target != to)
3042               convert_move (to, target, 0);
3043             return;
3044           }
3045     }
3046
3047 #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
3048
3049   /* Unsigned integer, and no way to convert directly.
3050      Convert as signed, then conditionally adjust the result.  */
3051   if (unsignedp)
3052     {
3053       rtx label = gen_label_rtx ();
3054       rtx temp;
3055       REAL_VALUE_TYPE offset;
3056
3057       emit_queue ();
3058
3059       to = protect_from_queue (to, 1);
3060       from = protect_from_queue (from, 0);
3061
3062       if (flag_force_mem)
3063         from = force_not_mem (from);
3064
3065       /* Look for a usable floating mode FMODE wider than the source and at
3066          least as wide as the target.  Using FMODE will avoid rounding woes
3067          with unsigned values greater than the signed maximum value.  */
3068       for (fmode = GET_MODE (to);  fmode != VOIDmode;
3069            fmode = GET_MODE_WIDER_MODE (fmode))
3070         if (GET_MODE_BITSIZE (GET_MODE (from)) < GET_MODE_BITSIZE (fmode)
3071             && can_float_p (fmode, GET_MODE (from), 0) != CODE_FOR_nothing)
3072           break;
3073
3074       if (fmode == VOIDmode)
3075         {
3076           /* There is no such mode.  Pretend the target is wide enough.  */
3077           fmode = GET_MODE (to);
3078
3079           /* Avoid double-rounding when TO is narrower than FROM. */
3080           if ((significand_size (fmode) + 1)
3081               < GET_MODE_BITSIZE (GET_MODE (from)))
3082             {
3083               rtx temp1;
3084               rtx neglabel = gen_label_rtx ();
3085
3086               /* Don't use TARGET if it isn't a register or is a
3087                  hard register.  */
3088               if (GET_CODE (target) != REG
3089                   || REGNO (target) < FIRST_PSEUDO_REGISTER)
3090                 target = gen_reg_rtx (fmode);
3091
3092               imode = GET_MODE (from);
3093               do_pending_stack_adjust ();
3094
3095               /* Test whether the sign bit is set.  */
3096               emit_cmp_insn (from, const0_rtx, GE, NULL_RTX, imode, 0, 0);
3097               emit_jump_insn (gen_blt (neglabel));
3098
3099               /* The sign bit is not set.  Convert as signed.  */
3100               expand_float (target, from, 0);
3101               emit_jump_insn (gen_jump (label));
3102
3103               /* The sign bit is set.
3104                  Convert to a usable (positive signed) value by shifting right
3105                  one bit, while remembering if a nonzero bit was shifted
3106                  out; i.e., compute  (from & 1) | (from >> 1).  */
3107
3108               emit_label (neglabel);
3109               temp = expand_binop (imode, and_optab, from, const1_rtx,
3110                                    0, 1, 0);
3111               temp1 = expand_binop (imode, lshr_optab, from, const1_rtx,
3112                                     0, 1, 0);
3113               temp = expand_binop (imode, ior_optab, temp, temp1, temp, 1, 0);
3114               expand_float (target, temp, 0);
3115
3116               /* Multiply by 2 to undo the shift above.  */
3117               target = expand_binop (fmode, add_optab, target, target,
3118                                    target, 0, 0);
3119               do_pending_stack_adjust ();
3120               emit_label (label);
3121               goto done;
3122             }
3123         }
3124
3125       /* If we are about to do some arithmetic to correct for an
3126          unsigned operand, do it in a pseudo-register.  */
3127
3128       if (GET_MODE (to) != fmode
3129           || GET_CODE (to) != REG || REGNO (to) <= LAST_VIRTUAL_REGISTER)
3130         target = gen_reg_rtx (fmode);
3131
3132       /* Convert as signed integer to floating.  */
3133       expand_float (target, from, 0);
3134
3135       /* If FROM is negative (and therefore TO is negative),
3136          correct its value by 2**bitwidth.  */
3137
3138       do_pending_stack_adjust ();
3139       emit_cmp_insn (from, const0_rtx, GE, NULL_RTX, GET_MODE (from), 0, 0);
3140       emit_jump_insn (gen_bge (label));
3141       /* On SCO 3.2.1, ldexp rejects values outside [0.5, 1).
3142          Rather than setting up a dconst_dot_5, let's hope SCO
3143          fixes the bug.  */
3144       offset = REAL_VALUE_LDEXP (dconst1, GET_MODE_BITSIZE (GET_MODE (from)));
3145       temp = expand_binop (fmode, add_optab, target,
3146                            CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode),
3147                            target, 0, OPTAB_LIB_WIDEN);
3148       if (temp != target)
3149         emit_move_insn (target, temp);
3150
3151       do_pending_stack_adjust ();
3152       emit_label (label);
3153     }
3154   else
3155 #endif
3156
3157   /* No hardware instruction available; call a library rotine to convert from
3158      SImode, DImode, or TImode into SFmode, DFmode, XFmode, or TFmode.  */
3159     {
3160       rtx libfcn;
3161       rtx insns;
3162       rtx value;
3163
3164       to = protect_from_queue (to, 1);
3165       from = protect_from_queue (from, 0);
3166
3167       if (GET_MODE_SIZE (GET_MODE (from)) < GET_MODE_SIZE (SImode))
3168         from = convert_to_mode (SImode, from, unsignedp);
3169
3170       if (flag_force_mem)
3171         from = force_not_mem (from);
3172
3173       if (GET_MODE (to) == SFmode)
3174         {
3175           if (GET_MODE (from) == SImode)
3176             libfcn = floatsisf_libfunc;
3177           else if (GET_MODE (from) == DImode)
3178             libfcn = floatdisf_libfunc;
3179           else if (GET_MODE (from) == TImode)
3180             libfcn = floattisf_libfunc;
3181           else
3182             abort ();
3183         }
3184       else if (GET_MODE (to) == DFmode)
3185         {
3186           if (GET_MODE (from) == SImode)
3187             libfcn = floatsidf_libfunc;
3188           else if (GET_MODE (from) == DImode)
3189             libfcn = floatdidf_libfunc;
3190           else if (GET_MODE (from) == TImode)
3191             libfcn = floattidf_libfunc;
3192           else
3193             abort ();
3194         }
3195       else if (GET_MODE (to) == XFmode)
3196         {
3197           if (GET_MODE (from) == SImode)
3198             libfcn = floatsixf_libfunc;
3199           else if (GET_MODE (from) == DImode)
3200             libfcn = floatdixf_libfunc;
3201           else if (GET_MODE (from) == TImode)
3202             libfcn = floattixf_libfunc;
3203           else
3204             abort ();
3205         }
3206       else if (GET_MODE (to) == TFmode)
3207         {
3208           if (GET_MODE (from) == SImode)
3209             libfcn = floatsitf_libfunc;
3210           else if (GET_MODE (from) == DImode)
3211             libfcn = floatditf_libfunc;
3212           else if (GET_MODE (from) == TImode)
3213             libfcn = floattitf_libfunc;
3214           else
3215             abort ();
3216         }
3217       else
3218         abort ();
3219
3220       start_sequence ();
3221
3222       value = emit_library_call_value (libfcn, NULL_RTX, 1,
3223                                        GET_MODE (to),
3224                                        1, from, GET_MODE (from));
3225       insns = get_insns ();
3226       end_sequence ();
3227
3228       emit_libcall_block (insns, target, value,
3229                           gen_rtx (FLOAT, GET_MODE (to), from));
3230     }
3231
3232  done:
3233
3234   /* Copy result to requested destination
3235      if we have been computing in a temp location.  */
3236
3237   if (target != to)
3238     {
3239       if (GET_MODE (target) == GET_MODE (to))
3240         emit_move_insn (to, target);
3241       else
3242         convert_move (to, target, 0);
3243     }
3244 }
3245 \f
3246 /* expand_fix: generate code to convert FROM to fixed point
3247    and store in TO.  FROM must be floating point.  */
3248
3249 static rtx
3250 ftruncify (x)
3251      rtx x;
3252 {
3253   rtx temp = gen_reg_rtx (GET_MODE (x));
3254   return expand_unop (GET_MODE (x), ftrunc_optab, x, temp, 0);
3255 }
3256
3257 void
3258 expand_fix (to, from, unsignedp)
3259      register rtx to, from;
3260      int unsignedp;
3261 {
3262   enum insn_code icode;
3263   register rtx target = to;
3264   enum machine_mode fmode, imode;
3265   int must_trunc = 0;
3266   rtx libfcn = 0;
3267
3268   /* We first try to find a pair of modes, one real and one integer, at
3269      least as wide as FROM and TO, respectively, in which we can open-code
3270      this conversion.  If the integer mode is wider than the mode of TO,
3271      we can do the conversion either signed or unsigned.  */
3272
3273   for (imode = GET_MODE (to); imode != VOIDmode;
3274        imode = GET_MODE_WIDER_MODE (imode))
3275     for (fmode = GET_MODE (from); fmode != VOIDmode;
3276          fmode = GET_MODE_WIDER_MODE (fmode))
3277       {
3278         int doing_unsigned = unsignedp;
3279
3280         icode = can_fix_p (imode, fmode, unsignedp, &must_trunc);
3281         if (icode == CODE_FOR_nothing && imode != GET_MODE (to) && unsignedp)
3282           icode = can_fix_p (imode, fmode, 0, &must_trunc), doing_unsigned = 0;
3283
3284         if (icode != CODE_FOR_nothing)
3285           {
3286             to = protect_from_queue (to, 1);
3287             from = protect_from_queue (from, 0);
3288
3289             if (fmode != GET_MODE (from))
3290               from = convert_to_mode (fmode, from, 0);
3291
3292             if (must_trunc)
3293               from = ftruncify (from);
3294
3295             if (imode != GET_MODE (to))
3296               target = gen_reg_rtx (imode);
3297
3298             emit_unop_insn (icode, target, from,
3299                             doing_unsigned ? UNSIGNED_FIX : FIX);
3300             if (target != to)
3301               convert_move (to, target, unsignedp);
3302             return;
3303           }
3304       }
3305
3306 #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
3307   /* For an unsigned conversion, there is one more way to do it.
3308      If we have a signed conversion, we generate code that compares
3309      the real value to the largest representable positive number.  If if
3310      is smaller, the conversion is done normally.  Otherwise, subtract
3311      one plus the highest signed number, convert, and add it back.
3312
3313      We only need to check all real modes, since we know we didn't find
3314      anything with a wider integer mode.  */
3315
3316   if (unsignedp && GET_MODE_BITSIZE (GET_MODE (to)) <= HOST_BITS_PER_WIDE_INT)
3317     for (fmode = GET_MODE (from); fmode != VOIDmode;
3318          fmode = GET_MODE_WIDER_MODE (fmode))
3319       /* Make sure we won't lose significant bits doing this.  */
3320       if (GET_MODE_BITSIZE (fmode) > GET_MODE_BITSIZE (GET_MODE (to))
3321           && CODE_FOR_nothing != can_fix_p (GET_MODE (to), fmode, 0,
3322                                             &must_trunc))
3323         {
3324           int bitsize;
3325           REAL_VALUE_TYPE offset;
3326           rtx limit, lab1, lab2, insn;
3327
3328           bitsize = GET_MODE_BITSIZE (GET_MODE (to));
3329           offset = REAL_VALUE_LDEXP (dconst1, bitsize - 1);
3330           limit = CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode);
3331           lab1 = gen_label_rtx ();
3332           lab2 = gen_label_rtx ();
3333
3334           emit_queue ();
3335           to = protect_from_queue (to, 1);
3336           from = protect_from_queue (from, 0);
3337
3338           if (flag_force_mem)
3339             from = force_not_mem (from);
3340
3341           if (fmode != GET_MODE (from))
3342             from = convert_to_mode (fmode, from, 0);
3343
3344           /* See if we need to do the subtraction.  */
3345           do_pending_stack_adjust ();
3346           emit_cmp_insn (from, limit, GE, NULL_RTX, GET_MODE (from), 0, 0);
3347           emit_jump_insn (gen_bge (lab1));
3348
3349           /* If not, do the signed "fix" and branch around fixup code.  */
3350           expand_fix (to, from, 0);
3351           emit_jump_insn (gen_jump (lab2));
3352           emit_barrier ();
3353
3354           /* Otherwise, subtract 2**(N-1), convert to signed number,
3355              then add 2**(N-1).  Do the addition using XOR since this
3356              will often generate better code.  */
3357           emit_label (lab1);
3358           target = expand_binop (GET_MODE (from), sub_optab, from, limit,
3359                                  NULL_RTX, 0, OPTAB_LIB_WIDEN);
3360           expand_fix (to, target, 0);
3361           target = expand_binop (GET_MODE (to), xor_optab, to,
3362                                  GEN_INT ((HOST_WIDE_INT) 1 << (bitsize - 1)),
3363                                  to, 1, OPTAB_LIB_WIDEN);
3364
3365           if (target != to)
3366             emit_move_insn (to, target);
3367
3368           emit_label (lab2);
3369
3370           /* Make a place for a REG_NOTE and add it.  */
3371           insn = emit_move_insn (to, to);
3372           REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL,
3373                                       gen_rtx (UNSIGNED_FIX, GET_MODE (to),
3374                                                copy_rtx (from)),
3375                                       REG_NOTES (insn));
3376
3377           return;
3378         }
3379 #endif
3380
3381   /* We can't do it with an insn, so use a library call.  But first ensure
3382      that the mode of TO is at least as wide as SImode, since those are the
3383      only library calls we know about.  */
3384
3385   if (GET_MODE_SIZE (GET_MODE (to)) < GET_MODE_SIZE (SImode))
3386     {
3387       target = gen_reg_rtx (SImode);
3388
3389       expand_fix (target, from, unsignedp);
3390     }
3391   else if (GET_MODE (from) == SFmode)
3392     {
3393       if (GET_MODE (to) == SImode)
3394         libfcn = unsignedp ? fixunssfsi_libfunc : fixsfsi_libfunc;
3395       else if (GET_MODE (to) == DImode)
3396         libfcn = unsignedp ? fixunssfdi_libfunc : fixsfdi_libfunc;
3397       else if (GET_MODE (to) == TImode)
3398         libfcn = unsignedp ? fixunssfti_libfunc : fixsfti_libfunc;
3399       else
3400         abort ();
3401     }
3402   else if (GET_MODE (from) == DFmode)
3403     {
3404       if (GET_MODE (to) == SImode)
3405         libfcn = unsignedp ? fixunsdfsi_libfunc : fixdfsi_libfunc;
3406       else if (GET_MODE (to) == DImode)
3407         libfcn = unsignedp ? fixunsdfdi_libfunc : fixdfdi_libfunc;
3408       else if (GET_MODE (to) == TImode)
3409         libfcn = unsignedp ? fixunsdfti_libfunc : fixdfti_libfunc;
3410       else
3411         abort ();
3412     }
3413   else if (GET_MODE (from) == XFmode)
3414     {
3415       if (GET_MODE (to) == SImode)
3416         libfcn = unsignedp ? fixunsxfsi_libfunc : fixxfsi_libfunc;
3417       else if (GET_MODE (to) == DImode)
3418         libfcn = unsignedp ? fixunsxfdi_libfunc : fixxfdi_libfunc;
3419       else if (GET_MODE (to) == TImode)
3420         libfcn = unsignedp ? fixunsxfti_libfunc : fixxfti_libfunc;
3421       else
3422         abort ();
3423     }
3424   else if (GET_MODE (from) == TFmode)
3425     {
3426       if (GET_MODE (to) == SImode)
3427         libfcn = unsignedp ? fixunstfsi_libfunc : fixtfsi_libfunc;
3428       else if (GET_MODE (to) == DImode)
3429         libfcn = unsignedp ? fixunstfdi_libfunc : fixtfdi_libfunc;
3430       else if (GET_MODE (to) == TImode)
3431         libfcn = unsignedp ? fixunstfti_libfunc : fixtfti_libfunc;
3432       else
3433         abort ();
3434     }
3435   else
3436     abort ();
3437
3438   if (libfcn)
3439     {
3440       rtx insns;
3441
3442       to = protect_from_queue (to, 1);
3443       from = protect_from_queue (from, 0);
3444
3445       if (flag_force_mem)
3446         from = force_not_mem (from);
3447
3448       start_sequence ();
3449
3450       emit_library_call (libfcn, 1, GET_MODE (to), 1, from, GET_MODE (from));
3451       insns = get_insns ();
3452       end_sequence ();
3453
3454       emit_libcall_block (insns, target, hard_libcall_value (GET_MODE (to)),
3455                           gen_rtx (unsignedp ? FIX : UNSIGNED_FIX,
3456                                    GET_MODE (to), from));
3457     }
3458       
3459   if (GET_MODE (to) == GET_MODE (target))
3460     emit_move_insn (to, target);
3461   else
3462     convert_move (to, target, 0);
3463 }
3464 \f
3465 static optab
3466 init_optab (code)
3467      enum rtx_code code;
3468 {
3469   int i;
3470   optab op = (optab) xmalloc (sizeof (struct optab));
3471   op->code = code;
3472   for (i = 0; i < NUM_MACHINE_MODES; i++)
3473     {
3474       op->handlers[i].insn_code = CODE_FOR_nothing;
3475       op->handlers[i].libfunc = 0;
3476     }
3477
3478   if (code != UNKNOWN)
3479     code_to_optab[(int) code] = op;
3480
3481   return op;
3482 }
3483
3484 /* Initialize the libfunc fields of an entire group of entries in some
3485    optab.  Each entry is set equal to a string consisting of a leading
3486    pair of underscores followed by a generic operation name followed by
3487    a mode name (downshifted to lower case) followed by a single character
3488    representing the number of operands for the given operation (which is
3489    usually one of the characters '2', '3', or '4').
3490
3491    OPTABLE is the table in which libfunc fields are to be initialized.
3492    FIRST_MODE is the first machine mode index in the given optab to
3493      initialize.
3494    LAST_MODE is the last machine mode index in the given optab to
3495      initialize.
3496    OPNAME is the generic (string) name of the operation.
3497    SUFFIX is the character which specifies the number of operands for
3498      the given generic operation.
3499 */
3500
3501 static void
3502 init_libfuncs (optable, first_mode, last_mode, opname, suffix)
3503     register optab optable;
3504     register int first_mode;
3505     register int last_mode;
3506     register char *opname;
3507     register char suffix;
3508 {
3509   register int mode;
3510   register unsigned opname_len = strlen (opname);
3511
3512   for (mode = first_mode; (int) mode <= (int) last_mode;
3513        mode = (enum machine_mode) ((int) mode + 1))
3514     {
3515       register char *mname = mode_name[(int) mode];
3516       register unsigned mname_len = strlen (mname);
3517       register char *libfunc_name
3518         = (char *) xmalloc (2 + opname_len + mname_len + 1 + 1);
3519       register char *p;
3520       register char *q;
3521
3522       p = libfunc_name;
3523       *p++ = '_';
3524       *p++ = '_';
3525       for (q = opname; *q; )
3526         *p++ = *q++;
3527       for (q = mname; *q; q++)
3528         *p++ = tolower (*q);
3529       *p++ = suffix;
3530       *p++ = '\0';
3531       optable->handlers[(int) mode].libfunc
3532         = gen_rtx (SYMBOL_REF, Pmode, libfunc_name);
3533     }
3534 }
3535
3536 /* Initialize the libfunc fields of an entire group of entries in some
3537    optab which correspond to all integer mode operations.  The parameters
3538    have the same meaning as similarly named ones for the `init_libfuncs'
3539    routine.  (See above).  */
3540
3541 static void
3542 init_integral_libfuncs (optable, opname, suffix)
3543     register optab optable;
3544     register char *opname;
3545     register char suffix;
3546 {
3547   init_libfuncs (optable, SImode, TImode, opname, suffix);
3548 }
3549
3550 /* Initialize the libfunc fields of an entire group of entries in some
3551    optab which correspond to all real mode operations.  The parameters
3552    have the same meaning as similarly named ones for the `init_libfuncs'
3553    routine.  (See above).  */
3554
3555 static void
3556 init_floating_libfuncs (optable, opname, suffix)
3557     register optab optable;
3558     register char *opname;
3559     register char suffix;
3560 {
3561   init_libfuncs (optable, SFmode, TFmode, opname, suffix);
3562 }
3563
3564 /* Initialize the libfunc fields of an entire group of entries in some
3565    optab which correspond to all complex floating modes.  The parameters
3566    have the same meaning as similarly named ones for the `init_libfuncs'
3567    routine.  (See above).  */
3568
3569 static void
3570 init_complex_libfuncs (optable, opname, suffix)
3571     register optab optable;
3572     register char *opname;
3573     register char suffix;
3574 {
3575   init_libfuncs (optable, SCmode, TCmode, opname, suffix);
3576 }
3577
3578 /* Call this once to initialize the contents of the optabs
3579    appropriately for the current target machine.  */
3580
3581 void
3582 init_optabs ()
3583 {
3584   int i, j;
3585   enum insn_code *p;
3586
3587   /* Start by initializing all tables to contain CODE_FOR_nothing.  */
3588
3589   for (p = fixtab[0][0];
3590        p < fixtab[0][0] + sizeof fixtab / sizeof (fixtab[0][0][0]); 
3591        p++)
3592     *p = CODE_FOR_nothing;
3593
3594   for (p = fixtrunctab[0][0];
3595        p < fixtrunctab[0][0] + sizeof fixtrunctab / sizeof (fixtrunctab[0][0][0]); 
3596        p++)
3597     *p = CODE_FOR_nothing;
3598
3599   for (p = floattab[0][0];
3600        p < floattab[0][0] + sizeof floattab / sizeof (floattab[0][0][0]); 
3601        p++)
3602     *p = CODE_FOR_nothing;
3603
3604   for (p = extendtab[0][0];
3605        p < extendtab[0][0] + sizeof extendtab / sizeof extendtab[0][0][0];
3606        p++)
3607     *p = CODE_FOR_nothing;
3608
3609   for (i = 0; i < NUM_RTX_CODE; i++)
3610     setcc_gen_code[i] = CODE_FOR_nothing;
3611
3612   add_optab = init_optab (PLUS);
3613   sub_optab = init_optab (MINUS);
3614   smul_optab = init_optab (MULT);
3615   smul_widen_optab = init_optab (UNKNOWN);
3616   umul_widen_optab = init_optab (UNKNOWN);
3617   sdiv_optab = init_optab (DIV);
3618   sdivmod_optab = init_optab (UNKNOWN);
3619   udiv_optab = init_optab (UDIV);
3620   udivmod_optab = init_optab (UNKNOWN);
3621   smod_optab = init_optab (MOD);
3622   umod_optab = init_optab (UMOD);
3623   flodiv_optab = init_optab (DIV);
3624   ftrunc_optab = init_optab (UNKNOWN);
3625   and_optab = init_optab (AND);
3626   ior_optab = init_optab (IOR);
3627   xor_optab = init_optab (XOR);
3628   ashl_optab = init_optab (ASHIFT);
3629   ashr_optab = init_optab (ASHIFTRT);
3630   lshr_optab = init_optab (LSHIFTRT);
3631   rotl_optab = init_optab (ROTATE);
3632   rotr_optab = init_optab (ROTATERT);
3633   smin_optab = init_optab (SMIN);
3634   smax_optab = init_optab (SMAX);
3635   umin_optab = init_optab (UMIN);
3636   umax_optab = init_optab (UMAX);
3637   mov_optab = init_optab (UNKNOWN);
3638   movstrict_optab = init_optab (UNKNOWN);
3639   cmp_optab = init_optab (UNKNOWN);
3640   ucmp_optab = init_optab (UNKNOWN);
3641   tst_optab = init_optab (UNKNOWN);
3642   neg_optab = init_optab (NEG);
3643   abs_optab = init_optab (ABS);
3644   one_cmpl_optab = init_optab (NOT);
3645   ffs_optab = init_optab (FFS);
3646   sqrt_optab = init_optab (SQRT);
3647   sin_optab = init_optab (UNKNOWN);
3648   cos_optab = init_optab (UNKNOWN);
3649   strlen_optab = init_optab (UNKNOWN);
3650
3651   for (i = 0; i < NUM_MACHINE_MODES; i++)
3652     {
3653       movstr_optab[i] = CODE_FOR_nothing;
3654
3655 #ifdef HAVE_SECONDARY_RELOADS
3656       reload_in_optab[i] = reload_out_optab[i] = CODE_FOR_nothing;
3657 #endif
3658     }
3659
3660   /* Fill in the optabs with the insns we support.  */
3661   init_all_optabs ();
3662
3663 #ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC
3664   /* This flag says the same insns that convert to a signed fixnum
3665      also convert validly to an unsigned one.  */
3666   for (i = 0; i < NUM_MACHINE_MODES; i++)
3667     for (j = 0; j < NUM_MACHINE_MODES; j++)
3668       fixtrunctab[i][j][1] = fixtrunctab[i][j][0];
3669 #endif
3670
3671 #ifdef EXTRA_CC_MODES
3672   init_mov_optab ();
3673 #endif
3674
3675   /* Initialize the optabs with the names of the library functions.  */
3676   init_integral_libfuncs (add_optab, "add", '3');
3677   init_floating_libfuncs (add_optab, "add", '3');
3678   init_integral_libfuncs (sub_optab, "sub", '3');
3679   init_floating_libfuncs (sub_optab, "sub", '3');
3680   init_integral_libfuncs (smul_optab, "mul", '3');
3681   init_floating_libfuncs (smul_optab, "mul", '3');
3682   init_integral_libfuncs (sdiv_optab, "div", '3');
3683   init_integral_libfuncs (udiv_optab, "udiv", '3');
3684   init_integral_libfuncs (sdivmod_optab, "divmod", '4');
3685   init_integral_libfuncs (udivmod_optab, "udivmod", '4');
3686   init_integral_libfuncs (smod_optab, "mod", '3');
3687   init_integral_libfuncs (umod_optab, "umod", '3');
3688   init_floating_libfuncs (flodiv_optab, "div", '3');
3689   init_floating_libfuncs (ftrunc_optab, "ftrunc", '2');
3690   init_integral_libfuncs (and_optab, "and", '3');
3691   init_integral_libfuncs (ior_optab, "ior", '3');
3692   init_integral_libfuncs (xor_optab, "xor", '3');
3693   init_integral_libfuncs (ashl_optab, "ashl", '3');
3694   init_integral_libfuncs (ashr_optab, "ashr", '3');
3695   init_integral_libfuncs (lshr_optab, "lshr", '3');
3696   init_integral_libfuncs (rotl_optab, "rotl", '3');
3697   init_integral_libfuncs (rotr_optab, "rotr", '3');
3698   init_integral_libfuncs (smin_optab, "min", '3');
3699   init_floating_libfuncs (smin_optab, "min", '3');
3700   init_integral_libfuncs (smax_optab, "max", '3');
3701   init_floating_libfuncs (smax_optab, "max", '3');
3702   init_integral_libfuncs (umin_optab, "umin", '3');
3703   init_integral_libfuncs (umax_optab, "umax", '3');
3704   init_integral_libfuncs (neg_optab, "neg", '2');
3705   init_floating_libfuncs (neg_optab, "neg", '2');
3706   init_integral_libfuncs (one_cmpl_optab, "one_cmpl", '2');
3707   init_integral_libfuncs (ffs_optab, "ffs", '2');
3708
3709   /* Comparison libcalls for integers MUST come in pairs, signed/unsigned.  */
3710   init_integral_libfuncs (cmp_optab, "cmp", '2');
3711   init_integral_libfuncs (ucmp_optab, "ucmp", '2');
3712   init_floating_libfuncs (cmp_optab, "cmp", '2');
3713
3714 #ifdef MULSI3_LIBCALL
3715   smul_optab->handlers[(int) SImode].libfunc
3716     = gen_rtx (SYMBOL_REF, Pmode, MULSI3_LIBCALL);
3717 #endif
3718 #ifdef MULDI3_LIBCALL
3719   smul_optab->handlers[(int) DImode].libfunc
3720     = gen_rtx (SYMBOL_REF, Pmode, MULDI3_LIBCALL);
3721 #endif
3722 #ifdef MULTI3_LIBCALL
3723   smul_optab->handlers[(int) TImode].libfunc
3724     = gen_rtx (SYMBOL_REF, Pmode, MULTI3_LIBCALL);
3725 #endif
3726
3727 #ifdef DIVSI3_LIBCALL
3728   sdiv_optab->handlers[(int) SImode].libfunc
3729     = gen_rtx (SYMBOL_REF, Pmode, DIVSI3_LIBCALL);
3730 #endif
3731 #ifdef DIVDI3_LIBCALL
3732   sdiv_optab->handlers[(int) DImode].libfunc
3733     = gen_rtx (SYMBOL_REF, Pmode, DIVDI3_LIBCALL);
3734 #endif
3735 #ifdef DIVTI3_LIBCALL
3736   sdiv_optab->handlers[(int) TImode].libfunc
3737     = gen_rtx (SYMBOL_REF, Pmode, DIVTI3_LIBCALL);
3738 #endif
3739
3740 #ifdef UDIVSI3_LIBCALL
3741   udiv_optab->handlers[(int) SImode].libfunc
3742     = gen_rtx (SYMBOL_REF, Pmode, UDIVSI3_LIBCALL);
3743 #endif
3744 #ifdef UDIVDI3_LIBCALL
3745   udiv_optab->handlers[(int) DImode].libfunc
3746     = gen_rtx (SYMBOL_REF, Pmode, UDIVDI3_LIBCALL);
3747 #endif
3748 #ifdef UDIVTI3_LIBCALL
3749   udiv_optab->handlers[(int) TImode].libfunc
3750     = gen_rtx (SYMBOL_REF, Pmode, UDIVTI3_LIBCALL);
3751 #endif
3752
3753
3754 #ifdef MODSI3_LIBCALL
3755   smod_optab->handlers[(int) SImode].libfunc
3756     = gen_rtx (SYMBOL_REF, Pmode, MODSI3_LIBCALL);
3757 #endif
3758 #ifdef MODDI3_LIBCALL
3759   smod_optab->handlers[(int) DImode].libfunc
3760     = gen_rtx (SYMBOL_REF, Pmode, MODDI3_LIBCALL);
3761 #endif
3762 #ifdef MODTI3_LIBCALL
3763   smod_optab->handlers[(int) TImode].libfunc
3764     = gen_rtx (SYMBOL_REF, Pmode, MODTI3_LIBCALL);
3765 #endif
3766
3767
3768 #ifdef UMODSI3_LIBCALL
3769   umod_optab->handlers[(int) SImode].libfunc
3770     = gen_rtx (SYMBOL_REF, Pmode, UMODSI3_LIBCALL);
3771 #endif
3772 #ifdef UMODDI3_LIBCALL
3773   umod_optab->handlers[(int) DImode].libfunc
3774     = gen_rtx (SYMBOL_REF, Pmode, UMODDI3_LIBCALL);
3775 #endif
3776 #ifdef UMODTI3_LIBCALL
3777   umod_optab->handlers[(int) TImode].libfunc
3778     = gen_rtx (SYMBOL_REF, Pmode, UMODTI3_LIBCALL);
3779 #endif
3780
3781 /* Define library calls for quad FP instructions */
3782 #ifdef ADDTF3_LIBCALL
3783   add_optab->handlers[(int) TFmode].libfunc
3784     = gen_rtx (SYMBOL_REF, Pmode, ADDTF3_LIBCALL);
3785 #endif
3786 #ifdef SUBTF3_LIBCALL
3787   sub_optab->handlers[(int) TFmode].libfunc
3788     = gen_rtx (SYMBOL_REF, Pmode, SUBTF3_LIBCALL);
3789 #endif
3790 #ifdef MULTF3_LIBCALL
3791   smul_optab->handlers[(int) TFmode].libfunc
3792     = gen_rtx (SYMBOL_REF, Pmode, MULTF3_LIBCALL);
3793 #endif
3794 #ifdef DIVTF3_LIBCALL
3795   flodiv_optab->handlers[(int) TFmode].libfunc
3796     = gen_rtx (SYMBOL_REF, Pmode, DIVTF3_LIBCALL);
3797 #endif
3798 #ifdef SQRTTF2_LIBCALL
3799   sqrt_optab->handlers[(int) TFmode].libfunc
3800     = gen_rtx (SYMBOL_REF, Pmode, SQRTTF2_LIBCALL);
3801 #endif
3802
3803   /* Use cabs for DC complex abs, since systems generally have cabs.
3804      Don't define any libcall for SCmode, so that cabs will be used.  */
3805   abs_optab->handlers[(int) DCmode].libfunc
3806     = gen_rtx (SYMBOL_REF, Pmode, "cabs");
3807
3808   /* The ffs function operates on `int'.  */
3809 #ifndef INT_TYPE_SIZE
3810 #define INT_TYPE_SIZE BITS_PER_WORD
3811 #endif
3812   ffs_optab->handlers[(int) mode_for_size (INT_TYPE_SIZE, MODE_INT, 0)] .libfunc
3813     = gen_rtx (SYMBOL_REF, Pmode, "ffs");
3814
3815   extendsfdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extendsfdf2");
3816   extendsfxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extendsfxf2");
3817   extendsftf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extendsftf2");
3818   extenddfxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extenddfxf2");
3819   extenddftf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extenddftf2");
3820
3821   truncdfsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__truncdfsf2");
3822   truncxfsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__truncxfsf2");
3823   trunctfsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__trunctfsf2");
3824   truncxfdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__truncxfdf2");
3825   trunctfdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__trunctfdf2");
3826
3827   memcpy_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memcpy");
3828   bcopy_libfunc = gen_rtx (SYMBOL_REF, Pmode, "bcopy");
3829   memcmp_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memcmp");
3830   bcmp_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gcc_bcmp");
3831   memset_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memset");
3832   bzero_libfunc = gen_rtx (SYMBOL_REF, Pmode, "bzero");
3833
3834   eqsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqsf2");
3835   nesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nesf2");
3836   gtsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gtsf2");
3837   gesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gesf2");
3838   ltsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ltsf2");
3839   lesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__lesf2");
3840
3841   eqdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqdf2");
3842   nedf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nedf2");
3843   gtdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gtdf2");
3844   gedf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gedf2");
3845   ltdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ltdf2");
3846   ledf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ledf2");
3847
3848   eqxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqxf2");
3849   nexf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nexf2");
3850   gtxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gtxf2");
3851   gexf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gexf2");
3852   ltxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ltxf2");
3853   lexf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__lexf2");
3854
3855   eqtf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqtf2");
3856   netf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__netf2");
3857   gttf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gttf2");
3858   getf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__getf2");
3859   lttf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__lttf2");
3860   letf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__letf2");
3861
3862 /* Define library calls for quad FP instructions */
3863 #ifdef EQTF2_LIBCALL
3864   eqtf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, EQTF2_LIBCALL);
3865 #endif
3866 #ifdef NETF2_LIBCALL
3867   netf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, NETF2_LIBCALL);
3868 #endif
3869 #ifdef GTTF2_LIBCALL
3870   gttf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, GTTF2_LIBCALL);
3871 #endif
3872 #ifdef GETF2_LIBCALL
3873   getf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, GETF2_LIBCALL);
3874 #endif
3875 #ifdef LTTF2_LIBCALL
3876   lttf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, LTTF2_LIBCALL);
3877 #endif
3878 #ifdef LETF2_LIBCALL
3879   letf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, LETF2_LIBCALL);
3880 #endif
3881
3882   floatsisf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsisf");
3883   floatdisf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatdisf");
3884   floattisf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floattisf");
3885
3886   floatsidf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsidf");
3887   floatdidf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatdidf");
3888   floattidf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floattidf");
3889
3890   floatsixf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsixf");
3891   floatdixf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatdixf");
3892   floattixf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floattixf");
3893
3894   floatsitf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsitf");
3895   floatditf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatditf");
3896   floattitf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floattitf");
3897
3898   fixsfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixsfsi");
3899   fixsfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixsfdi");
3900   fixsfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixsfti");
3901
3902   fixdfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixdfsi");
3903   fixdfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixdfdi");
3904   fixdfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixdfti");
3905
3906   fixxfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixxfsi");
3907   fixxfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixxfdi");
3908   fixxfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixxfti");
3909
3910   fixtfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixtfsi");
3911   fixtfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixtfdi");
3912   fixtfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixtfti");
3913
3914   fixunssfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunssfsi");
3915   fixunssfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunssfdi");
3916   fixunssfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunssfti");
3917
3918   fixunsdfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsdfsi");
3919   fixunsdfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsdfdi");
3920   fixunsdfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsdfti");
3921
3922   fixunsxfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsxfsi");
3923   fixunsxfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsxfdi");
3924   fixunsxfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsxfti");
3925
3926   fixunstfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunstfsi");
3927   fixunstfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunstfdi");
3928   fixunstfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunstfti");
3929
3930 /* Define library calls for quad FP instructions */
3931 #ifdef TRUNCTFSF2_LIBCALL
3932   trunctfsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, TRUNCTFSF2_LIBCALL);
3933 #endif
3934 #ifdef TRUNCTFDF2_LIBCALL
3935   trunctfdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, TRUNCTFDF2_LIBCALL);
3936 #endif
3937 #ifdef EXTENDSFTF2_LIBCALL
3938   extendsftf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, EXTENDSFTF2_LIBCALL);
3939 #endif
3940 #ifdef EXTENDDFTF2_LIBCALL
3941   extenddftf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, EXTENDDFTF2_LIBCALL);
3942 #endif
3943 #ifdef FLOATSITF2_LIBCALL
3944   floatsitf_libfunc = gen_rtx (SYMBOL_REF, Pmode, FLOATSITF2_LIBCALL);
3945 #endif
3946 #ifdef FIX_TRUNCTFSI2_LIBCALL
3947   fixtfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, FIX_TRUNCTFSI2_LIBCALL);
3948 #endif
3949 #ifdef FIXUNS_TRUNCTFSI2_LIBCALL
3950   fixunstfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, FIXUNS_TRUNCTFSI2_LIBCALL);
3951 #endif
3952 }
3953 \f
3954 #ifdef BROKEN_LDEXP
3955
3956 /* SCO 3.2 apparently has a broken ldexp. */
3957
3958 double
3959 ldexp(x,n)
3960      double x;
3961      int n;
3962 {
3963   if (n > 0)
3964     while (n--)
3965       x *= 2;
3966
3967   return x;
3968 }
3969 #endif /* BROKEN_LDEXP */