OSDN Git Service

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