OSDN Git Service

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