OSDN Git Service

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