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