OSDN Git Service

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