OSDN Git Service

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