OSDN Git Service

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