OSDN Git Service

Include function.h in most files. Remove most of the global variables
[pf3gnuchains/gcc-fork.git] / gcc / optabs.c
1 /* Expand the basic unary and binary arithmetic operations, for GNU compiler.
2    Copyright (C) 1987, 88, 92-98, 1999 Free Software Foundation, Inc.
3
4 This file is part of GNU CC.
5
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING.  If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.  */
20
21
22 #include "config.h"
23 #include "system.h"
24 #include "toplev.h"
25
26 /* Include insn-config.h before expr.h so that HAVE_conditional_move
27    is properly defined. */
28 #include "insn-config.h"
29 #include "rtl.h"
30 #include "tree.h"
31 #include "flags.h"
32 #include "insn-flags.h"
33 #include "insn-codes.h"
34 #include "function.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 prev, next, first, last, insn;
2892
2893   /* look for any CALL_INSNs in this sequence, and attach a REG_EH_REGION
2894      reg note to indicate that this call cannot throw. (Unless there is
2895      already a REG_EH_REGION note.) */
2896
2897   for (insn = insns; insn; insn = NEXT_INSN (insn))
2898     {
2899       if (GET_CODE (insn) == CALL_INSN)
2900         {
2901           rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
2902           if (note == NULL_RTX)
2903             REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EH_REGION, GEN_INT (-1),
2904                                                   REG_NOTES (insn));
2905         }
2906     }
2907
2908   /* First emit all insns that set pseudos.  Remove them from the list as
2909      we go.  Avoid insns that set pseudos which were referenced in previous
2910      insns.  These can be generated by move_by_pieces, for example,
2911      to update an address.  Similarly, avoid insns that reference things
2912      set in previous insns.  */
2913
2914   for (insn = insns; insn; insn = next)
2915     {
2916       rtx set = single_set (insn);
2917
2918       next = NEXT_INSN (insn);
2919
2920       if (set != 0 && GET_CODE (SET_DEST (set)) == REG
2921           && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER
2922           && (insn == insns
2923               || (! reg_mentioned_p (SET_DEST (set), PATTERN (insns))
2924                   && ! reg_used_between_p (SET_DEST (set), insns, insn)
2925                   && ! modified_in_p (SET_SRC (set), insns)
2926                   && ! modified_between_p (SET_SRC (set), insns, insn))))
2927         {
2928           if (PREV_INSN (insn))
2929             NEXT_INSN (PREV_INSN (insn)) = next;
2930           else
2931             insns = next;
2932
2933           if (next)
2934             PREV_INSN (next) = PREV_INSN (insn);
2935
2936           add_insn (insn);
2937         }
2938     }
2939
2940   prev = get_last_insn ();
2941
2942   /* Write the remaining insns followed by the final copy.  */
2943
2944   for (insn = insns; insn; insn = next)
2945     {
2946       next = NEXT_INSN (insn);
2947
2948       add_insn (insn);
2949     }
2950
2951   last = emit_move_insn (target, result);
2952   if (mov_optab->handlers[(int) GET_MODE (target)].insn_code
2953       != CODE_FOR_nothing)
2954     set_unique_reg_note (last, REG_EQUAL, copy_rtx (equiv));
2955
2956   if (prev == 0)
2957     first = get_insns ();
2958   else
2959     first = NEXT_INSN (prev);
2960
2961   /* Encapsulate the block so it gets manipulated as a unit.  */
2962   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last,
2963                                          REG_NOTES (first));
2964   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
2965 }
2966 \f
2967 /* Generate code to store zero in X.  */
2968
2969 void
2970 emit_clr_insn (x)
2971      rtx x;
2972 {
2973   emit_move_insn (x, const0_rtx);
2974 }
2975
2976 /* Generate code to store 1 in X
2977    assuming it contains zero beforehand.  */
2978
2979 void
2980 emit_0_to_1_insn (x)
2981      rtx x;
2982 {
2983   emit_move_insn (x, const1_rtx);
2984 }
2985
2986 /* Generate code to compare X with Y
2987    so that the condition codes are set.
2988
2989    MODE is the mode of the inputs (in case they are const_int).
2990    UNSIGNEDP nonzero says that X and Y are unsigned;
2991    this matters if they need to be widened.
2992
2993    If they have mode BLKmode, then SIZE specifies the size of both X and Y,
2994    and ALIGN specifies the known shared alignment of X and Y.
2995
2996    COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).
2997    It is ignored for fixed-point and block comparisons;
2998    it is used only for floating-point comparisons.  */
2999
3000 void
3001 emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align)
3002      rtx x, y;
3003      enum rtx_code comparison;
3004      rtx size;
3005      enum machine_mode mode;
3006      int unsignedp;
3007      int align;
3008 {
3009   enum mode_class class;
3010   enum machine_mode wider_mode;
3011
3012   class = GET_MODE_CLASS (mode);
3013
3014   /* They could both be VOIDmode if both args are immediate constants,
3015      but we should fold that at an earlier stage.
3016      With no special code here, this will call abort,
3017      reminding the programmer to implement such folding.  */
3018
3019   if (mode != BLKmode && flag_force_mem)
3020     {
3021       x = force_not_mem (x);
3022       y = force_not_mem (y);
3023     }
3024
3025   /* If we are inside an appropriately-short loop and one operand is an
3026      expensive constant, force it into a register.  */
3027   if (CONSTANT_P (x) && preserve_subexpressions_p () && rtx_cost (x, COMPARE) > 2)
3028     x = force_reg (mode, x);
3029
3030   if (CONSTANT_P (y) && preserve_subexpressions_p () && rtx_cost (y, COMPARE) > 2)
3031     y = force_reg (mode, y);
3032
3033 #ifdef HAVE_cc0
3034   /* Abort if we have a non-canonical comparison.  The RTL documentation
3035      states that canonical comparisons are required only for targets which
3036      have cc0.  */
3037   if (CONSTANT_P (x) && ! CONSTANT_P (y))
3038     abort();
3039 #endif
3040
3041   /* Don't let both operands fail to indicate the mode.  */
3042   if (GET_MODE (x) == VOIDmode && GET_MODE (y) == VOIDmode)
3043     x = force_reg (mode, x);
3044
3045   /* Handle all BLKmode compares.  */
3046
3047   if (mode == BLKmode)
3048     {
3049       emit_queue ();
3050       x = protect_from_queue (x, 0);
3051       y = protect_from_queue (y, 0);
3052
3053       if (size == 0)
3054         abort ();
3055 #ifdef HAVE_cmpstrqi
3056       if (HAVE_cmpstrqi
3057           && GET_CODE (size) == CONST_INT
3058           && INTVAL (size) < (1 << GET_MODE_BITSIZE (QImode)))
3059         {
3060           enum machine_mode result_mode
3061             = insn_operand_mode[(int) CODE_FOR_cmpstrqi][0];
3062           rtx result = gen_reg_rtx (result_mode);
3063           emit_insn (gen_cmpstrqi (result, x, y, size, GEN_INT (align)));
3064           emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX,
3065                          result_mode, 0, 0);
3066         }
3067       else
3068 #endif
3069 #ifdef HAVE_cmpstrhi
3070       if (HAVE_cmpstrhi
3071           && GET_CODE (size) == CONST_INT
3072           && INTVAL (size) < (1 << GET_MODE_BITSIZE (HImode)))
3073         {
3074           enum machine_mode result_mode
3075             = insn_operand_mode[(int) CODE_FOR_cmpstrhi][0];
3076           rtx result = gen_reg_rtx (result_mode);
3077           emit_insn (gen_cmpstrhi (result, x, y, size, GEN_INT (align)));
3078           emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX,
3079                          result_mode, 0, 0);
3080         }
3081       else
3082 #endif
3083 #ifdef HAVE_cmpstrsi
3084       if (HAVE_cmpstrsi)
3085         {
3086           enum machine_mode result_mode
3087             = insn_operand_mode[(int) CODE_FOR_cmpstrsi][0];
3088           rtx result = gen_reg_rtx (result_mode);
3089           size = protect_from_queue (size, 0);
3090           emit_insn (gen_cmpstrsi (result, x, y,
3091                                    convert_to_mode (SImode, size, 1),
3092                                    GEN_INT (align)));
3093           emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX,
3094                          result_mode, 0, 0);
3095         }
3096       else
3097 #endif
3098         {
3099           rtx result;
3100
3101 #ifdef TARGET_MEM_FUNCTIONS
3102           emit_library_call (memcmp_libfunc, 0,
3103                              TYPE_MODE (integer_type_node), 3,
3104                              XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
3105                              convert_to_mode (TYPE_MODE (sizetype), size,
3106                                               TREE_UNSIGNED (sizetype)),
3107                              TYPE_MODE (sizetype));
3108 #else
3109           emit_library_call (bcmp_libfunc, 0,
3110                              TYPE_MODE (integer_type_node), 3,
3111                              XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
3112                              convert_to_mode (TYPE_MODE (integer_type_node),
3113                                               size,
3114                                               TREE_UNSIGNED (integer_type_node)),
3115                              TYPE_MODE (integer_type_node));
3116 #endif
3117
3118           /* Immediately move the result of the libcall into a pseudo
3119              register so reload doesn't clobber the value if it needs
3120              the return register for a spill reg.  */
3121           result = gen_reg_rtx (TYPE_MODE (integer_type_node));
3122           emit_move_insn (result,
3123                           hard_libcall_value (TYPE_MODE (integer_type_node)));
3124           emit_cmp_insn (result,
3125                          const0_rtx, comparison, NULL_RTX,
3126                          TYPE_MODE (integer_type_node), 0, 0);
3127         }
3128       return;
3129     }
3130
3131   /* Handle some compares against zero.  */
3132
3133   if (y == CONST0_RTX (mode)
3134       && tst_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
3135     {
3136       int icode = (int) tst_optab->handlers[(int) mode].insn_code;
3137
3138       emit_queue ();
3139       x = protect_from_queue (x, 0);
3140       y = protect_from_queue (y, 0);
3141
3142       /* Now, if insn does accept these operands, put them into pseudos.  */
3143       if (! (*insn_operand_predicate[icode][0])
3144           (x, insn_operand_mode[icode][0]))
3145         x = copy_to_mode_reg (insn_operand_mode[icode][0], x);
3146
3147       emit_insn (GEN_FCN (icode) (x));
3148       return;
3149     }
3150
3151   /* Handle compares for which there is a directly suitable insn.  */
3152
3153   if (cmp_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
3154     {
3155       int icode = (int) cmp_optab->handlers[(int) mode].insn_code;
3156
3157       emit_queue ();
3158       x = protect_from_queue (x, 0);
3159       y = protect_from_queue (y, 0);
3160
3161       /* Now, if insn doesn't accept these operands, put them into pseudos.  */
3162       if (! (*insn_operand_predicate[icode][0])
3163           (x, insn_operand_mode[icode][0]))
3164         x = copy_to_mode_reg (insn_operand_mode[icode][0], x);
3165
3166       if (! (*insn_operand_predicate[icode][1])
3167           (y, insn_operand_mode[icode][1]))
3168         y = copy_to_mode_reg (insn_operand_mode[icode][1], y);
3169
3170       emit_insn (GEN_FCN (icode) (x, y));
3171       return;
3172     }
3173
3174   /* Try widening if we can find a direct insn that way.  */
3175
3176   if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
3177     {
3178       for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
3179            wider_mode = GET_MODE_WIDER_MODE (wider_mode))
3180         {
3181           if (cmp_optab->handlers[(int) wider_mode].insn_code
3182               != CODE_FOR_nothing)
3183             {
3184               x = protect_from_queue (x, 0);
3185               y = protect_from_queue (y, 0);
3186               x = convert_modes (wider_mode, mode, x, unsignedp);
3187               y = convert_modes (wider_mode, mode, y, unsignedp);
3188               emit_cmp_insn (x, y, comparison, NULL_RTX,
3189                              wider_mode, unsignedp, align);
3190               return;
3191             }
3192         }
3193     }
3194
3195   /* Handle a lib call just for the mode we are using.  */
3196
3197   if (cmp_optab->handlers[(int) mode].libfunc
3198       && class != MODE_FLOAT)
3199     {
3200       rtx libfunc = cmp_optab->handlers[(int) mode].libfunc;
3201       rtx result;
3202
3203       /* If we want unsigned, and this mode has a distinct unsigned
3204          comparison routine, use that.  */
3205       if (unsignedp && ucmp_optab->handlers[(int) mode].libfunc)
3206         libfunc = ucmp_optab->handlers[(int) mode].libfunc;
3207
3208       emit_library_call (libfunc, 1,
3209                          word_mode, 2, x, mode, y, mode);
3210
3211       /* Immediately move the result of the libcall into a pseudo
3212          register so reload doesn't clobber the value if it needs
3213          the return register for a spill reg.  */
3214       result = gen_reg_rtx (word_mode);
3215       emit_move_insn (result, hard_libcall_value (word_mode));
3216
3217       /* Integer comparison returns a result that must be compared against 1,
3218          so that even if we do an unsigned compare afterward,
3219          there is still a value that can represent the result "less than".  */
3220       emit_cmp_insn (result, const1_rtx,
3221                      comparison, NULL_RTX, word_mode, unsignedp, 0);
3222       return;
3223     }
3224
3225   if (class == MODE_FLOAT)
3226     emit_float_lib_cmp (x, y, comparison);
3227
3228   else
3229     abort ();
3230 }
3231
3232 /* Generate code to compare X with Y so that the condition codes are
3233    set and to jump to LABEL if the condition is true.  If X is a
3234    constant and Y is not a constant, then the comparison is swapped to
3235    ensure that the comparison RTL has the canonical form.
3236
3237    UNSIGNEDP nonzero says that X and Y are unsigned; this matters if they
3238    need to be widened by emit_cmp_insn.  UNSIGNEDP is also used to select
3239    the proper branch condition code.
3240
3241    If X and Y have mode BLKmode, then SIZE specifies the size of both X and Y,
3242    and ALIGN specifies the known shared alignment of X and Y. 
3243
3244    MODE is the mode of the inputs (in case they are const_int).
3245
3246    COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).  It will
3247    be passed unchanged to emit_cmp_insn, then potentially converted into an
3248    unsigned variant based on UNSIGNEDP to select a proper jump instruction.  */
3249
3250 void
3251 emit_cmp_and_jump_insns (x, y, comparison, size, mode, unsignedp, align, label)
3252      rtx x, y;
3253      enum rtx_code comparison;
3254      rtx size;
3255      enum machine_mode mode;
3256      int unsignedp;
3257      int align;
3258      rtx label;
3259 {
3260   rtx op0;
3261   rtx op1;
3262           
3263   if (CONSTANT_P (x))
3264     {
3265       /* Swap operands and condition to ensure canonical RTL.  */
3266       op0 = y;
3267       op1 = x;
3268       comparison = swap_condition (comparison);
3269     }
3270   else
3271     {
3272       op0 = x;
3273       op1 = y;
3274     }
3275
3276 #ifdef HAVE_cc0
3277   /* If OP0 is still a constant, then both X and Y must be constants.  Force
3278      X into a register to avoid aborting in emit_cmp_insn due to non-canonical
3279      RTL.  */
3280   if (CONSTANT_P (op0))
3281     op0 = force_reg (mode, op0);
3282 #endif
3283
3284   emit_cmp_insn (op0, op1, comparison, size, mode, unsignedp, align);
3285
3286   if (unsignedp)
3287     comparison = unsigned_condition (comparison);
3288   emit_jump_insn ((*bcc_gen_fctn[(int) comparison]) (label));
3289 }
3290
3291
3292 /* Nonzero if a compare of mode MODE can be done straightforwardly
3293    (without splitting it into pieces).  */
3294
3295 int
3296 can_compare_p (mode)
3297      enum machine_mode mode;
3298 {
3299   do
3300     {
3301       if (cmp_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)
3302         return 1;
3303       mode = GET_MODE_WIDER_MODE (mode);
3304     } while (mode != VOIDmode);
3305
3306   return 0;
3307 }
3308 \f
3309 /* Emit a library call comparison between floating point X and Y.
3310    COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).  */
3311
3312 void
3313 emit_float_lib_cmp (x, y, comparison)
3314      rtx x, y;
3315      enum rtx_code comparison;
3316 {
3317   enum machine_mode mode = GET_MODE (x);
3318   rtx libfunc = 0;
3319   rtx result;
3320
3321   if (mode == HFmode)
3322     switch (comparison)
3323       {
3324       case EQ:
3325         libfunc = eqhf2_libfunc;
3326         break;
3327
3328       case NE:
3329         libfunc = nehf2_libfunc;
3330         break;
3331
3332       case GT:
3333         libfunc = gthf2_libfunc;
3334         break;
3335
3336       case GE:
3337         libfunc = gehf2_libfunc;
3338         break;
3339
3340       case LT:
3341         libfunc = lthf2_libfunc;
3342         break;
3343
3344       case LE:
3345         libfunc = lehf2_libfunc;
3346         break;
3347
3348       default:
3349         break;
3350       }
3351   else if (mode == SFmode)
3352     switch (comparison)
3353       {
3354       case EQ:
3355         libfunc = eqsf2_libfunc;
3356         break;
3357
3358       case NE:
3359         libfunc = nesf2_libfunc;
3360         break;
3361
3362       case GT:
3363         libfunc = gtsf2_libfunc;
3364         break;
3365
3366       case GE:
3367         libfunc = gesf2_libfunc;
3368         break;
3369
3370       case LT:
3371         libfunc = ltsf2_libfunc;
3372         break;
3373
3374       case LE:
3375         libfunc = lesf2_libfunc;
3376         break;
3377
3378       default:
3379         break;
3380       }
3381   else if (mode == DFmode)
3382     switch (comparison)
3383       {
3384       case EQ:
3385         libfunc = eqdf2_libfunc;
3386         break;
3387
3388       case NE:
3389         libfunc = nedf2_libfunc;
3390         break;
3391
3392       case GT:
3393         libfunc = gtdf2_libfunc;
3394         break;
3395
3396       case GE:
3397         libfunc = gedf2_libfunc;
3398         break;
3399
3400       case LT:
3401         libfunc = ltdf2_libfunc;
3402         break;
3403
3404       case LE:
3405         libfunc = ledf2_libfunc;
3406         break;
3407
3408       default:
3409         break;
3410       }
3411   else if (mode == XFmode)
3412     switch (comparison)
3413       {
3414       case EQ:
3415         libfunc = eqxf2_libfunc;
3416         break;
3417
3418       case NE:
3419         libfunc = nexf2_libfunc;
3420         break;
3421
3422       case GT:
3423         libfunc = gtxf2_libfunc;
3424         break;
3425
3426       case GE:
3427         libfunc = gexf2_libfunc;
3428         break;
3429
3430       case LT:
3431         libfunc = ltxf2_libfunc;
3432         break;
3433
3434       case LE:
3435         libfunc = lexf2_libfunc;
3436         break;
3437
3438       default:
3439         break;
3440       }
3441   else if (mode == TFmode)
3442     switch (comparison)
3443       {
3444       case EQ:
3445         libfunc = eqtf2_libfunc;
3446         break;
3447
3448       case NE:
3449         libfunc = netf2_libfunc;
3450         break;
3451
3452       case GT:
3453         libfunc = gttf2_libfunc;
3454         break;
3455
3456       case GE:
3457         libfunc = getf2_libfunc;
3458         break;
3459
3460       case LT:
3461         libfunc = lttf2_libfunc;
3462         break;
3463
3464       case LE:
3465         libfunc = letf2_libfunc;
3466         break;
3467
3468       default:
3469         break;
3470       }
3471   else
3472     {
3473       enum machine_mode wider_mode;
3474
3475       for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
3476            wider_mode = GET_MODE_WIDER_MODE (wider_mode))
3477         {
3478           if ((cmp_optab->handlers[(int) wider_mode].insn_code
3479                != CODE_FOR_nothing)
3480               || (cmp_optab->handlers[(int) wider_mode].libfunc != 0))
3481             {
3482               x = protect_from_queue (x, 0);
3483               y = protect_from_queue (y, 0);
3484               x = convert_to_mode (wider_mode, x, 0);
3485               y = convert_to_mode (wider_mode, y, 0);
3486               emit_float_lib_cmp (x, y, comparison);
3487               return;
3488             }
3489         }
3490       abort ();
3491     }
3492
3493   if (libfunc == 0)
3494     abort ();
3495
3496   emit_library_call (libfunc, 1,
3497                      word_mode, 2, x, mode, y, mode);
3498
3499   /* Immediately move the result of the libcall into a pseudo
3500      register so reload doesn't clobber the value if it needs
3501      the return register for a spill reg.  */
3502   result = gen_reg_rtx (word_mode);
3503   emit_move_insn (result, hard_libcall_value (word_mode));
3504
3505   emit_cmp_insn (result, const0_rtx, comparison,
3506                  NULL_RTX, word_mode, 0, 0);
3507 }
3508 \f
3509 /* Generate code to indirectly jump to a location given in the rtx LOC.  */
3510
3511 void
3512 emit_indirect_jump (loc)
3513      rtx loc;
3514 {
3515   if (! ((*insn_operand_predicate[(int)CODE_FOR_indirect_jump][0])
3516          (loc, Pmode)))
3517     loc = copy_to_mode_reg (Pmode, loc);
3518
3519   emit_jump_insn (gen_indirect_jump (loc));
3520   emit_barrier ();
3521 }
3522 \f
3523 #ifdef HAVE_conditional_move
3524
3525 /* Emit a conditional move instruction if the machine supports one for that
3526    condition and machine mode.
3527
3528    OP0 and OP1 are the operands that should be compared using CODE.  CMODE is
3529    the mode to use should they be constants.  If it is VOIDmode, they cannot
3530    both be constants.
3531
3532    OP2 should be stored in TARGET if the comparison is true, otherwise OP3
3533    should be stored there.  MODE is the mode to use should they be constants.
3534    If it is VOIDmode, they cannot both be constants.
3535
3536    The result is either TARGET (perhaps modified) or NULL_RTX if the operation
3537    is not supported.  */
3538
3539 rtx
3540 emit_conditional_move (target, code, op0, op1, cmode, op2, op3, mode,
3541                        unsignedp)
3542      rtx target;
3543      enum rtx_code code;
3544      rtx op0, op1;
3545      enum machine_mode cmode;
3546      rtx op2, op3;
3547      enum machine_mode mode;
3548      int unsignedp;
3549 {
3550   rtx tem, subtarget, comparison, insn;
3551   enum insn_code icode;
3552
3553   /* If one operand is constant, make it the second one.  Only do this
3554      if the other operand is not constant as well.  */
3555
3556   if ((CONSTANT_P (op0) && ! CONSTANT_P (op1))
3557       || (GET_CODE (op0) == CONST_INT && GET_CODE (op1) != CONST_INT))
3558     {
3559       tem = op0;
3560       op0 = op1;
3561       op1 = tem;
3562       code = swap_condition (code);
3563     }
3564
3565   if (cmode == VOIDmode)
3566     cmode = GET_MODE (op0);
3567
3568   if (((CONSTANT_P (op2) && ! CONSTANT_P (op3))
3569        || (GET_CODE (op2) == CONST_INT && GET_CODE (op3) != CONST_INT))
3570       && (GET_MODE_CLASS (GET_MODE (op1)) != MODE_FLOAT
3571           || TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT || flag_fast_math))
3572     {
3573       tem = op2;
3574       op2 = op3;
3575       op3 = tem;
3576       code = reverse_condition (code);
3577     }
3578
3579   if (mode == VOIDmode)
3580     mode = GET_MODE (op2);
3581
3582   icode = movcc_gen_code[mode];
3583
3584   if (icode == CODE_FOR_nothing)
3585     return 0;
3586
3587   if (flag_force_mem)
3588     {
3589       op2 = force_not_mem (op2);
3590       op3 = force_not_mem (op3);
3591     }
3592
3593   if (target)
3594     target = protect_from_queue (target, 1);
3595   else
3596     target = gen_reg_rtx (mode);
3597
3598   subtarget = target;
3599
3600   emit_queue ();
3601
3602   op2 = protect_from_queue (op2, 0);
3603   op3 = protect_from_queue (op3, 0);
3604
3605   /* If the insn doesn't accept these operands, put them in pseudos.  */
3606
3607   if (! (*insn_operand_predicate[icode][0])
3608       (subtarget, insn_operand_mode[icode][0]))
3609     subtarget = gen_reg_rtx (insn_operand_mode[icode][0]);
3610
3611   if (! (*insn_operand_predicate[icode][2])
3612       (op2, insn_operand_mode[icode][2]))
3613     op2 = copy_to_mode_reg (insn_operand_mode[icode][2], op2);
3614
3615   if (! (*insn_operand_predicate[icode][3])
3616       (op3, insn_operand_mode[icode][3]))
3617     op3 = copy_to_mode_reg (insn_operand_mode[icode][3], op3);
3618
3619   /* Everything should now be in the suitable form, so emit the compare insn
3620      and then the conditional move.  */
3621
3622   comparison 
3623     = compare_from_rtx (op0, op1, code, unsignedp, cmode, NULL_RTX, 0);
3624
3625   /* ??? Watch for const0_rtx (nop) and const_true_rtx (unconditional)?  */
3626   if (GET_CODE (comparison) != code)
3627     /* This shouldn't happen.  */
3628     abort ();
3629   
3630   insn = GEN_FCN (icode) (subtarget, comparison, op2, op3);
3631
3632   /* If that failed, then give up.  */
3633   if (insn == 0)
3634     return 0;
3635
3636   emit_insn (insn);
3637
3638   if (subtarget != target)
3639     convert_move (target, subtarget, 0);
3640
3641   return target;
3642 }
3643
3644 /* Return non-zero if a conditional move of mode MODE is supported.
3645
3646    This function is for combine so it can tell whether an insn that looks
3647    like a conditional move is actually supported by the hardware.  If we
3648    guess wrong we lose a bit on optimization, but that's it.  */
3649 /* ??? sparc64 supports conditionally moving integers values based on fp
3650    comparisons, and vice versa.  How do we handle them?  */
3651
3652 int
3653 can_conditionally_move_p (mode)
3654      enum machine_mode mode;
3655 {
3656   if (movcc_gen_code[mode] != CODE_FOR_nothing)
3657     return 1;
3658
3659   return 0;
3660 }
3661
3662 #endif /* HAVE_conditional_move */
3663 \f
3664 /* These three functions generate an insn body and return it
3665    rather than emitting the insn.
3666
3667    They do not protect from queued increments,
3668    because they may be used 1) in protect_from_queue itself
3669    and 2) in other passes where there is no queue.  */
3670
3671 /* Generate and return an insn body to add Y to X.  */
3672
3673 rtx
3674 gen_add2_insn (x, y)
3675      rtx x, y;
3676 {
3677   int icode = (int) add_optab->handlers[(int) GET_MODE (x)].insn_code; 
3678
3679   if (! (*insn_operand_predicate[icode][0]) (x, insn_operand_mode[icode][0])
3680       || ! (*insn_operand_predicate[icode][1]) (x, insn_operand_mode[icode][1])
3681       || ! (*insn_operand_predicate[icode][2]) (y, insn_operand_mode[icode][2]))
3682     abort ();
3683
3684   return (GEN_FCN (icode) (x, x, y));
3685 }
3686
3687 int
3688 have_add2_insn (mode)
3689      enum machine_mode mode;
3690 {
3691   return add_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing;
3692 }
3693
3694 /* Generate and return an insn body to subtract Y from X.  */
3695
3696 rtx
3697 gen_sub2_insn (x, y)
3698      rtx x, y;
3699 {
3700   int icode = (int) sub_optab->handlers[(int) GET_MODE (x)].insn_code; 
3701
3702   if (! (*insn_operand_predicate[icode][0]) (x, insn_operand_mode[icode][0])
3703       || ! (*insn_operand_predicate[icode][1]) (x, insn_operand_mode[icode][1])
3704       || ! (*insn_operand_predicate[icode][2]) (y, insn_operand_mode[icode][2]))
3705     abort ();
3706
3707   return (GEN_FCN (icode) (x, x, y));
3708 }
3709
3710 int
3711 have_sub2_insn (mode)
3712      enum machine_mode mode;
3713 {
3714   return sub_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing;
3715 }
3716
3717 /* Generate the body of an instruction to copy Y into X.
3718    It may be a SEQUENCE, if one insn isn't enough.  */
3719
3720 rtx
3721 gen_move_insn (x, y)
3722      rtx x, y;
3723 {
3724   register enum machine_mode mode = GET_MODE (x);
3725   enum insn_code insn_code;
3726   rtx seq;
3727
3728   if (mode == VOIDmode)
3729     mode = GET_MODE (y); 
3730
3731   insn_code = mov_optab->handlers[(int) mode].insn_code;
3732
3733   /* Handle MODE_CC modes:  If we don't have a special move insn for this mode,
3734      find a mode to do it in.  If we have a movcc, use it.  Otherwise,
3735      find the MODE_INT mode of the same width.  */
3736
3737   if (GET_MODE_CLASS (mode) == MODE_CC && insn_code == CODE_FOR_nothing)
3738     {
3739       enum machine_mode tmode = VOIDmode;
3740       rtx x1 = x, y1 = y;
3741
3742       if (mode != CCmode
3743           && mov_optab->handlers[(int) CCmode].insn_code != CODE_FOR_nothing)
3744         tmode = CCmode;
3745       else
3746         for (tmode = QImode; tmode != VOIDmode;
3747              tmode = GET_MODE_WIDER_MODE (tmode))
3748           if (GET_MODE_SIZE (tmode) == GET_MODE_SIZE (mode))
3749             break;
3750
3751       if (tmode == VOIDmode)
3752         abort ();
3753
3754       /* Get X and Y in TMODE.  We can't use gen_lowpart here because it
3755          may call change_address which is not appropriate if we were
3756          called when a reload was in progress.  We don't have to worry
3757          about changing the address since the size in bytes is supposed to
3758          be the same.  Copy the MEM to change the mode and move any
3759          substitutions from the old MEM to the new one.  */
3760
3761       if (reload_in_progress)
3762         {
3763           x = gen_lowpart_common (tmode, x1);
3764           if (x == 0 && GET_CODE (x1) == MEM)
3765             {
3766               x = gen_rtx_MEM (tmode, XEXP (x1, 0));
3767               RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (x1);
3768               MEM_COPY_ATTRIBUTES (x, x1);
3769               copy_replacements (x1, x);
3770             }
3771
3772           y = gen_lowpart_common (tmode, y1);
3773           if (y == 0 && GET_CODE (y1) == MEM)
3774             {
3775               y = gen_rtx_MEM (tmode, XEXP (y1, 0));
3776               RTX_UNCHANGING_P (y) = RTX_UNCHANGING_P (y1);
3777               MEM_COPY_ATTRIBUTES (y, y1);
3778               copy_replacements (y1, y);
3779             }
3780         }
3781       else
3782         {
3783           x = gen_lowpart (tmode, x);
3784           y = gen_lowpart (tmode, y);
3785         }
3786           
3787       insn_code = mov_optab->handlers[(int) tmode].insn_code;
3788       return (GEN_FCN (insn_code) (x, y));
3789     }
3790
3791   start_sequence ();
3792   emit_move_insn_1 (x, y);
3793   seq = gen_sequence ();
3794   end_sequence ();
3795   return seq;
3796 }
3797 \f
3798 /* Return the insn code used to extend FROM_MODE to TO_MODE.
3799    UNSIGNEDP specifies zero-extension instead of sign-extension.  If
3800    no such operation exists, CODE_FOR_nothing will be returned.  */
3801
3802 enum insn_code
3803 can_extend_p (to_mode, from_mode, unsignedp)
3804      enum machine_mode to_mode, from_mode;
3805      int unsignedp;
3806 {
3807   return extendtab[(int) to_mode][(int) from_mode][unsignedp];
3808 }
3809
3810 /* Generate the body of an insn to extend Y (with mode MFROM)
3811    into X (with mode MTO).  Do zero-extension if UNSIGNEDP is nonzero.  */
3812
3813 rtx
3814 gen_extend_insn (x, y, mto, mfrom, unsignedp)
3815      rtx x, y;
3816      enum machine_mode mto, mfrom;
3817      int unsignedp;
3818 {
3819   return (GEN_FCN (extendtab[(int) mto][(int) mfrom][unsignedp]) (x, y));
3820 }
3821 \f
3822 /* can_fix_p and can_float_p say whether the target machine
3823    can directly convert a given fixed point type to
3824    a given floating point type, or vice versa.
3825    The returned value is the CODE_FOR_... value to use,
3826    or CODE_FOR_nothing if these modes cannot be directly converted.
3827
3828    *TRUNCP_PTR is set to 1 if it is necessary to output
3829    an explicit FTRUNC insn before the fix insn; otherwise 0.  */
3830
3831 static enum insn_code
3832 can_fix_p (fixmode, fltmode, unsignedp, truncp_ptr)
3833      enum machine_mode fltmode, fixmode;
3834      int unsignedp;
3835      int *truncp_ptr;
3836 {
3837   *truncp_ptr = 0;
3838   if (fixtrunctab[(int) fltmode][(int) fixmode][unsignedp] != CODE_FOR_nothing)
3839     return fixtrunctab[(int) fltmode][(int) fixmode][unsignedp];
3840
3841   if (ftrunc_optab->handlers[(int) fltmode].insn_code != CODE_FOR_nothing)
3842     {
3843       *truncp_ptr = 1;
3844       return fixtab[(int) fltmode][(int) fixmode][unsignedp];
3845     }
3846   return CODE_FOR_nothing;
3847 }
3848
3849 static enum insn_code
3850 can_float_p (fltmode, fixmode, unsignedp)
3851      enum machine_mode fixmode, fltmode;
3852      int unsignedp;
3853 {
3854   return floattab[(int) fltmode][(int) fixmode][unsignedp];
3855 }
3856 \f
3857 /* Generate code to convert FROM to floating point
3858    and store in TO.  FROM must be fixed point and not VOIDmode.
3859    UNSIGNEDP nonzero means regard FROM as unsigned.
3860    Normally this is done by correcting the final value
3861    if it is negative.  */
3862
3863 void
3864 expand_float (to, from, unsignedp)
3865      rtx to, from;
3866      int unsignedp;
3867 {
3868   enum insn_code icode;
3869   register rtx target = to;
3870   enum machine_mode fmode, imode;
3871
3872   /* Crash now, because we won't be able to decide which mode to use.  */
3873   if (GET_MODE (from) == VOIDmode)
3874     abort ();
3875
3876   /* Look for an insn to do the conversion.  Do it in the specified
3877      modes if possible; otherwise convert either input, output or both to
3878      wider mode.  If the integer mode is wider than the mode of FROM,
3879      we can do the conversion signed even if the input is unsigned.  */
3880
3881   for (imode = GET_MODE (from); imode != VOIDmode;
3882        imode = GET_MODE_WIDER_MODE (imode))
3883     for (fmode = GET_MODE (to); fmode != VOIDmode;
3884          fmode = GET_MODE_WIDER_MODE (fmode))
3885       {
3886         int doing_unsigned = unsignedp;
3887
3888         icode = can_float_p (fmode, imode, unsignedp);
3889         if (icode == CODE_FOR_nothing && imode != GET_MODE (from) && unsignedp)
3890           icode = can_float_p (fmode, imode, 0), doing_unsigned = 0;
3891
3892         if (icode != CODE_FOR_nothing)
3893           {
3894             to = protect_from_queue (to, 1);
3895             from = protect_from_queue (from, 0);
3896
3897             if (imode != GET_MODE (from))
3898               from = convert_to_mode (imode, from, unsignedp);
3899
3900             if (fmode != GET_MODE (to))
3901               target = gen_reg_rtx (fmode);
3902
3903             emit_unop_insn (icode, target, from,
3904                             doing_unsigned ? UNSIGNED_FLOAT : FLOAT);
3905
3906             if (target != to)
3907               convert_move (to, target, 0);
3908             return;
3909           }
3910     }
3911
3912 #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
3913
3914   /* Unsigned integer, and no way to convert directly.
3915      Convert as signed, then conditionally adjust the result.  */
3916   if (unsignedp)
3917     {
3918       rtx label = gen_label_rtx ();
3919       rtx temp;
3920       REAL_VALUE_TYPE offset;
3921
3922       emit_queue ();
3923
3924       to = protect_from_queue (to, 1);
3925       from = protect_from_queue (from, 0);
3926
3927       if (flag_force_mem)
3928         from = force_not_mem (from);
3929
3930       /* Look for a usable floating mode FMODE wider than the source and at
3931          least as wide as the target.  Using FMODE will avoid rounding woes
3932          with unsigned values greater than the signed maximum value.  */
3933
3934       for (fmode = GET_MODE (to);  fmode != VOIDmode;
3935            fmode = GET_MODE_WIDER_MODE (fmode))
3936         if (GET_MODE_BITSIZE (GET_MODE (from)) < GET_MODE_BITSIZE (fmode)
3937             && can_float_p (fmode, GET_MODE (from), 0) != CODE_FOR_nothing)
3938           break;
3939
3940       if (fmode == VOIDmode)
3941         {
3942           /* There is no such mode.  Pretend the target is wide enough.  */
3943           fmode = GET_MODE (to);
3944
3945           /* Avoid double-rounding when TO is narrower than FROM.  */
3946           if ((significand_size (fmode) + 1)
3947               < GET_MODE_BITSIZE (GET_MODE (from)))
3948             {
3949               rtx temp1;
3950               rtx neglabel = gen_label_rtx ();
3951
3952               /* Don't use TARGET if it isn't a register, is a hard register, 
3953                  or is the wrong mode.  */
3954               if (GET_CODE (target) != REG
3955                   || REGNO (target) < FIRST_PSEUDO_REGISTER
3956                   || GET_MODE (target) != fmode)
3957                 target = gen_reg_rtx (fmode);
3958
3959               imode = GET_MODE (from);
3960               do_pending_stack_adjust ();
3961
3962               /* Test whether the sign bit is set.  */
3963               emit_cmp_insn (from, const0_rtx, GE, NULL_RTX, imode, 0, 0);
3964               emit_jump_insn (gen_blt (neglabel));
3965
3966               /* The sign bit is not set.  Convert as signed.  */
3967               expand_float (target, from, 0);
3968               emit_jump_insn (gen_jump (label));
3969               emit_barrier ();
3970
3971               /* The sign bit is set.
3972                  Convert to a usable (positive signed) value by shifting right
3973                  one bit, while remembering if a nonzero bit was shifted
3974                  out; i.e., compute  (from & 1) | (from >> 1).  */
3975
3976               emit_label (neglabel);
3977               temp = expand_binop (imode, and_optab, from, const1_rtx,
3978                                    NULL_RTX, 1, OPTAB_LIB_WIDEN);
3979               temp1 = expand_shift (RSHIFT_EXPR, imode, from, integer_one_node,
3980                                     NULL_RTX, 1);
3981               temp = expand_binop (imode, ior_optab, temp, temp1, temp, 1, 
3982                                    OPTAB_LIB_WIDEN);
3983               expand_float (target, temp, 0);
3984
3985               /* Multiply by 2 to undo the shift above.  */
3986               temp = expand_binop (fmode, add_optab, target, target,
3987                                      target, 0, OPTAB_LIB_WIDEN);
3988               if (temp != target)
3989                 emit_move_insn (target, temp);
3990
3991               do_pending_stack_adjust ();
3992               emit_label (label);
3993               goto done;
3994             }
3995         }
3996
3997       /* If we are about to do some arithmetic to correct for an
3998          unsigned operand, do it in a pseudo-register.  */
3999
4000       if (GET_MODE (to) != fmode
4001           || GET_CODE (to) != REG || REGNO (to) < FIRST_PSEUDO_REGISTER)
4002         target = gen_reg_rtx (fmode);
4003
4004       /* Convert as signed integer to floating.  */
4005       expand_float (target, from, 0);
4006
4007       /* If FROM is negative (and therefore TO is negative),
4008          correct its value by 2**bitwidth.  */
4009
4010       do_pending_stack_adjust ();
4011       emit_cmp_and_jump_insns (from, const0_rtx, GE, NULL_RTX, GET_MODE (from),
4012                                 0, 0, label);
4013
4014       /* On SCO 3.2.1, ldexp rejects values outside [0.5, 1).
4015          Rather than setting up a dconst_dot_5, let's hope SCO
4016          fixes the bug.  */
4017       offset = REAL_VALUE_LDEXP (dconst1, GET_MODE_BITSIZE (GET_MODE (from)));
4018       temp = expand_binop (fmode, add_optab, target,
4019                            CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode),
4020                            target, 0, OPTAB_LIB_WIDEN);
4021       if (temp != target)
4022         emit_move_insn (target, temp);
4023
4024       do_pending_stack_adjust ();
4025       emit_label (label);
4026       goto done;
4027     }
4028 #endif
4029
4030   /* No hardware instruction available; call a library routine to convert from
4031      SImode, DImode, or TImode into SFmode, DFmode, XFmode, or TFmode.  */
4032     {
4033       rtx libfcn;
4034       rtx insns;
4035       rtx value;
4036
4037       to = protect_from_queue (to, 1);
4038       from = protect_from_queue (from, 0);
4039
4040       if (GET_MODE_SIZE (GET_MODE (from)) < GET_MODE_SIZE (SImode))
4041         from = convert_to_mode (SImode, from, unsignedp);
4042
4043       if (flag_force_mem)
4044         from = force_not_mem (from);
4045
4046       if (GET_MODE (to) == SFmode)
4047         {
4048           if (GET_MODE (from) == SImode)
4049             libfcn = floatsisf_libfunc;
4050           else if (GET_MODE (from) == DImode)
4051             libfcn = floatdisf_libfunc;
4052           else if (GET_MODE (from) == TImode)
4053             libfcn = floattisf_libfunc;
4054           else
4055             abort ();
4056         }
4057       else if (GET_MODE (to) == DFmode)
4058         {
4059           if (GET_MODE (from) == SImode)
4060             libfcn = floatsidf_libfunc;
4061           else if (GET_MODE (from) == DImode)
4062             libfcn = floatdidf_libfunc;
4063           else if (GET_MODE (from) == TImode)
4064             libfcn = floattidf_libfunc;
4065           else
4066             abort ();
4067         }
4068       else if (GET_MODE (to) == XFmode)
4069         {
4070           if (GET_MODE (from) == SImode)
4071             libfcn = floatsixf_libfunc;
4072           else if (GET_MODE (from) == DImode)
4073             libfcn = floatdixf_libfunc;
4074           else if (GET_MODE (from) == TImode)
4075             libfcn = floattixf_libfunc;
4076           else
4077             abort ();
4078         }
4079       else if (GET_MODE (to) == TFmode)
4080         {
4081           if (GET_MODE (from) == SImode)
4082             libfcn = floatsitf_libfunc;
4083           else if (GET_MODE (from) == DImode)
4084             libfcn = floatditf_libfunc;
4085           else if (GET_MODE (from) == TImode)
4086             libfcn = floattitf_libfunc;
4087           else
4088             abort ();
4089         }
4090       else
4091         abort ();
4092
4093       start_sequence ();
4094
4095       value = emit_library_call_value (libfcn, NULL_RTX, 1,
4096                                        GET_MODE (to),
4097                                        1, from, GET_MODE (from));
4098       insns = get_insns ();
4099       end_sequence ();
4100
4101       emit_libcall_block (insns, target, value,
4102                           gen_rtx_FLOAT (GET_MODE (to), from));
4103     }
4104
4105  done:
4106
4107   /* Copy result to requested destination
4108      if we have been computing in a temp location.  */
4109
4110   if (target != to)
4111     {
4112       if (GET_MODE (target) == GET_MODE (to))
4113         emit_move_insn (to, target);
4114       else
4115         convert_move (to, target, 0);
4116     }
4117 }
4118 \f
4119 /* expand_fix: generate code to convert FROM to fixed point
4120    and store in TO.  FROM must be floating point.  */
4121
4122 static rtx
4123 ftruncify (x)
4124      rtx x;
4125 {
4126   rtx temp = gen_reg_rtx (GET_MODE (x));
4127   return expand_unop (GET_MODE (x), ftrunc_optab, x, temp, 0);
4128 }
4129
4130 void
4131 expand_fix (to, from, unsignedp)
4132      register rtx to, from;
4133      int unsignedp;
4134 {
4135   enum insn_code icode;
4136   register rtx target = to;
4137   enum machine_mode fmode, imode;
4138   int must_trunc = 0;
4139   rtx libfcn = 0;
4140
4141   /* We first try to find a pair of modes, one real and one integer, at
4142      least as wide as FROM and TO, respectively, in which we can open-code
4143      this conversion.  If the integer mode is wider than the mode of TO,
4144      we can do the conversion either signed or unsigned.  */
4145
4146   for (imode = GET_MODE (to); imode != VOIDmode;
4147        imode = GET_MODE_WIDER_MODE (imode))
4148     for (fmode = GET_MODE (from); fmode != VOIDmode;
4149          fmode = GET_MODE_WIDER_MODE (fmode))
4150       {
4151         int doing_unsigned = unsignedp;
4152
4153         icode = can_fix_p (imode, fmode, unsignedp, &must_trunc);
4154         if (icode == CODE_FOR_nothing && imode != GET_MODE (to) && unsignedp)
4155           icode = can_fix_p (imode, fmode, 0, &must_trunc), doing_unsigned = 0;
4156
4157         if (icode != CODE_FOR_nothing)
4158           {
4159             to = protect_from_queue (to, 1);
4160             from = protect_from_queue (from, 0);
4161
4162             if (fmode != GET_MODE (from))
4163               from = convert_to_mode (fmode, from, 0);
4164
4165             if (must_trunc)
4166               from = ftruncify (from);
4167
4168             if (imode != GET_MODE (to))
4169               target = gen_reg_rtx (imode);
4170
4171             emit_unop_insn (icode, target, from,
4172                             doing_unsigned ? UNSIGNED_FIX : FIX);
4173             if (target != to)
4174               convert_move (to, target, unsignedp);
4175             return;
4176           }
4177       }
4178
4179 #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
4180   /* For an unsigned conversion, there is one more way to do it.
4181      If we have a signed conversion, we generate code that compares
4182      the real value to the largest representable positive number.  If if
4183      is smaller, the conversion is done normally.  Otherwise, subtract
4184      one plus the highest signed number, convert, and add it back.
4185
4186      We only need to check all real modes, since we know we didn't find
4187      anything with a wider integer mode.  */
4188
4189   if (unsignedp && GET_MODE_BITSIZE (GET_MODE (to)) <= HOST_BITS_PER_WIDE_INT)
4190     for (fmode = GET_MODE (from); fmode != VOIDmode;
4191          fmode = GET_MODE_WIDER_MODE (fmode))
4192       /* Make sure we won't lose significant bits doing this.  */
4193       if (GET_MODE_BITSIZE (fmode) > GET_MODE_BITSIZE (GET_MODE (to))
4194           && CODE_FOR_nothing != can_fix_p (GET_MODE (to), fmode, 0,
4195                                             &must_trunc))
4196         {
4197           int bitsize;
4198           REAL_VALUE_TYPE offset;
4199           rtx limit, lab1, lab2, insn;
4200
4201           bitsize = GET_MODE_BITSIZE (GET_MODE (to));
4202           offset = REAL_VALUE_LDEXP (dconst1, bitsize - 1);
4203           limit = CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode);
4204           lab1 = gen_label_rtx ();
4205           lab2 = gen_label_rtx ();
4206
4207           emit_queue ();
4208           to = protect_from_queue (to, 1);
4209           from = protect_from_queue (from, 0);
4210
4211           if (flag_force_mem)
4212             from = force_not_mem (from);
4213
4214           if (fmode != GET_MODE (from))
4215             from = convert_to_mode (fmode, from, 0);
4216
4217           /* See if we need to do the subtraction.  */
4218           do_pending_stack_adjust ();
4219           emit_cmp_and_jump_insns (from, limit, GE, NULL_RTX, GET_MODE (from),
4220                                    0, 0, lab1);
4221
4222           /* If not, do the signed "fix" and branch around fixup code.  */
4223           expand_fix (to, from, 0);
4224           emit_jump_insn (gen_jump (lab2));
4225           emit_barrier ();
4226
4227           /* Otherwise, subtract 2**(N-1), convert to signed number,
4228              then add 2**(N-1).  Do the addition using XOR since this
4229              will often generate better code.  */
4230           emit_label (lab1);
4231           target = expand_binop (GET_MODE (from), sub_optab, from, limit,
4232                                  NULL_RTX, 0, OPTAB_LIB_WIDEN);
4233           expand_fix (to, target, 0);
4234           target = expand_binop (GET_MODE (to), xor_optab, to,
4235                                  GEN_INT ((HOST_WIDE_INT) 1 << (bitsize - 1)),
4236                                  to, 1, OPTAB_LIB_WIDEN);
4237
4238           if (target != to)
4239             emit_move_insn (to, target);
4240
4241           emit_label (lab2);
4242
4243           if (mov_optab->handlers[(int) GET_MODE (to)].insn_code
4244               != CODE_FOR_nothing)
4245             {
4246               /* Make a place for a REG_NOTE and add it.  */
4247               insn = emit_move_insn (to, to);
4248               set_unique_reg_note (insn,
4249                                    REG_EQUAL,
4250                                    gen_rtx_fmt_e (UNSIGNED_FIX,
4251                                                   GET_MODE (to),
4252                                                   copy_rtx (from)));
4253             }
4254           return;
4255         }
4256 #endif
4257
4258   /* We can't do it with an insn, so use a library call.  But first ensure
4259      that the mode of TO is at least as wide as SImode, since those are the
4260      only library calls we know about.  */
4261
4262   if (GET_MODE_SIZE (GET_MODE (to)) < GET_MODE_SIZE (SImode))
4263     {
4264       target = gen_reg_rtx (SImode);
4265
4266       expand_fix (target, from, unsignedp);
4267     }
4268   else if (GET_MODE (from) == SFmode)
4269     {
4270       if (GET_MODE (to) == SImode)
4271         libfcn = unsignedp ? fixunssfsi_libfunc : fixsfsi_libfunc;
4272       else if (GET_MODE (to) == DImode)
4273         libfcn = unsignedp ? fixunssfdi_libfunc : fixsfdi_libfunc;
4274       else if (GET_MODE (to) == TImode)
4275         libfcn = unsignedp ? fixunssfti_libfunc : fixsfti_libfunc;
4276       else
4277         abort ();
4278     }
4279   else if (GET_MODE (from) == DFmode)
4280     {
4281       if (GET_MODE (to) == SImode)
4282         libfcn = unsignedp ? fixunsdfsi_libfunc : fixdfsi_libfunc;
4283       else if (GET_MODE (to) == DImode)
4284         libfcn = unsignedp ? fixunsdfdi_libfunc : fixdfdi_libfunc;
4285       else if (GET_MODE (to) == TImode)
4286         libfcn = unsignedp ? fixunsdfti_libfunc : fixdfti_libfunc;
4287       else
4288         abort ();
4289     }
4290   else if (GET_MODE (from) == XFmode)
4291     {
4292       if (GET_MODE (to) == SImode)
4293         libfcn = unsignedp ? fixunsxfsi_libfunc : fixxfsi_libfunc;
4294       else if (GET_MODE (to) == DImode)
4295         libfcn = unsignedp ? fixunsxfdi_libfunc : fixxfdi_libfunc;
4296       else if (GET_MODE (to) == TImode)
4297         libfcn = unsignedp ? fixunsxfti_libfunc : fixxfti_libfunc;
4298       else
4299         abort ();
4300     }
4301   else if (GET_MODE (from) == TFmode)
4302     {
4303       if (GET_MODE (to) == SImode)
4304         libfcn = unsignedp ? fixunstfsi_libfunc : fixtfsi_libfunc;
4305       else if (GET_MODE (to) == DImode)
4306         libfcn = unsignedp ? fixunstfdi_libfunc : fixtfdi_libfunc;
4307       else if (GET_MODE (to) == TImode)
4308         libfcn = unsignedp ? fixunstfti_libfunc : fixtfti_libfunc;
4309       else
4310         abort ();
4311     }
4312   else
4313     abort ();
4314
4315   if (libfcn)
4316     {
4317       rtx insns;
4318       rtx value;
4319
4320       to = protect_from_queue (to, 1);
4321       from = protect_from_queue (from, 0);
4322
4323       if (flag_force_mem)
4324         from = force_not_mem (from);
4325
4326       start_sequence ();
4327
4328       value = emit_library_call_value (libfcn, NULL_RTX, 1, GET_MODE (to),
4329
4330                                        1, from, GET_MODE (from));
4331       insns = get_insns ();
4332       end_sequence ();
4333
4334       emit_libcall_block (insns, target, value,
4335                           gen_rtx_fmt_e (unsignedp ? UNSIGNED_FIX : FIX,
4336                                          GET_MODE (to), from));
4337     }
4338       
4339   if (target != to)
4340     {
4341       if (GET_MODE (to) == GET_MODE (target))
4342         emit_move_insn (to, target);
4343       else
4344         convert_move (to, target, 0);
4345     }
4346 }
4347 \f
4348 static optab
4349 init_optab (code)
4350      enum rtx_code code;
4351 {
4352   int i;
4353   optab op = (optab) xmalloc (sizeof (struct optab));
4354   op->code = code;
4355   for (i = 0; i < NUM_MACHINE_MODES; i++)
4356     {
4357       op->handlers[i].insn_code = CODE_FOR_nothing;
4358       op->handlers[i].libfunc = 0;
4359     }
4360
4361   if (code != UNKNOWN)
4362     code_to_optab[(int) code] = op;
4363
4364   return op;
4365 }
4366
4367 /* Initialize the libfunc fields of an entire group of entries in some
4368    optab.  Each entry is set equal to a string consisting of a leading
4369    pair of underscores followed by a generic operation name followed by
4370    a mode name (downshifted to lower case) followed by a single character
4371    representing the number of operands for the given operation (which is
4372    usually one of the characters '2', '3', or '4').
4373
4374    OPTABLE is the table in which libfunc fields are to be initialized.
4375    FIRST_MODE is the first machine mode index in the given optab to
4376      initialize.
4377    LAST_MODE is the last machine mode index in the given optab to
4378      initialize.
4379    OPNAME is the generic (string) name of the operation.
4380    SUFFIX is the character which specifies the number of operands for
4381      the given generic operation.
4382 */
4383
4384 static void
4385 init_libfuncs (optable, first_mode, last_mode, opname, suffix)
4386     register optab optable;
4387     register int first_mode;
4388     register int last_mode;
4389     register const char *opname;
4390     register int suffix;
4391 {
4392   register int mode;
4393   register unsigned opname_len = strlen (opname);
4394
4395   for (mode = first_mode; (int) mode <= (int) last_mode;
4396        mode = (enum machine_mode) ((int) mode + 1))
4397     {
4398       register char *mname = mode_name[(int) mode];
4399       register unsigned mname_len = strlen (mname);
4400       register char *libfunc_name
4401         = (char *) xmalloc (2 + opname_len + mname_len + 1 + 1);
4402       register char *p;
4403       register const char *q;
4404
4405       p = libfunc_name;
4406       *p++ = '_';
4407       *p++ = '_';
4408       for (q = opname; *q; )
4409         *p++ = *q++;
4410       for (q = mname; *q; q++)
4411         *p++ = tolower ((unsigned char)*q);
4412       *p++ = suffix;
4413       *p++ = '\0';
4414       optable->handlers[(int) mode].libfunc
4415         = gen_rtx_SYMBOL_REF (Pmode, libfunc_name);
4416     }
4417 }
4418
4419 /* Initialize the libfunc fields of an entire group of entries in some
4420    optab which correspond to all integer mode operations.  The parameters
4421    have the same meaning as similarly named ones for the `init_libfuncs'
4422    routine.  (See above).  */
4423
4424 static void
4425 init_integral_libfuncs (optable, opname, suffix)
4426     register optab optable;
4427     register const char *opname;
4428     register int suffix;
4429 {
4430   init_libfuncs (optable, SImode, TImode, opname, suffix);
4431 }
4432
4433 /* Initialize the libfunc fields of an entire group of entries in some
4434    optab which correspond to all real mode operations.  The parameters
4435    have the same meaning as similarly named ones for the `init_libfuncs'
4436    routine.  (See above).  */
4437
4438 static void
4439 init_floating_libfuncs (optable, opname, suffix)
4440     register optab optable;
4441     register const char *opname;
4442     register int suffix;
4443 {
4444   init_libfuncs (optable, SFmode, TFmode, opname, suffix);
4445 }
4446
4447
4448 /* Call this once to initialize the contents of the optabs
4449    appropriately for the current target machine.  */
4450
4451 void
4452 init_optabs ()
4453 {
4454   int i;
4455 #ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC
4456   int j;
4457 #endif
4458
4459   enum insn_code *p;
4460
4461   /* Start by initializing all tables to contain CODE_FOR_nothing.  */
4462
4463   for (p = fixtab[0][0];
4464        p < fixtab[0][0] + sizeof fixtab / sizeof (fixtab[0][0][0]); 
4465        p++)
4466     *p = CODE_FOR_nothing;
4467
4468   for (p = fixtrunctab[0][0];
4469        p < fixtrunctab[0][0] + sizeof fixtrunctab / sizeof (fixtrunctab[0][0][0]); 
4470        p++)
4471     *p = CODE_FOR_nothing;
4472
4473   for (p = floattab[0][0];
4474        p < floattab[0][0] + sizeof floattab / sizeof (floattab[0][0][0]); 
4475        p++)
4476     *p = CODE_FOR_nothing;
4477
4478   for (p = extendtab[0][0];
4479        p < extendtab[0][0] + sizeof extendtab / sizeof extendtab[0][0][0];
4480        p++)
4481     *p = CODE_FOR_nothing;
4482
4483   for (i = 0; i < NUM_RTX_CODE; i++)
4484     setcc_gen_code[i] = CODE_FOR_nothing;
4485
4486 #ifdef HAVE_conditional_move
4487   for (i = 0; i < NUM_MACHINE_MODES; i++)
4488     movcc_gen_code[i] = CODE_FOR_nothing;
4489 #endif
4490
4491   add_optab = init_optab (PLUS);
4492   sub_optab = init_optab (MINUS);
4493   smul_optab = init_optab (MULT);
4494   smul_highpart_optab = init_optab (UNKNOWN);
4495   umul_highpart_optab = init_optab (UNKNOWN);
4496   smul_widen_optab = init_optab (UNKNOWN);
4497   umul_widen_optab = init_optab (UNKNOWN);
4498   sdiv_optab = init_optab (DIV);
4499   sdivmod_optab = init_optab (UNKNOWN);
4500   udiv_optab = init_optab (UDIV);
4501   udivmod_optab = init_optab (UNKNOWN);
4502   smod_optab = init_optab (MOD);
4503   umod_optab = init_optab (UMOD);
4504   flodiv_optab = init_optab (DIV);
4505   ftrunc_optab = init_optab (UNKNOWN);
4506   and_optab = init_optab (AND);
4507   ior_optab = init_optab (IOR);
4508   xor_optab = init_optab (XOR);
4509   ashl_optab = init_optab (ASHIFT);
4510   ashr_optab = init_optab (ASHIFTRT);
4511   lshr_optab = init_optab (LSHIFTRT);
4512   rotl_optab = init_optab (ROTATE);
4513   rotr_optab = init_optab (ROTATERT);
4514   smin_optab = init_optab (SMIN);
4515   smax_optab = init_optab (SMAX);
4516   umin_optab = init_optab (UMIN);
4517   umax_optab = init_optab (UMAX);
4518   mov_optab = init_optab (UNKNOWN);
4519   movstrict_optab = init_optab (UNKNOWN);
4520   cmp_optab = init_optab (UNKNOWN);
4521   ucmp_optab = init_optab (UNKNOWN);
4522   tst_optab = init_optab (UNKNOWN);
4523   neg_optab = init_optab (NEG);
4524   abs_optab = init_optab (ABS);
4525   one_cmpl_optab = init_optab (NOT);
4526   ffs_optab = init_optab (FFS);
4527   sqrt_optab = init_optab (SQRT);
4528   sin_optab = init_optab (UNKNOWN);
4529   cos_optab = init_optab (UNKNOWN);
4530   strlen_optab = init_optab (UNKNOWN);
4531
4532   for (i = 0; i < NUM_MACHINE_MODES; i++)
4533     {
4534       movstr_optab[i] = CODE_FOR_nothing;
4535       clrstr_optab[i] = CODE_FOR_nothing;
4536
4537 #ifdef HAVE_SECONDARY_RELOADS
4538       reload_in_optab[i] = reload_out_optab[i] = CODE_FOR_nothing;
4539 #endif
4540     }
4541
4542   /* Fill in the optabs with the insns we support.  */
4543   init_all_optabs ();
4544
4545 #ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC
4546   /* This flag says the same insns that convert to a signed fixnum
4547      also convert validly to an unsigned one.  */
4548   for (i = 0; i < NUM_MACHINE_MODES; i++)
4549     for (j = 0; j < NUM_MACHINE_MODES; j++)
4550       fixtrunctab[i][j][1] = fixtrunctab[i][j][0];
4551 #endif
4552
4553 #ifdef EXTRA_CC_MODES
4554   init_mov_optab ();
4555 #endif
4556
4557   /* Initialize the optabs with the names of the library functions.  */
4558   init_integral_libfuncs (add_optab, "add", '3');
4559   init_floating_libfuncs (add_optab, "add", '3');
4560   init_integral_libfuncs (sub_optab, "sub", '3');
4561   init_floating_libfuncs (sub_optab, "sub", '3');
4562   init_integral_libfuncs (smul_optab, "mul", '3');
4563   init_floating_libfuncs (smul_optab, "mul", '3');
4564   init_integral_libfuncs (sdiv_optab, "div", '3');
4565   init_integral_libfuncs (udiv_optab, "udiv", '3');
4566   init_integral_libfuncs (sdivmod_optab, "divmod", '4');
4567   init_integral_libfuncs (udivmod_optab, "udivmod", '4');
4568   init_integral_libfuncs (smod_optab, "mod", '3');
4569   init_integral_libfuncs (umod_optab, "umod", '3');
4570   init_floating_libfuncs (flodiv_optab, "div", '3');
4571   init_floating_libfuncs (ftrunc_optab, "ftrunc", '2');
4572   init_integral_libfuncs (and_optab, "and", '3');
4573   init_integral_libfuncs (ior_optab, "ior", '3');
4574   init_integral_libfuncs (xor_optab, "xor", '3');
4575   init_integral_libfuncs (ashl_optab, "ashl", '3');
4576   init_integral_libfuncs (ashr_optab, "ashr", '3');
4577   init_integral_libfuncs (lshr_optab, "lshr", '3');
4578   init_integral_libfuncs (smin_optab, "min", '3');
4579   init_floating_libfuncs (smin_optab, "min", '3');
4580   init_integral_libfuncs (smax_optab, "max", '3');
4581   init_floating_libfuncs (smax_optab, "max", '3');
4582   init_integral_libfuncs (umin_optab, "umin", '3');
4583   init_integral_libfuncs (umax_optab, "umax", '3');
4584   init_integral_libfuncs (neg_optab, "neg", '2');
4585   init_floating_libfuncs (neg_optab, "neg", '2');
4586   init_integral_libfuncs (one_cmpl_optab, "one_cmpl", '2');
4587   init_integral_libfuncs (ffs_optab, "ffs", '2');
4588
4589   /* Comparison libcalls for integers MUST come in pairs, signed/unsigned.  */
4590   init_integral_libfuncs (cmp_optab, "cmp", '2');
4591   init_integral_libfuncs (ucmp_optab, "ucmp", '2');
4592   init_floating_libfuncs (cmp_optab, "cmp", '2');
4593
4594 #ifdef MULSI3_LIBCALL
4595   smul_optab->handlers[(int) SImode].libfunc
4596     = gen_rtx_SYMBOL_REF (Pmode, MULSI3_LIBCALL);
4597 #endif
4598 #ifdef MULDI3_LIBCALL
4599   smul_optab->handlers[(int) DImode].libfunc
4600     = gen_rtx_SYMBOL_REF (Pmode, MULDI3_LIBCALL);
4601 #endif
4602
4603 #ifdef DIVSI3_LIBCALL
4604   sdiv_optab->handlers[(int) SImode].libfunc
4605     = gen_rtx_SYMBOL_REF (Pmode, DIVSI3_LIBCALL);
4606 #endif
4607 #ifdef DIVDI3_LIBCALL
4608   sdiv_optab->handlers[(int) DImode].libfunc
4609     = gen_rtx_SYMBOL_REF (Pmode, DIVDI3_LIBCALL);
4610 #endif
4611
4612 #ifdef UDIVSI3_LIBCALL
4613   udiv_optab->handlers[(int) SImode].libfunc
4614     = gen_rtx_SYMBOL_REF (Pmode, UDIVSI3_LIBCALL);
4615 #endif
4616 #ifdef UDIVDI3_LIBCALL
4617   udiv_optab->handlers[(int) DImode].libfunc
4618     = gen_rtx_SYMBOL_REF (Pmode, UDIVDI3_LIBCALL);
4619 #endif
4620
4621 #ifdef MODSI3_LIBCALL
4622   smod_optab->handlers[(int) SImode].libfunc
4623     = gen_rtx_SYMBOL_REF (Pmode, MODSI3_LIBCALL);
4624 #endif
4625 #ifdef MODDI3_LIBCALL
4626   smod_optab->handlers[(int) DImode].libfunc
4627     = gen_rtx_SYMBOL_REF (Pmode, MODDI3_LIBCALL);
4628 #endif
4629
4630 #ifdef UMODSI3_LIBCALL
4631   umod_optab->handlers[(int) SImode].libfunc
4632     = gen_rtx_SYMBOL_REF (Pmode, UMODSI3_LIBCALL);
4633 #endif
4634 #ifdef UMODDI3_LIBCALL
4635   umod_optab->handlers[(int) DImode].libfunc
4636     = gen_rtx_SYMBOL_REF (Pmode, UMODDI3_LIBCALL);
4637 #endif
4638
4639   /* Use cabs for DC complex abs, since systems generally have cabs.
4640      Don't define any libcall for SCmode, so that cabs will be used.  */
4641   abs_optab->handlers[(int) DCmode].libfunc
4642     = gen_rtx_SYMBOL_REF (Pmode, "cabs");
4643
4644   /* The ffs function operates on `int'.  */
4645 #ifndef INT_TYPE_SIZE
4646 #define INT_TYPE_SIZE BITS_PER_WORD
4647 #endif
4648   ffs_optab->handlers[(int) mode_for_size (INT_TYPE_SIZE, MODE_INT, 0)] .libfunc
4649     = gen_rtx_SYMBOL_REF (Pmode, "ffs");
4650
4651   extendsfdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__extendsfdf2");
4652   extendsfxf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__extendsfxf2");
4653   extendsftf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__extendsftf2");
4654   extenddfxf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__extenddfxf2");
4655   extenddftf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__extenddftf2");
4656
4657   truncdfsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__truncdfsf2");
4658   truncxfsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__truncxfsf2");
4659   trunctfsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__trunctfsf2");
4660   truncxfdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__truncxfdf2");
4661   trunctfdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__trunctfdf2");
4662
4663   memcpy_libfunc = gen_rtx_SYMBOL_REF (Pmode, "memcpy");
4664   bcopy_libfunc = gen_rtx_SYMBOL_REF (Pmode, "bcopy");
4665   memcmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "memcmp");
4666   bcmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gcc_bcmp");
4667   memset_libfunc = gen_rtx_SYMBOL_REF (Pmode, "memset");
4668   bzero_libfunc = gen_rtx_SYMBOL_REF (Pmode, "bzero");
4669
4670   throw_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__throw");
4671   rethrow_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__rethrow");
4672   sjthrow_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__sjthrow");
4673   sjpopnthrow_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__sjpopnthrow");
4674   terminate_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__terminate");
4675   eh_rtime_match_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eh_rtime_match");
4676 #ifndef DONT_USE_BUILTIN_SETJMP
4677   setjmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__builtin_setjmp");
4678   longjmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__builtin_longjmp");
4679 #else
4680   setjmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "setjmp");
4681   longjmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "longjmp");
4682 #endif
4683
4684   eqhf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eqhf2");
4685   nehf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__nehf2");
4686   gthf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gthf2");
4687   gehf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gehf2");
4688   lthf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__lthf2");
4689   lehf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__lehf2");
4690
4691   eqsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eqsf2");
4692   nesf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__nesf2");
4693   gtsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gtsf2");
4694   gesf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gesf2");
4695   ltsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__ltsf2");
4696   lesf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__lesf2");
4697
4698   eqdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eqdf2");
4699   nedf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__nedf2");
4700   gtdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gtdf2");
4701   gedf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gedf2");
4702   ltdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__ltdf2");
4703   ledf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__ledf2");
4704
4705   eqxf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eqxf2");
4706   nexf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__nexf2");
4707   gtxf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gtxf2");
4708   gexf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gexf2");
4709   ltxf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__ltxf2");
4710   lexf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__lexf2");
4711
4712   eqtf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eqtf2");
4713   netf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__netf2");
4714   gttf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gttf2");
4715   getf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__getf2");
4716   lttf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__lttf2");
4717   letf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__letf2");
4718
4719   floatsisf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatsisf");
4720   floatdisf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatdisf");
4721   floattisf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floattisf");
4722
4723   floatsidf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatsidf");
4724   floatdidf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatdidf");
4725   floattidf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floattidf");
4726
4727   floatsixf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatsixf");
4728   floatdixf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatdixf");
4729   floattixf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floattixf");
4730
4731   floatsitf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatsitf");
4732   floatditf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatditf");
4733   floattitf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floattitf");
4734
4735   fixsfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixsfsi");
4736   fixsfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixsfdi");
4737   fixsfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixsfti");
4738
4739   fixdfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixdfsi");
4740   fixdfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixdfdi");
4741   fixdfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixdfti");
4742
4743   fixxfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixxfsi");
4744   fixxfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixxfdi");
4745   fixxfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixxfti");
4746
4747   fixtfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixtfsi");
4748   fixtfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixtfdi");
4749   fixtfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixtfti");
4750
4751   fixunssfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunssfsi");
4752   fixunssfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunssfdi");
4753   fixunssfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunssfti");
4754
4755   fixunsdfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsdfsi");
4756   fixunsdfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsdfdi");
4757   fixunsdfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsdfti");
4758
4759   fixunsxfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsxfsi");
4760   fixunsxfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsxfdi");
4761   fixunsxfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsxfti");
4762
4763   fixunstfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunstfsi");
4764   fixunstfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunstfdi");
4765   fixunstfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunstfti");
4766
4767   /* For check-memory-usage.  */
4768   chkr_check_addr_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_check_addr");
4769   chkr_set_right_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_set_right");
4770   chkr_copy_bitmap_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_copy_bitmap");
4771   chkr_check_exec_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_check_exec");
4772   chkr_check_str_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_check_str");
4773
4774   /* For function entry/exit instrumentation.  */
4775   profile_function_entry_libfunc
4776     = gen_rtx_SYMBOL_REF (Pmode, "__cyg_profile_func_enter");
4777   profile_function_exit_libfunc
4778     = gen_rtx_SYMBOL_REF (Pmode, "__cyg_profile_func_exit");
4779
4780 #ifdef HAVE_conditional_trap
4781   init_traps ();
4782 #endif
4783
4784 #ifdef INIT_TARGET_OPTABS
4785   /* Allow the target to add more libcalls or rename some, etc.  */
4786   INIT_TARGET_OPTABS;
4787 #endif
4788 }
4789 \f
4790 #ifdef BROKEN_LDEXP
4791
4792 /* SCO 3.2 apparently has a broken ldexp.  */
4793
4794 double
4795 ldexp(x,n)
4796      double x;
4797      int n;
4798 {
4799   if (n > 0)
4800     while (n--)
4801       x *= 2;
4802
4803   return x;
4804 }
4805 #endif /* BROKEN_LDEXP */
4806 \f
4807 #ifdef HAVE_conditional_trap
4808 /* The insn generating function can not take an rtx_code argument.
4809    TRAP_RTX is used as an rtx argument.  Its code is replaced with
4810    the code to be used in the trap insn and all other fields are
4811    ignored.
4812
4813    ??? Will need to change to support garbage collection.  */
4814 static rtx trap_rtx;
4815
4816 static void
4817 init_traps ()
4818 {
4819   if (HAVE_conditional_trap)
4820     trap_rtx = gen_rtx_fmt_ee (EQ, VOIDmode, NULL_RTX, NULL_RTX);
4821 }
4822 #endif
4823
4824 /* Generate insns to trap with code TCODE if OP1 and OP2 satisfy condition
4825    CODE.  Return 0 on failure.  */
4826
4827 rtx
4828 gen_cond_trap (code, op1, op2, tcode)
4829   enum rtx_code code ATTRIBUTE_UNUSED;
4830   rtx op1, op2 ATTRIBUTE_UNUSED, tcode ATTRIBUTE_UNUSED;
4831 {
4832   enum machine_mode mode = GET_MODE (op1);
4833
4834   if (mode == VOIDmode)
4835     return 0;
4836
4837 #ifdef HAVE_conditional_trap
4838   if (HAVE_conditional_trap
4839       && cmp_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
4840     {
4841       rtx insn;
4842       emit_insn (GEN_FCN (cmp_optab->handlers[(int) mode].insn_code) (op1, op2));
4843       PUT_CODE (trap_rtx, code);
4844       insn = gen_conditional_trap (trap_rtx, tcode);
4845       if (insn)
4846         return insn;
4847     }
4848 #endif
4849
4850   return 0;
4851 }