OSDN Git Service

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