OSDN Git Service

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