OSDN Git Service

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