OSDN Git Service

(widen_operand): New function.
[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 pseudo which were referenced in previous
2299      insns.  These can be generated by move_by_pieces, for example,
2300      to update an address.  */
2301
2302   for (insn = insns; insn; insn = next)
2303     {
2304       rtx set = single_set (insn);
2305
2306       next = NEXT_INSN (insn);
2307
2308       if (set != 0 && GET_CODE (SET_DEST (set)) == REG
2309           && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER
2310           && (insn == insns
2311               || (! reg_mentioned_p (SET_DEST (set), PATTERN (insns))
2312                   && ! reg_used_between_p (SET_DEST (set), insns, insn))))
2313         {
2314           if (PREV_INSN (insn))
2315             NEXT_INSN (PREV_INSN (insn)) = next;
2316           else
2317             insns = next;
2318
2319           if (next)
2320             PREV_INSN (next) = PREV_INSN (insn);
2321
2322           add_insn (insn);
2323         }
2324     }
2325
2326   prev = get_last_insn ();
2327
2328   /* Write the remaining insns followed by the final copy.  */
2329
2330   for (insn = insns; insn; insn = next)
2331     {
2332       next = NEXT_INSN (insn);
2333
2334       add_insn (insn);
2335     }
2336
2337   last = emit_move_insn (target, result);
2338   REG_NOTES (last) = gen_rtx (EXPR_LIST,
2339                               REG_EQUAL, copy_rtx (equiv), REG_NOTES (last));
2340
2341   if (prev == 0)
2342     first = get_insns ();
2343   else
2344     first = NEXT_INSN (prev);
2345
2346   /* Encapsulate the block so it gets manipulated as a unit.  */
2347   REG_NOTES (first) = gen_rtx (INSN_LIST, REG_LIBCALL, last,
2348                                REG_NOTES (first));
2349   REG_NOTES (last) = gen_rtx (INSN_LIST, REG_RETVAL, first, REG_NOTES (last));
2350 }
2351 \f
2352 /* Generate code to store zero in X.  */
2353
2354 void
2355 emit_clr_insn (x)
2356      rtx x;
2357 {
2358   emit_move_insn (x, const0_rtx);
2359 }
2360
2361 /* Generate code to store 1 in X
2362    assuming it contains zero beforehand.  */
2363
2364 void
2365 emit_0_to_1_insn (x)
2366      rtx x;
2367 {
2368   emit_move_insn (x, const1_rtx);
2369 }
2370
2371 /* Generate code to compare X with Y
2372    so that the condition codes are set.
2373
2374    MODE is the mode of the inputs (in case they are const_int).
2375    UNSIGNEDP nonzero says that X and Y are unsigned;
2376    this matters if they need to be widened.
2377
2378    If they have mode BLKmode, then SIZE specifies the size of both X and Y,
2379    and ALIGN specifies the known shared alignment of X and Y.
2380
2381    COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).
2382    It is ignored for fixed-point and block comparisons;
2383    it is used only for floating-point comparisons.  */
2384
2385 void
2386 emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align)
2387      rtx x, y;
2388      enum rtx_code comparison;
2389      rtx size;
2390      enum machine_mode mode;
2391      int unsignedp;
2392      int align;
2393 {
2394   enum mode_class class;
2395   enum machine_mode wider_mode;
2396
2397   class = GET_MODE_CLASS (mode);
2398
2399   /* They could both be VOIDmode if both args are immediate constants,
2400      but we should fold that at an earlier stage.
2401      With no special code here, this will call abort,
2402      reminding the programmer to implement such folding.  */
2403
2404   if (mode != BLKmode && flag_force_mem)
2405     {
2406       x = force_not_mem (x);
2407       y = force_not_mem (y);
2408     }
2409
2410   /* If we are inside an appropriately-short loop and one operand is an
2411      expensive constant, force it into a register.  */
2412   if (CONSTANT_P (x) && preserve_subexpressions_p () && rtx_cost (x, COMPARE) > 2)
2413     x = force_reg (mode, x);
2414
2415   if (CONSTANT_P (y) && preserve_subexpressions_p () && rtx_cost (y, COMPARE) > 2)
2416     y = force_reg (mode, y);
2417
2418   /* Don't let both operands fail to indicate the mode.  */
2419   if (GET_MODE (x) == VOIDmode && GET_MODE (y) == VOIDmode)
2420     x = force_reg (mode, x);
2421
2422   /* Handle all BLKmode compares.  */
2423
2424   if (mode == BLKmode)
2425     {
2426       emit_queue ();
2427       x = protect_from_queue (x, 0);
2428       y = protect_from_queue (y, 0);
2429
2430       if (size == 0)
2431         abort ();
2432 #ifdef HAVE_cmpstrqi
2433       if (HAVE_cmpstrqi
2434           && GET_CODE (size) == CONST_INT
2435           && INTVAL (size) < (1 << GET_MODE_BITSIZE (QImode)))
2436         {
2437           enum machine_mode result_mode
2438             = insn_operand_mode[(int) CODE_FOR_cmpstrqi][0];
2439           rtx result = gen_reg_rtx (result_mode);
2440           emit_insn (gen_cmpstrqi (result, x, y, size, GEN_INT (align)));
2441           emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX,
2442                          result_mode, 0, 0);
2443         }
2444       else
2445 #endif
2446 #ifdef HAVE_cmpstrhi
2447       if (HAVE_cmpstrhi
2448           && GET_CODE (size) == CONST_INT
2449           && INTVAL (size) < (1 << GET_MODE_BITSIZE (HImode)))
2450         {
2451           enum machine_mode result_mode
2452             = insn_operand_mode[(int) CODE_FOR_cmpstrhi][0];
2453           rtx result = gen_reg_rtx (result_mode);
2454           emit_insn (gen_cmpstrhi (result, x, y, size, GEN_INT (align)));
2455           emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX,
2456                          result_mode, 0, 0);
2457         }
2458       else
2459 #endif
2460 #ifdef HAVE_cmpstrsi
2461       if (HAVE_cmpstrsi)
2462         {
2463           enum machine_mode result_mode
2464             = insn_operand_mode[(int) CODE_FOR_cmpstrsi][0];
2465           rtx result = gen_reg_rtx (result_mode);
2466           size = protect_from_queue (size, 0);
2467           emit_insn (gen_cmpstrsi (result, x, y,
2468                                    convert_to_mode (SImode, size, 1),
2469                                    GEN_INT (align)));
2470           emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX,
2471                          result_mode, 0, 0);
2472         }
2473       else
2474 #endif
2475         {
2476 #ifdef TARGET_MEM_FUNCTIONS
2477           emit_library_call (memcmp_libfunc, 0,
2478                              TYPE_MODE (integer_type_node), 3,
2479                              XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
2480                              size, Pmode);
2481 #else
2482           emit_library_call (bcmp_libfunc, 0,
2483                              TYPE_MODE (integer_type_node), 3,
2484                              XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
2485                              size, Pmode);
2486 #endif
2487           emit_cmp_insn (hard_libcall_value (TYPE_MODE (integer_type_node)),
2488                          const0_rtx, comparison, NULL_RTX,
2489                          TYPE_MODE (integer_type_node), 0, 0);
2490         }
2491       return;
2492     }
2493
2494   /* Handle some compares against zero.  */
2495
2496   if (y == CONST0_RTX (mode)
2497       && tst_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
2498     {
2499       int icode = (int) tst_optab->handlers[(int) mode].insn_code;
2500
2501       emit_queue ();
2502       x = protect_from_queue (x, 0);
2503       y = protect_from_queue (y, 0);
2504
2505       /* Now, if insn does accept these operands, put them into pseudos.  */
2506       if (! (*insn_operand_predicate[icode][0])
2507           (x, insn_operand_mode[icode][0]))
2508         x = copy_to_mode_reg (insn_operand_mode[icode][0], x);
2509
2510       emit_insn (GEN_FCN (icode) (x));
2511       return;
2512     }
2513
2514   /* Handle compares for which there is a directly suitable insn.  */
2515
2516   if (cmp_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
2517     {
2518       int icode = (int) cmp_optab->handlers[(int) mode].insn_code;
2519
2520       emit_queue ();
2521       x = protect_from_queue (x, 0);
2522       y = protect_from_queue (y, 0);
2523
2524       /* Now, if insn doesn't accept these operands, put them into pseudos.  */
2525       if (! (*insn_operand_predicate[icode][0])
2526           (x, insn_operand_mode[icode][0]))
2527         x = copy_to_mode_reg (insn_operand_mode[icode][0], x);
2528
2529       if (! (*insn_operand_predicate[icode][1])
2530           (y, insn_operand_mode[icode][1]))
2531         y = copy_to_mode_reg (insn_operand_mode[icode][1], y);
2532
2533       emit_insn (GEN_FCN (icode) (x, y));
2534       return;
2535     }
2536
2537   /* Try widening if we can find a direct insn that way.  */
2538
2539   if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
2540     {
2541       for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
2542            wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2543         {
2544           if (cmp_optab->handlers[(int) wider_mode].insn_code
2545               != CODE_FOR_nothing)
2546             {
2547               x = protect_from_queue (x, 0);
2548               y = protect_from_queue (y, 0);
2549               x = convert_to_mode (wider_mode, x, unsignedp);
2550               y = convert_to_mode (wider_mode, y, unsignedp);
2551               emit_cmp_insn (x, y, comparison, NULL_RTX,
2552                              wider_mode, unsignedp, align);
2553               return;
2554             }
2555         }
2556     }
2557
2558   /* Handle a lib call just for the mode we are using.  */
2559
2560   if (cmp_optab->handlers[(int) mode].libfunc
2561       && class != MODE_FLOAT)
2562     {
2563       rtx libfunc = cmp_optab->handlers[(int) mode].libfunc;
2564       /* If we want unsigned, and this mode has a distinct unsigned
2565          comparison routine, use that.  */
2566       if (unsignedp && ucmp_optab->handlers[(int) mode].libfunc)
2567         libfunc = ucmp_optab->handlers[(int) mode].libfunc;
2568
2569       emit_library_call (libfunc, 1,
2570                          word_mode, 2, x, mode, y, mode);
2571
2572       /* Integer comparison returns a result that must be compared against 1,
2573          so that even if we do an unsigned compare afterward,
2574          there is still a value that can represent the result "less than".  */
2575
2576       emit_cmp_insn (hard_libcall_value (word_mode), const1_rtx,
2577                      comparison, NULL_RTX, word_mode, unsignedp, 0);
2578       return;
2579     }
2580
2581   if (class == MODE_FLOAT)
2582     emit_float_lib_cmp (x, y, comparison);
2583
2584   else
2585     abort ();
2586 }
2587
2588 /* Nonzero if a compare of mode MODE can be done straightforwardly
2589    (without splitting it into pieces).  */
2590
2591 int
2592 can_compare_p (mode)
2593      enum machine_mode mode;
2594 {
2595   do
2596     {
2597       if (cmp_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)
2598         return 1;
2599       mode = GET_MODE_WIDER_MODE (mode);
2600     } while (mode != VOIDmode);
2601
2602   return 0;
2603 }
2604 \f
2605 /* Emit a library call comparison between floating point X and Y.
2606    COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).  */
2607
2608 static void
2609 emit_float_lib_cmp (x, y, comparison)
2610      rtx x, y;
2611      enum rtx_code comparison;
2612 {
2613   enum machine_mode mode = GET_MODE (x);
2614   rtx libfunc;
2615
2616   if (mode == SFmode)
2617     switch (comparison)
2618       {
2619       case EQ:
2620         libfunc = eqsf2_libfunc;
2621         break;
2622
2623       case NE:
2624         libfunc = nesf2_libfunc;
2625         break;
2626
2627       case GT:
2628         libfunc = gtsf2_libfunc;
2629         break;
2630
2631       case GE:
2632         libfunc = gesf2_libfunc;
2633         break;
2634
2635       case LT:
2636         libfunc = ltsf2_libfunc;
2637         break;
2638
2639       case LE:
2640         libfunc = lesf2_libfunc;
2641         break;
2642       }
2643   else if (mode == DFmode)
2644     switch (comparison)
2645       {
2646       case EQ:
2647         libfunc = eqdf2_libfunc;
2648         break;
2649
2650       case NE:
2651         libfunc = nedf2_libfunc;
2652         break;
2653
2654       case GT:
2655         libfunc = gtdf2_libfunc;
2656         break;
2657
2658       case GE:
2659         libfunc = gedf2_libfunc;
2660         break;
2661
2662       case LT:
2663         libfunc = ltdf2_libfunc;
2664         break;
2665
2666       case LE:
2667         libfunc = ledf2_libfunc;
2668         break;
2669       }
2670   else if (mode == XFmode)
2671     switch (comparison)
2672       {
2673       case EQ:
2674         libfunc = eqxf2_libfunc;
2675         break;
2676
2677       case NE:
2678         libfunc = nexf2_libfunc;
2679         break;
2680
2681       case GT:
2682         libfunc = gtxf2_libfunc;
2683         break;
2684
2685       case GE:
2686         libfunc = gexf2_libfunc;
2687         break;
2688
2689       case LT:
2690         libfunc = ltxf2_libfunc;
2691         break;
2692
2693       case LE:
2694         libfunc = lexf2_libfunc;
2695         break;
2696       }
2697   else if (mode == TFmode)
2698     switch (comparison)
2699       {
2700       case EQ:
2701         libfunc = eqtf2_libfunc;
2702         break;
2703
2704       case NE:
2705         libfunc = netf2_libfunc;
2706         break;
2707
2708       case GT:
2709         libfunc = gttf2_libfunc;
2710         break;
2711
2712       case GE:
2713         libfunc = getf2_libfunc;
2714         break;
2715
2716       case LT:
2717         libfunc = lttf2_libfunc;
2718         break;
2719
2720       case LE:
2721         libfunc = letf2_libfunc;
2722         break;
2723       }
2724   else
2725     {
2726       enum machine_mode wider_mode;
2727
2728       for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
2729            wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2730         {
2731           if ((cmp_optab->handlers[(int) wider_mode].insn_code
2732                != CODE_FOR_nothing)
2733               || (cmp_optab->handlers[(int) wider_mode].libfunc != 0))
2734             {
2735               x = protect_from_queue (x, 0);
2736               y = protect_from_queue (y, 0);
2737               x = convert_to_mode (wider_mode, x, 0);
2738               y = convert_to_mode (wider_mode, y, 0);
2739               emit_float_lib_cmp (x, y, comparison);
2740               return;
2741             }
2742         }
2743       abort ();
2744     }
2745
2746   emit_library_call (libfunc, 1,
2747                      word_mode, 2, x, mode, y, mode);
2748
2749   emit_cmp_insn (hard_libcall_value (word_mode), const0_rtx, comparison,
2750                  NULL_RTX, word_mode, 0, 0);
2751 }
2752 \f
2753 /* Generate code to indirectly jump to a location given in the rtx LOC.  */
2754
2755 void
2756 emit_indirect_jump (loc)
2757      rtx loc;
2758 {
2759   if (! ((*insn_operand_predicate[(int)CODE_FOR_indirect_jump][0])
2760          (loc, Pmode)))
2761     loc = copy_to_mode_reg (Pmode, loc);
2762
2763   emit_jump_insn (gen_indirect_jump (loc));
2764   emit_barrier ();
2765 }
2766 \f
2767 /* These three functions generate an insn body and return it
2768    rather than emitting the insn.
2769
2770    They do not protect from queued increments,
2771    because they may be used 1) in protect_from_queue itself
2772    and 2) in other passes where there is no queue.  */
2773
2774 /* Generate and return an insn body to add Y to X.  */
2775
2776 rtx
2777 gen_add2_insn (x, y)
2778      rtx x, y;
2779 {
2780   int icode = (int) add_optab->handlers[(int) GET_MODE (x)].insn_code; 
2781
2782   if (! (*insn_operand_predicate[icode][0]) (x, insn_operand_mode[icode][0])
2783       || ! (*insn_operand_predicate[icode][1]) (x, insn_operand_mode[icode][1])
2784       || ! (*insn_operand_predicate[icode][2]) (y, insn_operand_mode[icode][2]))
2785     abort ();
2786
2787   return (GEN_FCN (icode) (x, x, y));
2788 }
2789
2790 int
2791 have_add2_insn (mode)
2792      enum machine_mode mode;
2793 {
2794   return add_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing;
2795 }
2796
2797 /* Generate and return an insn body to subtract Y from X.  */
2798
2799 rtx
2800 gen_sub2_insn (x, y)
2801      rtx x, y;
2802 {
2803   int icode = (int) sub_optab->handlers[(int) GET_MODE (x)].insn_code; 
2804
2805   if (! (*insn_operand_predicate[icode][0]) (x, insn_operand_mode[icode][0])
2806       || ! (*insn_operand_predicate[icode][1]) (x, insn_operand_mode[icode][1])
2807       || ! (*insn_operand_predicate[icode][2]) (y, insn_operand_mode[icode][2]))
2808     abort ();
2809
2810   return (GEN_FCN (icode) (x, x, y));
2811 }
2812
2813 int
2814 have_sub2_insn (mode)
2815      enum machine_mode mode;
2816 {
2817   return sub_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing;
2818 }
2819
2820 /* Generate the body of an instruction to copy Y into X.
2821    It may be a SEQUENCE, if one insn isn't enough.  */
2822
2823 rtx
2824 gen_move_insn (x, y)
2825      rtx x, y;
2826 {
2827   register enum machine_mode mode = GET_MODE (x);
2828   enum insn_code insn_code;
2829   rtx seq;
2830
2831   if (mode == VOIDmode)
2832     mode = GET_MODE (y); 
2833
2834   insn_code = mov_optab->handlers[(int) mode].insn_code;
2835
2836   /* Handle MODE_CC modes:  If we don't have a special move insn for this mode,
2837      find a mode to do it in.  If we have a movcc, use it.  Otherwise,
2838      find the MODE_INT mode of the same width.  */
2839
2840   if (GET_MODE_CLASS (mode) == MODE_CC && insn_code == CODE_FOR_nothing)
2841     {
2842       enum machine_mode tmode = VOIDmode;
2843       rtx x1 = x, y1 = y;
2844
2845       if (mode != CCmode
2846           && mov_optab->handlers[(int) CCmode].insn_code != CODE_FOR_nothing)
2847         tmode = CCmode;
2848       else
2849         for (tmode = QImode; tmode != VOIDmode;
2850              tmode = GET_MODE_WIDER_MODE (tmode))
2851           if (GET_MODE_SIZE (tmode) == GET_MODE_SIZE (mode))
2852             break;
2853
2854       if (tmode == VOIDmode)
2855         abort ();
2856
2857       /* Get X and Y in TMODE.  We can't use gen_lowpart here because it
2858          may call change_address which is not appropriate if we were
2859          called when a reload was in progress.  We don't have to worry
2860          about changing the address since the size in bytes is supposed to
2861          be the same.  Copy the MEM to change the mode and move any
2862          substitutions from the old MEM to the new one.  */
2863
2864       if (reload_in_progress)
2865         {
2866           x = gen_lowpart_common (tmode, x1);
2867           if (x == 0 && GET_CODE (x1) == MEM)
2868             {
2869               x = gen_rtx (MEM, tmode, XEXP (x1, 0));
2870               RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (x1);
2871               MEM_IN_STRUCT_P (x) = MEM_IN_STRUCT_P (x1);
2872               MEM_VOLATILE_P (x) = MEM_VOLATILE_P (x1);
2873               copy_replacements (x1, x);
2874             }
2875
2876           y = gen_lowpart_common (tmode, y1);
2877           if (y == 0 && GET_CODE (y1) == MEM)
2878             {
2879               y = gen_rtx (MEM, tmode, XEXP (y1, 0));
2880               RTX_UNCHANGING_P (y) = RTX_UNCHANGING_P (y1);
2881               MEM_IN_STRUCT_P (y) = MEM_IN_STRUCT_P (y1);
2882               MEM_VOLATILE_P (y) = MEM_VOLATILE_P (y1);
2883               copy_replacements (y1, y);
2884             }
2885         }
2886       else
2887         {
2888           x = gen_lowpart (tmode, x);
2889           y = gen_lowpart (tmode, y);
2890         }
2891           
2892       insn_code = mov_optab->handlers[(int) tmode].insn_code;
2893       return (GEN_FCN (insn_code) (x, y));
2894     }
2895
2896   start_sequence ();
2897   emit_move_insn_1 (x, y);
2898   seq = gen_sequence ();
2899   end_sequence ();
2900   return seq;
2901 }
2902 \f
2903 /* Return the insn code used to extend FROM_MODE to TO_MODE.
2904    UNSIGNEDP specifies zero-extension instead of sign-extension.  If
2905    no such operation exists, CODE_FOR_nothing will be returned.  */
2906
2907 enum insn_code
2908 can_extend_p (to_mode, from_mode, unsignedp)
2909      enum machine_mode to_mode, from_mode;
2910      int unsignedp;
2911 {
2912   return extendtab[(int) to_mode][(int) from_mode][unsignedp];
2913 }
2914
2915 /* Generate the body of an insn to extend Y (with mode MFROM)
2916    into X (with mode MTO).  Do zero-extension if UNSIGNEDP is nonzero.  */
2917
2918 rtx
2919 gen_extend_insn (x, y, mto, mfrom, unsignedp)
2920      rtx x, y;
2921      enum machine_mode mto, mfrom;
2922      int unsignedp;
2923 {
2924   return (GEN_FCN (extendtab[(int) mto][(int) mfrom][unsignedp]) (x, y));
2925 }
2926 \f
2927 /* can_fix_p and can_float_p say whether the target machine
2928    can directly convert a given fixed point type to
2929    a given floating point type, or vice versa.
2930    The returned value is the CODE_FOR_... value to use,
2931    or CODE_FOR_nothing if these modes cannot be directly converted.
2932
2933    *TRUNCP_PTR is set to 1 if it is necessary to output
2934    an explicit FTRUNC insn before the fix insn; otherwise 0.  */
2935
2936 static enum insn_code
2937 can_fix_p (fixmode, fltmode, unsignedp, truncp_ptr)
2938      enum machine_mode fltmode, fixmode;
2939      int unsignedp;
2940      int *truncp_ptr;
2941 {
2942   *truncp_ptr = 0;
2943   if (fixtrunctab[(int) fltmode][(int) fixmode][unsignedp] != CODE_FOR_nothing)
2944     return fixtrunctab[(int) fltmode][(int) fixmode][unsignedp];
2945
2946   if (ftrunc_optab->handlers[(int) fltmode].insn_code != CODE_FOR_nothing)
2947     {
2948       *truncp_ptr = 1;
2949       return fixtab[(int) fltmode][(int) fixmode][unsignedp];
2950     }
2951   return CODE_FOR_nothing;
2952 }
2953
2954 static enum insn_code
2955 can_float_p (fltmode, fixmode, unsignedp)
2956      enum machine_mode fixmode, fltmode;
2957      int unsignedp;
2958 {
2959   return floattab[(int) fltmode][(int) fixmode][unsignedp];
2960 }
2961 \f
2962 /* Generate code to convert FROM to floating point
2963    and store in TO.  FROM must be fixed point and not VOIDmode.
2964    UNSIGNEDP nonzero means regard FROM as unsigned.
2965    Normally this is done by correcting the final value
2966    if it is negative.  */
2967
2968 void
2969 expand_float (to, from, unsignedp)
2970      rtx to, from;
2971      int unsignedp;
2972 {
2973   enum insn_code icode;
2974   register rtx target = to;
2975   enum machine_mode fmode, imode;
2976
2977   /* Crash now, because we won't be able to decide which mode to use.  */
2978   if (GET_MODE (from) == VOIDmode)
2979     abort ();
2980
2981   /* Look for an insn to do the conversion.  Do it in the specified
2982      modes if possible; otherwise convert either input, output or both to
2983      wider mode.  If the integer mode is wider than the mode of FROM,
2984      we can do the conversion signed even if the input is unsigned.  */
2985
2986   for (imode = GET_MODE (from); imode != VOIDmode;
2987        imode = GET_MODE_WIDER_MODE (imode))
2988     for (fmode = GET_MODE (to); fmode != VOIDmode;
2989          fmode = GET_MODE_WIDER_MODE (fmode))
2990       {
2991         int doing_unsigned = unsignedp;
2992
2993         icode = can_float_p (fmode, imode, unsignedp);
2994         if (icode == CODE_FOR_nothing && imode != GET_MODE (from) && unsignedp)
2995           icode = can_float_p (fmode, imode, 0), doing_unsigned = 0;
2996
2997         if (icode != CODE_FOR_nothing)
2998           {
2999             to = protect_from_queue (to, 1);
3000             from = protect_from_queue (from, 0);
3001
3002             if (imode != GET_MODE (from))
3003               from = convert_to_mode (imode, from, unsignedp);
3004
3005             if (fmode != GET_MODE (to))
3006               target = gen_reg_rtx (fmode);
3007
3008             emit_unop_insn (icode, target, from,
3009                             doing_unsigned ? UNSIGNED_FLOAT : FLOAT);
3010
3011             if (target != to)
3012               convert_move (to, target, 0);
3013             return;
3014           }
3015     }
3016
3017 #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
3018
3019   /* Unsigned integer, and no way to convert directly.
3020      Convert as signed, then conditionally adjust the result.  */
3021   if (unsignedp)
3022     {
3023       rtx label = gen_label_rtx ();
3024       rtx temp;
3025       REAL_VALUE_TYPE offset;
3026
3027       emit_queue ();
3028
3029       to = protect_from_queue (to, 1);
3030       from = protect_from_queue (from, 0);
3031
3032       if (flag_force_mem)
3033         from = force_not_mem (from);
3034
3035       /* Look for a usable floating mode FMODE wider than the source and at
3036          least as wide as the target.  Using FMODE will avoid rounding woes
3037          with unsigned values greater than the signed maximum value.  */
3038       for (fmode = GET_MODE (to);  fmode != VOIDmode;
3039            fmode = GET_MODE_WIDER_MODE (fmode))
3040         if (GET_MODE_BITSIZE (GET_MODE (from)) < GET_MODE_BITSIZE (fmode)
3041             && can_float_p (fmode, GET_MODE (from), 0) != CODE_FOR_nothing)
3042           break;
3043       if (fmode == VOIDmode)
3044         {
3045           /* There is no such mode.  Pretend the target is wide enough.
3046              This may cause rounding problems, unfortunately.  */
3047           fmode = GET_MODE (to);
3048         }
3049
3050       /* If we are about to do some arithmetic to correct for an
3051          unsigned operand, do it in a pseudo-register.  */
3052
3053       if (GET_MODE (to) != fmode
3054           || GET_CODE (to) != REG || REGNO (to) <= LAST_VIRTUAL_REGISTER)
3055         target = gen_reg_rtx (fmode);
3056
3057       /* Convert as signed integer to floating.  */
3058       expand_float (target, from, 0);
3059
3060       /* If FROM is negative (and therefore TO is negative),
3061          correct its value by 2**bitwidth.  */
3062
3063       do_pending_stack_adjust ();
3064       emit_cmp_insn (from, const0_rtx, GE, NULL_RTX, GET_MODE (from), 0, 0);
3065       emit_jump_insn (gen_bge (label));
3066       /* On SCO 3.2.1, ldexp rejects values outside [0.5, 1).
3067          Rather than setting up a dconst_dot_5, let's hope SCO
3068          fixes the bug.  */
3069       offset = REAL_VALUE_LDEXP (dconst1, GET_MODE_BITSIZE (GET_MODE (from)));
3070       temp = expand_binop (fmode, add_optab, target,
3071                            immed_real_const_1 (offset, fmode),
3072                            target, 0, OPTAB_LIB_WIDEN);
3073       if (temp != target)
3074         emit_move_insn (target, temp);
3075       do_pending_stack_adjust ();
3076       emit_label (label);
3077     }
3078   else
3079 #endif
3080
3081   /* No hardware instruction available; call a library rotine to convert from
3082      SImode, DImode, or TImode into SFmode, DFmode, XFmode, or TFmode.  */
3083     {
3084       rtx libfcn;
3085       rtx insns;
3086
3087       to = protect_from_queue (to, 1);
3088       from = protect_from_queue (from, 0);
3089
3090       if (GET_MODE_SIZE (GET_MODE (from)) < GET_MODE_SIZE (SImode))
3091         from = convert_to_mode (SImode, from, unsignedp);
3092
3093       if (flag_force_mem)
3094         from = force_not_mem (from);
3095
3096       if (GET_MODE (to) == SFmode)
3097         {
3098           if (GET_MODE (from) == SImode)
3099             libfcn = floatsisf_libfunc;
3100           else if (GET_MODE (from) == DImode)
3101             libfcn = floatdisf_libfunc;
3102           else if (GET_MODE (from) == TImode)
3103             libfcn = floattisf_libfunc;
3104           else
3105             abort ();
3106         }
3107       else if (GET_MODE (to) == DFmode)
3108         {
3109           if (GET_MODE (from) == SImode)
3110             libfcn = floatsidf_libfunc;
3111           else if (GET_MODE (from) == DImode)
3112             libfcn = floatdidf_libfunc;
3113           else if (GET_MODE (from) == TImode)
3114             libfcn = floattidf_libfunc;
3115           else
3116             abort ();
3117         }
3118       else if (GET_MODE (to) == XFmode)
3119         {
3120           if (GET_MODE (from) == SImode)
3121             libfcn = floatsixf_libfunc;
3122           else if (GET_MODE (from) == DImode)
3123             libfcn = floatdixf_libfunc;
3124           else if (GET_MODE (from) == TImode)
3125             libfcn = floattixf_libfunc;
3126           else
3127             abort ();
3128         }
3129       else if (GET_MODE (to) == TFmode)
3130         {
3131           if (GET_MODE (from) == SImode)
3132             libfcn = floatsitf_libfunc;
3133           else if (GET_MODE (from) == DImode)
3134             libfcn = floatditf_libfunc;
3135           else if (GET_MODE (from) == TImode)
3136             libfcn = floattitf_libfunc;
3137           else
3138             abort ();
3139         }
3140       else
3141         abort ();
3142
3143       start_sequence ();
3144
3145       emit_library_call (libfcn, 1, GET_MODE (to), 1, from, GET_MODE (from));
3146       insns = get_insns ();
3147       end_sequence ();
3148
3149       emit_libcall_block (insns, target, hard_libcall_value (GET_MODE (to)),
3150                           gen_rtx (FLOAT, GET_MODE (to), from));
3151     }
3152
3153   /* Copy result to requested destination
3154      if we have been computing in a temp location.  */
3155
3156   if (target != to)
3157     {
3158       if (GET_MODE (target) == GET_MODE (to))
3159         emit_move_insn (to, target);
3160       else
3161         convert_move (to, target, 0);
3162     }
3163 }
3164 \f
3165 /* expand_fix: generate code to convert FROM to fixed point
3166    and store in TO.  FROM must be floating point.  */
3167
3168 static rtx
3169 ftruncify (x)
3170      rtx x;
3171 {
3172   rtx temp = gen_reg_rtx (GET_MODE (x));
3173   return expand_unop (GET_MODE (x), ftrunc_optab, x, temp, 0);
3174 }
3175
3176 void
3177 expand_fix (to, from, unsignedp)
3178      register rtx to, from;
3179      int unsignedp;
3180 {
3181   enum insn_code icode;
3182   register rtx target = to;
3183   enum machine_mode fmode, imode;
3184   int must_trunc = 0;
3185   rtx libfcn = 0;
3186
3187   /* We first try to find a pair of modes, one real and one integer, at
3188      least as wide as FROM and TO, respectively, in which we can open-code
3189      this conversion.  If the integer mode is wider than the mode of TO,
3190      we can do the conversion either signed or unsigned.  */
3191
3192   for (imode = GET_MODE (to); imode != VOIDmode;
3193        imode = GET_MODE_WIDER_MODE (imode))
3194     for (fmode = GET_MODE (from); fmode != VOIDmode;
3195          fmode = GET_MODE_WIDER_MODE (fmode))
3196       {
3197         int doing_unsigned = unsignedp;
3198
3199         icode = can_fix_p (imode, fmode, unsignedp, &must_trunc);
3200         if (icode == CODE_FOR_nothing && imode != GET_MODE (to) && unsignedp)
3201           icode = can_fix_p (imode, fmode, 0, &must_trunc), doing_unsigned = 0;
3202
3203         if (icode != CODE_FOR_nothing)
3204           {
3205             to = protect_from_queue (to, 1);
3206             from = protect_from_queue (from, 0);
3207
3208             if (fmode != GET_MODE (from))
3209               from = convert_to_mode (fmode, from, 0);
3210
3211             if (must_trunc)
3212               from = ftruncify (from);
3213
3214             if (imode != GET_MODE (to))
3215               target = gen_reg_rtx (imode);
3216
3217             emit_unop_insn (icode, target, from,
3218                             doing_unsigned ? UNSIGNED_FIX : FIX);
3219             if (target != to)
3220               convert_move (to, target, unsignedp);
3221             return;
3222           }
3223       }
3224
3225 #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
3226   /* For an unsigned conversion, there is one more way to do it.
3227      If we have a signed conversion, we generate code that compares
3228      the real value to the largest representable positive number.  If if
3229      is smaller, the conversion is done normally.  Otherwise, subtract
3230      one plus the highest signed number, convert, and add it back.
3231
3232      We only need to check all real modes, since we know we didn't find
3233      anything with a wider integer mode.  */
3234
3235   if (unsignedp && GET_MODE_BITSIZE (GET_MODE (to)) <= HOST_BITS_PER_WIDE_INT)
3236     for (fmode = GET_MODE (from); fmode != VOIDmode;
3237          fmode = GET_MODE_WIDER_MODE (fmode))
3238       /* Make sure we won't lose significant bits doing this.  */
3239       if (GET_MODE_BITSIZE (fmode) > GET_MODE_BITSIZE (GET_MODE (to))
3240           && CODE_FOR_nothing != can_fix_p (GET_MODE (to), fmode, 0,
3241                                             &must_trunc))
3242         {
3243           int bitsize;
3244           REAL_VALUE_TYPE offset;
3245           rtx limit, lab1, lab2, insn;
3246
3247           bitsize = GET_MODE_BITSIZE (GET_MODE (to));
3248           offset = REAL_VALUE_LDEXP (dconst1, bitsize - 1);
3249           limit = immed_real_const_1 (offset, fmode);
3250           lab1 = gen_label_rtx ();
3251           lab2 = gen_label_rtx ();
3252
3253           emit_queue ();
3254           to = protect_from_queue (to, 1);
3255           from = protect_from_queue (from, 0);
3256
3257           if (flag_force_mem)
3258             from = force_not_mem (from);
3259
3260           if (fmode != GET_MODE (from))
3261             from = convert_to_mode (fmode, from, 0);
3262
3263           /* See if we need to do the subtraction.  */
3264           do_pending_stack_adjust ();
3265           emit_cmp_insn (from, limit, GE, NULL_RTX, GET_MODE (from), 0, 0);
3266           emit_jump_insn (gen_bge (lab1));
3267
3268           /* If not, do the signed "fix" and branch around fixup code.  */
3269           expand_fix (to, from, 0);
3270           emit_jump_insn (gen_jump (lab2));
3271           emit_barrier ();
3272
3273           /* Otherwise, subtract 2**(N-1), convert to signed number,
3274              then add 2**(N-1).  Do the addition using XOR since this
3275              will often generate better code.  */
3276           emit_label (lab1);
3277           target = expand_binop (GET_MODE (from), sub_optab, from, limit,
3278                                  NULL_RTX, 0, OPTAB_LIB_WIDEN);
3279           expand_fix (to, target, 0);
3280           target = expand_binop (GET_MODE (to), xor_optab, to,
3281                                  GEN_INT ((HOST_WIDE_INT) 1 << (bitsize - 1)),
3282                                  to, 1, OPTAB_LIB_WIDEN);
3283
3284           if (target != to)
3285             emit_move_insn (to, target);
3286
3287           emit_label (lab2);
3288
3289           /* Make a place for a REG_NOTE and add it.  */
3290           insn = emit_move_insn (to, to);
3291           REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL,
3292                                       gen_rtx (UNSIGNED_FIX, GET_MODE (to),
3293                                                copy_rtx (from)),
3294                                       REG_NOTES (insn));
3295
3296           return;
3297         }
3298 #endif
3299
3300   /* We can't do it with an insn, so use a library call.  But first ensure
3301      that the mode of TO is at least as wide as SImode, since those are the
3302      only library calls we know about.  */
3303
3304   if (GET_MODE_SIZE (GET_MODE (to)) < GET_MODE_SIZE (SImode))
3305     {
3306       target = gen_reg_rtx (SImode);
3307
3308       expand_fix (target, from, unsignedp);
3309     }
3310   else if (GET_MODE (from) == SFmode)
3311     {
3312       if (GET_MODE (to) == SImode)
3313         libfcn = unsignedp ? fixunssfsi_libfunc : fixsfsi_libfunc;
3314       else if (GET_MODE (to) == DImode)
3315         libfcn = unsignedp ? fixunssfdi_libfunc : fixsfdi_libfunc;
3316       else if (GET_MODE (to) == TImode)
3317         libfcn = unsignedp ? fixunssfti_libfunc : fixsfti_libfunc;
3318       else
3319         abort ();
3320     }
3321   else if (GET_MODE (from) == DFmode)
3322     {
3323       if (GET_MODE (to) == SImode)
3324         libfcn = unsignedp ? fixunsdfsi_libfunc : fixdfsi_libfunc;
3325       else if (GET_MODE (to) == DImode)
3326         libfcn = unsignedp ? fixunsdfdi_libfunc : fixdfdi_libfunc;
3327       else if (GET_MODE (to) == TImode)
3328         libfcn = unsignedp ? fixunsdfti_libfunc : fixdfti_libfunc;
3329       else
3330         abort ();
3331     }
3332   else if (GET_MODE (from) == XFmode)
3333     {
3334       if (GET_MODE (to) == SImode)
3335         libfcn = unsignedp ? fixunsxfsi_libfunc : fixxfsi_libfunc;
3336       else if (GET_MODE (to) == DImode)
3337         libfcn = unsignedp ? fixunsxfdi_libfunc : fixxfdi_libfunc;
3338       else if (GET_MODE (to) == TImode)
3339         libfcn = unsignedp ? fixunsxfti_libfunc : fixxfti_libfunc;
3340       else
3341         abort ();
3342     }
3343   else if (GET_MODE (from) == TFmode)
3344     {
3345       if (GET_MODE (to) == SImode)
3346         libfcn = unsignedp ? fixunstfsi_libfunc : fixtfsi_libfunc;
3347       else if (GET_MODE (to) == DImode)
3348         libfcn = unsignedp ? fixunstfdi_libfunc : fixtfdi_libfunc;
3349       else if (GET_MODE (to) == TImode)
3350         libfcn = unsignedp ? fixunstfti_libfunc : fixtfti_libfunc;
3351       else
3352         abort ();
3353     }
3354   else
3355     abort ();
3356
3357   if (libfcn)
3358     {
3359       rtx insns;
3360
3361       to = protect_from_queue (to, 1);
3362       from = protect_from_queue (from, 0);
3363
3364       if (flag_force_mem)
3365         from = force_not_mem (from);
3366
3367       start_sequence ();
3368
3369       emit_library_call (libfcn, 1, GET_MODE (to), 1, from, GET_MODE (from));
3370       insns = get_insns ();
3371       end_sequence ();
3372
3373       emit_libcall_block (insns, target, hard_libcall_value (GET_MODE (to)),
3374                           gen_rtx (unsignedp ? FIX : UNSIGNED_FIX,
3375                                    GET_MODE (to), from));
3376     }
3377       
3378   if (GET_MODE (to) == GET_MODE (target))
3379     emit_move_insn (to, target);
3380   else
3381     convert_move (to, target, 0);
3382 }
3383 \f
3384 static optab
3385 init_optab (code)
3386      enum rtx_code code;
3387 {
3388   int i;
3389   optab op = (optab) xmalloc (sizeof (struct optab));
3390   op->code = code;
3391   for (i = 0; i < NUM_MACHINE_MODES; i++)
3392     {
3393       op->handlers[i].insn_code = CODE_FOR_nothing;
3394       op->handlers[i].libfunc = 0;
3395     }
3396
3397   if (code != UNKNOWN)
3398     code_to_optab[(int) code] = op;
3399
3400   return op;
3401 }
3402
3403 /* Initialize the libfunc fields of an entire group of entries in some
3404    optab.  Each entry is set equal to a string consisting of a leading
3405    pair of underscores followed by a generic operation name followed by
3406    a mode name (downshifted to lower case) followed by a single character
3407    representing the number of operands for the given operation (which is
3408    usually one of the characters '2', '3', or '4').
3409
3410    OPTABLE is the table in which libfunc fields are to be initialized.
3411    FIRST_MODE is the first machine mode index in the given optab to
3412      initialize.
3413    LAST_MODE is the last machine mode index in the given optab to
3414      initialize.
3415    OPNAME is the generic (string) name of the operation.
3416    SUFFIX is the character which specifies the number of operands for
3417      the given generic operation.
3418 */
3419
3420 static void
3421 init_libfuncs (optable, first_mode, last_mode, opname, suffix)
3422     register optab optable;
3423     register int first_mode;
3424     register int last_mode;
3425     register char *opname;
3426     register char suffix;
3427 {
3428   register int mode;
3429   register unsigned opname_len = strlen (opname);
3430
3431   for (mode = first_mode; (int) mode <= (int) last_mode;
3432        mode = (enum machine_mode) ((int) mode + 1))
3433     {
3434       register char *mname = mode_name[(int) mode];
3435       register unsigned mname_len = strlen (mname);
3436       register char *libfunc_name
3437         = (char *) xmalloc (2 + opname_len + mname_len + 1 + 1);
3438       register char *p;
3439       register char *q;
3440
3441       p = libfunc_name;
3442       *p++ = '_';
3443       *p++ = '_';
3444       for (q = opname; *q; )
3445         *p++ = *q++;
3446       for (q = mname; *q; q++)
3447         *p++ = tolower (*q);
3448       *p++ = suffix;
3449       *p++ = '\0';
3450       optable->handlers[(int) mode].libfunc
3451         = gen_rtx (SYMBOL_REF, Pmode, libfunc_name);
3452     }
3453 }
3454
3455 /* Initialize the libfunc fields of an entire group of entries in some
3456    optab which correspond to all integer mode operations.  The parameters
3457    have the same meaning as similarly named ones for the `init_libfuncs'
3458    routine.  (See above).  */
3459
3460 static void
3461 init_integral_libfuncs (optable, opname, suffix)
3462     register optab optable;
3463     register char *opname;
3464     register char suffix;
3465 {
3466   init_libfuncs (optable, SImode, TImode, opname, suffix);
3467 }
3468
3469 /* Initialize the libfunc fields of an entire group of entries in some
3470    optab which correspond to all real mode operations.  The parameters
3471    have the same meaning as similarly named ones for the `init_libfuncs'
3472    routine.  (See above).  */
3473
3474 static void
3475 init_floating_libfuncs (optable, opname, suffix)
3476     register optab optable;
3477     register char *opname;
3478     register char suffix;
3479 {
3480   init_libfuncs (optable, SFmode, TFmode, opname, suffix);
3481 }
3482
3483 /* Initialize the libfunc fields of an entire group of entries in some
3484    optab which correspond to all complex floating modes.  The parameters
3485    have the same meaning as similarly named ones for the `init_libfuncs'
3486    routine.  (See above).  */
3487
3488 static void
3489 init_complex_libfuncs (optable, opname, suffix)
3490     register optab optable;
3491     register char *opname;
3492     register char suffix;
3493 {
3494   init_libfuncs (optable, SCmode, TCmode, opname, suffix);
3495 }
3496
3497 /* Call this once to initialize the contents of the optabs
3498    appropriately for the current target machine.  */
3499
3500 void
3501 init_optabs ()
3502 {
3503   int i, j;
3504   enum insn_code *p;
3505
3506   /* Start by initializing all tables to contain CODE_FOR_nothing.  */
3507
3508   for (p = fixtab[0][0];
3509        p < fixtab[0][0] + sizeof fixtab / sizeof (fixtab[0][0][0]); 
3510        p++)
3511     *p = CODE_FOR_nothing;
3512
3513   for (p = fixtrunctab[0][0];
3514        p < fixtrunctab[0][0] + sizeof fixtrunctab / sizeof (fixtrunctab[0][0][0]); 
3515        p++)
3516     *p = CODE_FOR_nothing;
3517
3518   for (p = floattab[0][0];
3519        p < floattab[0][0] + sizeof floattab / sizeof (floattab[0][0][0]); 
3520        p++)
3521     *p = CODE_FOR_nothing;
3522
3523   for (p = extendtab[0][0];
3524        p < extendtab[0][0] + sizeof extendtab / sizeof extendtab[0][0][0];
3525        p++)
3526     *p = CODE_FOR_nothing;
3527
3528   for (i = 0; i < NUM_RTX_CODE; i++)
3529     setcc_gen_code[i] = CODE_FOR_nothing;
3530
3531   add_optab = init_optab (PLUS);
3532   sub_optab = init_optab (MINUS);
3533   smul_optab = init_optab (MULT);
3534   smul_widen_optab = init_optab (UNKNOWN);
3535   umul_widen_optab = init_optab (UNKNOWN);
3536   sdiv_optab = init_optab (DIV);
3537   sdivmod_optab = init_optab (UNKNOWN);
3538   udiv_optab = init_optab (UDIV);
3539   udivmod_optab = init_optab (UNKNOWN);
3540   smod_optab = init_optab (MOD);
3541   umod_optab = init_optab (UMOD);
3542   flodiv_optab = init_optab (DIV);
3543   ftrunc_optab = init_optab (UNKNOWN);
3544   and_optab = init_optab (AND);
3545   ior_optab = init_optab (IOR);
3546   xor_optab = init_optab (XOR);
3547   ashl_optab = init_optab (ASHIFT);
3548   ashr_optab = init_optab (ASHIFTRT);
3549   lshl_optab = init_optab (LSHIFT);
3550   lshr_optab = init_optab (LSHIFTRT);
3551   rotl_optab = init_optab (ROTATE);
3552   rotr_optab = init_optab (ROTATERT);
3553   smin_optab = init_optab (SMIN);
3554   smax_optab = init_optab (SMAX);
3555   umin_optab = init_optab (UMIN);
3556   umax_optab = init_optab (UMAX);
3557   mov_optab = init_optab (UNKNOWN);
3558   movstrict_optab = init_optab (UNKNOWN);
3559   cmp_optab = init_optab (UNKNOWN);
3560   ucmp_optab = init_optab (UNKNOWN);
3561   tst_optab = init_optab (UNKNOWN);
3562   neg_optab = init_optab (NEG);
3563   abs_optab = init_optab (ABS);
3564   one_cmpl_optab = init_optab (NOT);
3565   ffs_optab = init_optab (FFS);
3566   sqrt_optab = init_optab (SQRT);
3567   sin_optab = init_optab (UNKNOWN);
3568   cos_optab = init_optab (UNKNOWN);
3569   strlen_optab = init_optab (UNKNOWN);
3570
3571   for (i = 0; i < NUM_MACHINE_MODES; i++)
3572     {
3573       movstr_optab[i] = CODE_FOR_nothing;
3574
3575 #ifdef HAVE_SECONDARY_RELOADS
3576       reload_in_optab[i] = reload_out_optab[i] = CODE_FOR_nothing;
3577 #endif
3578     }
3579
3580   /* Fill in the optabs with the insns we support.  */
3581   init_all_optabs ();
3582
3583 #ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC
3584   /* This flag says the same insns that convert to a signed fixnum
3585      also convert validly to an unsigned one.  */
3586   for (i = 0; i < NUM_MACHINE_MODES; i++)
3587     for (j = 0; j < NUM_MACHINE_MODES; j++)
3588       fixtrunctab[i][j][1] = fixtrunctab[i][j][0];
3589 #endif
3590
3591 #ifdef EXTRA_CC_MODES
3592   init_mov_optab ();
3593 #endif
3594
3595   /* Initialize the optabs with the names of the library functions.  */
3596   init_integral_libfuncs (add_optab, "add", '3');
3597   init_floating_libfuncs (add_optab, "add", '3');
3598   init_integral_libfuncs (sub_optab, "sub", '3');
3599   init_floating_libfuncs (sub_optab, "sub", '3');
3600   init_integral_libfuncs (smul_optab, "mul", '3');
3601   init_floating_libfuncs (smul_optab, "mul", '3');
3602   init_integral_libfuncs (sdiv_optab, "div", '3');
3603   init_integral_libfuncs (udiv_optab, "udiv", '3');
3604   init_integral_libfuncs (sdivmod_optab, "divmod", '4');
3605   init_integral_libfuncs (udivmod_optab, "udivmod", '4');
3606   init_integral_libfuncs (smod_optab, "mod", '3');
3607   init_integral_libfuncs (umod_optab, "umod", '3');
3608   init_floating_libfuncs (flodiv_optab, "div", '3');
3609   init_floating_libfuncs (ftrunc_optab, "ftrunc", '2');
3610   init_integral_libfuncs (and_optab, "and", '3');
3611   init_integral_libfuncs (ior_optab, "ior", '3');
3612   init_integral_libfuncs (xor_optab, "xor", '3');
3613   init_integral_libfuncs (ashl_optab, "ashl", '3');
3614   init_integral_libfuncs (ashr_optab, "ashr", '3');
3615   init_integral_libfuncs (lshl_optab, "lshl", '3');
3616   init_integral_libfuncs (lshr_optab, "lshr", '3');
3617   init_integral_libfuncs (rotl_optab, "rotl", '3');
3618   init_integral_libfuncs (rotr_optab, "rotr", '3');
3619   init_integral_libfuncs (smin_optab, "min", '3');
3620   init_floating_libfuncs (smin_optab, "min", '3');
3621   init_integral_libfuncs (smax_optab, "max", '3');
3622   init_floating_libfuncs (smax_optab, "max", '3');
3623   init_integral_libfuncs (umin_optab, "umin", '3');
3624   init_integral_libfuncs (umax_optab, "umax", '3');
3625   init_integral_libfuncs (neg_optab, "neg", '2');
3626   init_floating_libfuncs (neg_optab, "neg", '2');
3627   init_integral_libfuncs (one_cmpl_optab, "one_cmpl", '2');
3628   init_integral_libfuncs (ffs_optab, "ffs", '2');
3629
3630   /* Comparison libcalls for integers MUST come in pairs, signed/unsigned.  */
3631   init_integral_libfuncs (cmp_optab, "cmp", '2');
3632   init_integral_libfuncs (ucmp_optab, "ucmp", '2');
3633   init_floating_libfuncs (cmp_optab, "cmp", '2');
3634
3635 #ifdef MULSI3_LIBCALL
3636   smul_optab->handlers[(int) SImode].libfunc
3637     = gen_rtx (SYMBOL_REF, Pmode, MULSI3_LIBCALL);
3638 #endif
3639 #ifdef MULDI3_LIBCALL
3640   smul_optab->handlers[(int) DImode].libfunc
3641     = gen_rtx (SYMBOL_REF, Pmode, MULDI3_LIBCALL);
3642 #endif
3643 #ifdef MULTI3_LIBCALL
3644   smul_optab->handlers[(int) TImode].libfunc
3645     = gen_rtx (SYMBOL_REF, Pmode, MULTI3_LIBCALL);
3646 #endif
3647
3648 #ifdef DIVSI3_LIBCALL
3649   sdiv_optab->handlers[(int) SImode].libfunc
3650     = gen_rtx (SYMBOL_REF, Pmode, DIVSI3_LIBCALL);
3651 #endif
3652 #ifdef DIVDI3_LIBCALL
3653   sdiv_optab->handlers[(int) DImode].libfunc
3654     = gen_rtx (SYMBOL_REF, Pmode, DIVDI3_LIBCALL);
3655 #endif
3656 #ifdef DIVTI3_LIBCALL
3657   sdiv_optab->handlers[(int) TImode].libfunc
3658     = gen_rtx (SYMBOL_REF, Pmode, DIVTI3_LIBCALL);
3659 #endif
3660
3661 #ifdef UDIVSI3_LIBCALL
3662   udiv_optab->handlers[(int) SImode].libfunc
3663     = gen_rtx (SYMBOL_REF, Pmode, UDIVSI3_LIBCALL);
3664 #endif
3665 #ifdef UDIVDI3_LIBCALL
3666   udiv_optab->handlers[(int) DImode].libfunc
3667     = gen_rtx (SYMBOL_REF, Pmode, UDIVDI3_LIBCALL);
3668 #endif
3669 #ifdef UDIVTI3_LIBCALL
3670   udiv_optab->handlers[(int) TImode].libfunc
3671     = gen_rtx (SYMBOL_REF, Pmode, UDIVTI3_LIBCALL);
3672 #endif
3673
3674
3675 #ifdef MODSI3_LIBCALL
3676   smod_optab->handlers[(int) SImode].libfunc
3677     = gen_rtx (SYMBOL_REF, Pmode, MODSI3_LIBCALL);
3678 #endif
3679 #ifdef MODDI3_LIBCALL
3680   smod_optab->handlers[(int) DImode].libfunc
3681     = gen_rtx (SYMBOL_REF, Pmode, MODDI3_LIBCALL);
3682 #endif
3683 #ifdef MODTI3_LIBCALL
3684   smod_optab->handlers[(int) TImode].libfunc
3685     = gen_rtx (SYMBOL_REF, Pmode, MODTI3_LIBCALL);
3686 #endif
3687
3688
3689 #ifdef UMODSI3_LIBCALL
3690   umod_optab->handlers[(int) SImode].libfunc
3691     = gen_rtx (SYMBOL_REF, Pmode, UMODSI3_LIBCALL);
3692 #endif
3693 #ifdef UMODDI3_LIBCALL
3694   umod_optab->handlers[(int) DImode].libfunc
3695     = gen_rtx (SYMBOL_REF, Pmode, UMODDI3_LIBCALL);
3696 #endif
3697 #ifdef UMODTI3_LIBCALL
3698   umod_optab->handlers[(int) TImode].libfunc
3699     = gen_rtx (SYMBOL_REF, Pmode, UMODTI3_LIBCALL);
3700 #endif
3701
3702   /* Use cabs for DC complex abs, since systems generally have cabs.
3703      Don't define any libcall for SCmode, so that cabs will be used.  */
3704   abs_optab->handlers[(int) DCmode].libfunc
3705     = gen_rtx (SYMBOL_REF, Pmode, "cabs");
3706
3707   ffs_optab->handlers[(int) mode_for_size (BITS_PER_WORD, MODE_INT, 0)] .libfunc
3708     = gen_rtx (SYMBOL_REF, Pmode, "ffs");
3709
3710   extendsfdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extendsfdf2");
3711   extendsfxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extendsfxf2");
3712   extendsftf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extendsftf2");
3713   extenddfxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extenddfxf2");
3714   extenddftf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extenddftf2");
3715
3716   truncdfsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__truncdfsf2");
3717   truncxfsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__truncxfsf2");
3718   trunctfsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__trunctfsf2");
3719   truncxfdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__truncxfdf2");
3720   trunctfdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__trunctfdf2");
3721
3722   memcpy_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memcpy");
3723   bcopy_libfunc = gen_rtx (SYMBOL_REF, Pmode, "bcopy");
3724   memcmp_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memcmp");
3725   bcmp_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gcc_bcmp");
3726   memset_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memset");
3727   bzero_libfunc = gen_rtx (SYMBOL_REF, Pmode, "bzero");
3728
3729   eqsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqsf2");
3730   nesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nesf2");
3731   gtsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gtsf2");
3732   gesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gesf2");
3733   ltsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ltsf2");
3734   lesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__lesf2");
3735
3736   eqdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqdf2");
3737   nedf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nedf2");
3738   gtdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gtdf2");
3739   gedf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gedf2");
3740   ltdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ltdf2");
3741   ledf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ledf2");
3742
3743   eqxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqxf2");
3744   nexf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nexf2");
3745   gtxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gtxf2");
3746   gexf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gexf2");
3747   ltxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ltxf2");
3748   lexf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__lexf2");
3749
3750   eqtf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqtf2");
3751   netf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__netf2");
3752   gttf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gttf2");
3753   getf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__getf2");
3754   lttf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__lttf2");
3755   letf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__letf2");
3756
3757   floatsisf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsisf");
3758   floatdisf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatdisf");
3759   floattisf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floattisf");
3760
3761   floatsidf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsidf");
3762   floatdidf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatdidf");
3763   floattidf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floattidf");
3764
3765   floatsixf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsixf");
3766   floatdixf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatdixf");
3767   floattixf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floattixf");
3768
3769   floatsitf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsitf");
3770   floatditf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatditf");
3771   floattitf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floattitf");
3772
3773   fixsfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixsfsi");
3774   fixsfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixsfdi");
3775   fixsfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixsfti");
3776
3777   fixdfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixdfsi");
3778   fixdfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixdfdi");
3779   fixdfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixdfti");
3780
3781   fixxfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixxfsi");
3782   fixxfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixxfdi");
3783   fixxfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixxfti");
3784
3785   fixtfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixtfsi");
3786   fixtfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixtfdi");
3787   fixtfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixtfti");
3788
3789   fixunssfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunssfsi");
3790   fixunssfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunssfdi");
3791   fixunssfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunssfti");
3792
3793   fixunsdfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsdfsi");
3794   fixunsdfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsdfdi");
3795   fixunsdfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsdfti");
3796
3797   fixunsxfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsxfsi");
3798   fixunsxfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsxfdi");
3799   fixunsxfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsxfti");
3800
3801   fixunstfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunstfsi");
3802   fixunstfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunstfdi");
3803   fixunstfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunstfti");
3804 }
3805 \f
3806 #ifdef BROKEN_LDEXP
3807
3808 /* SCO 3.2 apparently has a broken ldexp. */
3809
3810 double
3811 ldexp(x,n)
3812      double x;
3813      int n;
3814 {
3815   if (n > 0)
3816     while (n--)
3817       x *= 2;
3818
3819   return x;
3820 }
3821 #endif /* BROKEN_LDEXP */