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