OSDN Git Service

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