OSDN Git Service

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