OSDN Git Service

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