]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/gcc/optabs.c
This commit was generated by cvs2svn to compensate for changes in r104977,
[FreeBSD/FreeBSD.git] / contrib / gcc / optabs.c
1 /* Expand the basic unary and binary arithmetic operations, for GNU compiler.
2    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3    1999, 2000, 2001 Free Software Foundation, Inc.
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
11
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING.  If not, write to the Free
19 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA.  */
21
22
23 #include "config.h"
24 #include "system.h"
25 #include "toplev.h"
26
27 /* Include insn-config.h before expr.h so that HAVE_conditional_move
28    is properly defined.  */
29 #include "insn-config.h"
30 #include "rtl.h"
31 #include "tree.h"
32 #include "tm_p.h"
33 #include "flags.h"
34 #include "function.h"
35 #include "except.h"
36 #include "expr.h"
37 #include "optabs.h"
38 #include "libfuncs.h"
39 #include "recog.h"
40 #include "reload.h"
41 #include "ggc.h"
42 #include "real.h"
43
44 /* Each optab contains info on how this target machine
45    can perform a particular operation
46    for all sizes and kinds of operands.
47
48    The operation to be performed is often specified
49    by passing one of these optabs as an argument.
50
51    See expr.h for documentation of these optabs.  */
52
53 optab optab_table[OTI_MAX];
54
55 rtx libfunc_table[LTI_MAX];
56
57 /* Tables of patterns for extending one integer mode to another.  */
58 enum insn_code extendtab[MAX_MACHINE_MODE][MAX_MACHINE_MODE][2];
59
60 /* Tables of patterns for converting between fixed and floating point.  */
61 enum insn_code fixtab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
62 enum insn_code fixtrunctab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
63 enum insn_code floattab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
64
65 /* Contains the optab used for each rtx code.  */
66 optab code_to_optab[NUM_RTX_CODE + 1];
67
68 /* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
69    gives the gen_function to make a branch to test that condition.  */
70
71 rtxfun bcc_gen_fctn[NUM_RTX_CODE];
72
73 /* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
74    gives the insn code to make a store-condition insn
75    to test that condition.  */
76
77 enum insn_code setcc_gen_code[NUM_RTX_CODE];
78
79 #ifdef HAVE_conditional_move
80 /* Indexed by the machine mode, gives the insn code to make a conditional
81    move insn.  This is not indexed by the rtx-code like bcc_gen_fctn and
82    setcc_gen_code to cut down on the number of named patterns.  Consider a day
83    when a lot more rtx codes are conditional (eg: for the ARM).  */
84
85 enum insn_code movcc_gen_code[NUM_MACHINE_MODES];
86 #endif
87
88 static int add_equal_note       PARAMS ((rtx, rtx, enum rtx_code, rtx, rtx));
89 static rtx widen_operand        PARAMS ((rtx, enum machine_mode,
90                                        enum machine_mode, int, int));
91 static int expand_cmplxdiv_straight PARAMS ((rtx, rtx, rtx, rtx,
92                                            rtx, rtx, enum machine_mode,
93                                            int, enum optab_methods,
94                                            enum mode_class, optab));
95 static int expand_cmplxdiv_wide PARAMS ((rtx, rtx, rtx, rtx,
96                                        rtx, rtx, enum machine_mode,
97                                        int, enum optab_methods,
98                                        enum mode_class, optab));
99 static void prepare_cmp_insn PARAMS ((rtx *, rtx *, enum rtx_code *, rtx,
100                                       enum machine_mode *, int *,
101                                       enum can_compare_purpose));
102 static enum insn_code can_fix_p PARAMS ((enum machine_mode, enum machine_mode,
103                                        int, int *));
104 static enum insn_code can_float_p PARAMS ((enum machine_mode,
105                                            enum machine_mode,
106                                            int));
107 static rtx ftruncify    PARAMS ((rtx));
108 static optab new_optab  PARAMS ((void));
109 static inline optab init_optab  PARAMS ((enum rtx_code));
110 static inline optab init_optabv PARAMS ((enum rtx_code));
111 static void init_libfuncs PARAMS ((optab, int, int, const char *, int));
112 static void init_integral_libfuncs PARAMS ((optab, const char *, int));
113 static void init_floating_libfuncs PARAMS ((optab, const char *, int));
114 #ifdef HAVE_conditional_trap
115 static void init_traps PARAMS ((void));
116 #endif
117 static void emit_cmp_and_jump_insn_1 PARAMS ((rtx, rtx, enum machine_mode,
118                                             enum rtx_code, int, rtx));
119 static void prepare_float_lib_cmp PARAMS ((rtx *, rtx *, enum rtx_code *,
120                                          enum machine_mode *, int *));
121 \f
122 /* Add a REG_EQUAL note to the last insn in SEQ.  TARGET is being set to
123    the result of operation CODE applied to OP0 (and OP1 if it is a binary
124    operation).
125
126    If the last insn does not set TARGET, don't do anything, but return 1.
127
128    If a previous insn sets TARGET and TARGET is one of OP0 or OP1,
129    don't add the REG_EQUAL note but return 0.  Our caller can then try
130    again, ensuring that TARGET is not one of the operands.  */
131
132 static int
133 add_equal_note (seq, target, code, op0, op1)
134      rtx seq;
135      rtx target;
136      enum rtx_code code;
137      rtx op0, op1;
138 {
139   rtx set;
140   int i;
141   rtx note;
142
143   if ((GET_RTX_CLASS (code) != '1' && GET_RTX_CLASS (code) != '2'
144        && GET_RTX_CLASS (code) != 'c' && GET_RTX_CLASS (code) != '<')
145       || GET_CODE (seq) != SEQUENCE
146       || (set = single_set (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1))) == 0
147       || GET_CODE (target) == ZERO_EXTRACT
148       || (! rtx_equal_p (SET_DEST (set), target)
149           /* For a STRICT_LOW_PART, the REG_NOTE applies to what is inside the
150              SUBREG.  */
151           && (GET_CODE (SET_DEST (set)) != STRICT_LOW_PART
152               || ! rtx_equal_p (SUBREG_REG (XEXP (SET_DEST (set), 0)),
153                                 target))))
154     return 1;
155
156   /* If TARGET is in OP0 or OP1, check if anything in SEQ sets TARGET
157      besides the last insn.  */
158   if (reg_overlap_mentioned_p (target, op0)
159       || (op1 && reg_overlap_mentioned_p (target, op1)))
160     for (i = XVECLEN (seq, 0) - 2; i >= 0; i--)
161       if (reg_set_p (target, XVECEXP (seq, 0, i)))
162         return 0;
163
164   if (GET_RTX_CLASS (code) == '1')
165     note = gen_rtx_fmt_e (code, GET_MODE (target), copy_rtx (op0));
166   else
167     note = gen_rtx_fmt_ee (code, GET_MODE (target), copy_rtx (op0), copy_rtx (op1));
168
169   set_unique_reg_note (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1), REG_EQUAL, note);
170
171   return 1;
172 }
173 \f
174 /* Widen OP to MODE and return the rtx for the widened operand.  UNSIGNEDP
175    says whether OP is signed or unsigned.  NO_EXTEND is nonzero if we need
176    not actually do a sign-extend or zero-extend, but can leave the 
177    higher-order bits of the result rtx undefined, for example, in the case
178    of logical operations, but not right shifts.  */
179
180 static rtx
181 widen_operand (op, mode, oldmode, unsignedp, no_extend)
182      rtx op;
183      enum machine_mode mode, oldmode;
184      int unsignedp;
185      int no_extend;
186 {
187   rtx result;
188
189   /* If we don't have to extend and this is a constant, return it.  */
190   if (no_extend && GET_MODE (op) == VOIDmode)
191     return op;
192
193   /* If we must extend do so.  If OP is a SUBREG for a promoted object, also
194      extend since it will be more efficient to do so unless the signedness of
195      a promoted object differs from our extension.  */
196   if (! no_extend
197       || (GET_CODE (op) == SUBREG && SUBREG_PROMOTED_VAR_P (op)
198           && SUBREG_PROMOTED_UNSIGNED_P (op) == unsignedp))
199     return convert_modes (mode, oldmode, op, unsignedp);
200
201   /* If MODE is no wider than a single word, we return a paradoxical
202      SUBREG.  */
203   if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
204     return gen_rtx_SUBREG (mode, force_reg (GET_MODE (op), op), 0);
205
206   /* Otherwise, get an object of MODE, clobber it, and set the low-order
207      part to OP.  */
208
209   result = gen_reg_rtx (mode);
210   emit_insn (gen_rtx_CLOBBER (VOIDmode, result));
211   emit_move_insn (gen_lowpart (GET_MODE (op), result), op);
212   return result;
213 }
214 \f
215 /* Generate code to perform a straightforward complex divide.  */
216
217 static int
218 expand_cmplxdiv_straight (real0, real1, imag0, imag1, realr, imagr, submode,
219                           unsignedp, methods, class, binoptab)
220   rtx real0, real1, imag0, imag1, realr, imagr;
221   enum machine_mode submode;
222   int unsignedp;
223   enum optab_methods methods;
224   enum mode_class class;
225   optab binoptab;
226 {
227   rtx divisor;
228   rtx real_t, imag_t;
229   rtx temp1, temp2;
230   rtx res;
231   optab this_add_optab = add_optab;
232   optab this_sub_optab = sub_optab;
233   optab this_neg_optab = neg_optab;
234   optab this_mul_optab = smul_optab;
235               
236   if (binoptab == sdivv_optab)
237     {
238       this_add_optab = addv_optab;
239       this_sub_optab = subv_optab;
240       this_neg_optab = negv_optab;
241       this_mul_optab = smulv_optab;
242     }
243
244   /* Don't fetch these from memory more than once.  */
245   real0 = force_reg (submode, real0);
246   real1 = force_reg (submode, real1);
247
248   if (imag0 != 0)
249     imag0 = force_reg (submode, imag0);
250
251   imag1 = force_reg (submode, imag1);
252
253   /* Divisor: c*c + d*d.  */
254   temp1 = expand_binop (submode, this_mul_optab, real1, real1,
255                         NULL_RTX, unsignedp, methods);
256
257   temp2 = expand_binop (submode, this_mul_optab, imag1, imag1,
258                         NULL_RTX, unsignedp, methods);
259
260   if (temp1 == 0 || temp2 == 0)
261     return 0;
262
263   divisor = expand_binop (submode, this_add_optab, temp1, temp2,
264                           NULL_RTX, unsignedp, methods);
265   if (divisor == 0)
266     return 0;
267
268   if (imag0 == 0)
269     {
270       /* Mathematically, ((a)(c-id))/divisor.  */
271       /* Computationally, (a+i0) / (c+id) = (ac/(cc+dd)) + i(-ad/(cc+dd)).  */
272
273       /* Calculate the dividend.  */
274       real_t = expand_binop (submode, this_mul_optab, real0, real1,
275                              NULL_RTX, unsignedp, methods);
276                   
277       imag_t = expand_binop (submode, this_mul_optab, real0, imag1,
278                              NULL_RTX, unsignedp, methods);
279
280       if (real_t == 0 || imag_t == 0)
281         return 0;
282
283       imag_t = expand_unop (submode, this_neg_optab, imag_t,
284                             NULL_RTX, unsignedp);
285     }
286   else
287     {
288       /* Mathematically, ((a+ib)(c-id))/divider.  */
289       /* Calculate the dividend.  */
290       temp1 = expand_binop (submode, this_mul_optab, real0, real1,
291                             NULL_RTX, unsignedp, methods);
292
293       temp2 = expand_binop (submode, this_mul_optab, imag0, imag1,
294                             NULL_RTX, unsignedp, methods);
295
296       if (temp1 == 0 || temp2 == 0)
297         return 0;
298
299       real_t = expand_binop (submode, this_add_optab, temp1, temp2,
300                              NULL_RTX, unsignedp, methods);
301                   
302       temp1 = expand_binop (submode, this_mul_optab, imag0, real1,
303                             NULL_RTX, unsignedp, methods);
304
305       temp2 = expand_binop (submode, this_mul_optab, real0, imag1,
306                             NULL_RTX, unsignedp, methods);
307
308       if (temp1 == 0 || temp2 == 0)
309         return 0;
310
311       imag_t = expand_binop (submode, this_sub_optab, temp1, temp2,
312                              NULL_RTX, unsignedp, methods);
313
314       if (real_t == 0 || imag_t == 0)
315         return 0;
316     }
317
318   if (class == MODE_COMPLEX_FLOAT)
319     res = expand_binop (submode, binoptab, real_t, divisor,
320                         realr, unsignedp, methods);
321   else
322     res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
323                          real_t, divisor, realr, unsignedp);
324
325   if (res == 0)
326     return 0;
327
328   if (res != realr)
329     emit_move_insn (realr, res);
330
331   if (class == MODE_COMPLEX_FLOAT)
332     res = expand_binop (submode, binoptab, imag_t, divisor,
333                         imagr, unsignedp, methods);
334   else
335     res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
336                          imag_t, divisor, imagr, unsignedp);
337
338   if (res == 0)
339     return 0;
340
341   if (res != imagr)
342     emit_move_insn (imagr, res);
343
344   return 1;
345 }
346 \f
347 /* Generate code to perform a wide-input-range-acceptable complex divide.  */
348
349 static int
350 expand_cmplxdiv_wide (real0, real1, imag0, imag1, realr, imagr, submode,
351                       unsignedp, methods, class, binoptab)
352   rtx real0, real1, imag0, imag1, realr, imagr;
353   enum machine_mode submode;
354   int unsignedp;
355   enum optab_methods methods;
356   enum mode_class class;
357   optab binoptab;
358 {
359   rtx ratio, divisor;
360   rtx real_t, imag_t;
361   rtx temp1, temp2, lab1, lab2;
362   enum machine_mode mode;
363   rtx res;
364   optab this_add_optab = add_optab;
365   optab this_sub_optab = sub_optab;
366   optab this_neg_optab = neg_optab;
367   optab this_mul_optab = smul_optab;
368
369   if (binoptab == sdivv_optab)
370     {
371       this_add_optab = addv_optab;
372       this_sub_optab = subv_optab;
373       this_neg_optab = negv_optab;
374       this_mul_optab = smulv_optab;
375     }
376               
377   /* Don't fetch these from memory more than once.  */
378   real0 = force_reg (submode, real0);
379   real1 = force_reg (submode, real1);
380
381   if (imag0 != 0)
382     imag0 = force_reg (submode, imag0);
383
384   imag1 = force_reg (submode, imag1);
385
386   /* XXX What's an "unsigned" complex number?  */
387   if (unsignedp)
388     {
389       temp1 = real1;
390       temp2 = imag1;
391     }
392   else
393     {
394       temp1 = expand_abs (submode, real1, NULL_RTX, unsignedp, 1);
395       temp2 = expand_abs (submode, imag1, NULL_RTX, unsignedp, 1);
396     }
397
398   if (temp1 == 0 || temp2 == 0)
399     return 0;
400
401   mode = GET_MODE (temp1);
402   lab1 = gen_label_rtx ();
403   emit_cmp_and_jump_insns (temp1, temp2, LT, NULL_RTX,
404                            mode, unsignedp, lab1);
405
406   /* |c| >= |d|; use ratio d/c to scale dividend and divisor.  */
407
408   if (class == MODE_COMPLEX_FLOAT)
409     ratio = expand_binop (submode, binoptab, imag1, real1,
410                           NULL_RTX, unsignedp, methods);
411   else
412     ratio = expand_divmod (0, TRUNC_DIV_EXPR, submode,
413                            imag1, real1, NULL_RTX, unsignedp);
414
415   if (ratio == 0)
416     return 0;
417
418   /* Calculate divisor.  */
419
420   temp1 = expand_binop (submode, this_mul_optab, imag1, ratio,
421                         NULL_RTX, unsignedp, methods);
422
423   if (temp1 == 0)
424     return 0;
425
426   divisor = expand_binop (submode, this_add_optab, temp1, real1,
427                           NULL_RTX, unsignedp, methods);
428
429   if (divisor == 0)
430     return 0;
431
432   /* Calculate dividend.  */
433
434   if (imag0 == 0)
435     {
436       real_t = real0;
437
438       /* Compute a / (c+id) as a / (c+d(d/c)) + i (-a(d/c)) / (c+d(d/c)).  */
439
440       imag_t = expand_binop (submode, this_mul_optab, real0, ratio,
441                              NULL_RTX, unsignedp, methods);
442
443       if (imag_t == 0)
444         return 0;
445
446       imag_t = expand_unop (submode, this_neg_optab, imag_t,
447                             NULL_RTX, unsignedp);
448
449       if (real_t == 0 || imag_t == 0)
450         return 0;
451     }
452   else
453     {
454       /* Compute (a+ib)/(c+id) as
455          (a+b(d/c))/(c+d(d/c) + i(b-a(d/c))/(c+d(d/c)).  */
456
457       temp1 = expand_binop (submode, this_mul_optab, imag0, ratio,
458                             NULL_RTX, unsignedp, methods);
459
460       if (temp1 == 0)
461         return 0;
462
463       real_t = expand_binop (submode, this_add_optab, temp1, real0,
464                              NULL_RTX, unsignedp, methods);
465
466       temp1 = expand_binop (submode, this_mul_optab, real0, ratio,
467                             NULL_RTX, unsignedp, methods);
468
469       if (temp1 == 0)
470         return 0;
471
472       imag_t = expand_binop (submode, this_sub_optab, imag0, temp1,
473                              NULL_RTX, unsignedp, methods);
474
475       if (real_t == 0 || imag_t == 0)
476         return 0;
477     }
478
479   if (class == MODE_COMPLEX_FLOAT)
480     res = expand_binop (submode, binoptab, real_t, divisor,
481                         realr, unsignedp, methods);
482   else
483     res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
484                          real_t, divisor, realr, unsignedp);
485
486   if (res == 0)
487     return 0;
488
489   if (res != realr)
490     emit_move_insn (realr, res);
491
492   if (class == MODE_COMPLEX_FLOAT)
493     res = expand_binop (submode, binoptab, imag_t, divisor,
494                         imagr, unsignedp, methods);
495   else
496     res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
497                          imag_t, divisor, imagr, unsignedp);
498
499   if (res == 0)
500     return 0;
501
502   if (res != imagr)
503     emit_move_insn (imagr, res);
504
505   lab2 = gen_label_rtx ();
506   emit_jump_insn (gen_jump (lab2));
507   emit_barrier ();
508
509   emit_label (lab1);
510
511   /* |d| > |c|; use ratio c/d to scale dividend and divisor.  */
512
513   if (class == MODE_COMPLEX_FLOAT)
514     ratio = expand_binop (submode, binoptab, real1, imag1,
515                           NULL_RTX, unsignedp, methods);
516   else
517     ratio = expand_divmod (0, TRUNC_DIV_EXPR, submode,
518                            real1, imag1, NULL_RTX, unsignedp);
519
520   if (ratio == 0)
521     return 0;
522
523   /* Calculate divisor.  */
524
525   temp1 = expand_binop (submode, this_mul_optab, real1, ratio,
526                         NULL_RTX, unsignedp, methods);
527
528   if (temp1 == 0)
529     return 0;
530
531   divisor = expand_binop (submode, this_add_optab, temp1, imag1,
532                           NULL_RTX, unsignedp, methods);
533
534   if (divisor == 0)
535     return 0;
536
537   /* Calculate dividend.  */
538
539   if (imag0 == 0)
540     {
541       /* Compute a / (c+id) as a(c/d) / (c(c/d)+d) + i (-a) / (c(c/d)+d).  */
542
543       real_t = expand_binop (submode, this_mul_optab, real0, ratio,
544                              NULL_RTX, unsignedp, methods);
545
546       imag_t = expand_unop (submode, this_neg_optab, real0,
547                             NULL_RTX, unsignedp);
548
549       if (real_t == 0 || imag_t == 0)
550         return 0;
551     }
552   else
553     {
554       /* Compute (a+ib)/(c+id) as
555          (a(c/d)+b)/(c(c/d)+d) + i (b(c/d)-a)/(c(c/d)+d).  */
556
557       temp1 = expand_binop (submode, this_mul_optab, real0, ratio,
558                             NULL_RTX, unsignedp, methods);
559
560       if (temp1 == 0)
561         return 0;
562
563       real_t = expand_binop (submode, this_add_optab, temp1, imag0,
564                              NULL_RTX, unsignedp, methods);
565
566       temp1 = expand_binop (submode, this_mul_optab, imag0, ratio,
567                             NULL_RTX, unsignedp, methods);
568
569       if (temp1 == 0)
570         return 0;
571
572       imag_t = expand_binop (submode, this_sub_optab, temp1, real0,
573                              NULL_RTX, unsignedp, methods);
574
575       if (real_t == 0 || imag_t == 0)
576         return 0;
577     }
578
579   if (class == MODE_COMPLEX_FLOAT)
580     res = expand_binop (submode, binoptab, real_t, divisor,
581                         realr, unsignedp, methods);
582   else
583     res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
584                          real_t, divisor, realr, unsignedp);
585
586   if (res == 0)
587     return 0;
588
589   if (res != realr)
590     emit_move_insn (realr, res);
591
592   if (class == MODE_COMPLEX_FLOAT)
593     res = expand_binop (submode, binoptab, imag_t, divisor,
594                         imagr, unsignedp, methods);
595   else
596     res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
597                          imag_t, divisor, imagr, unsignedp);
598
599   if (res == 0)
600     return 0;
601
602   if (res != imagr)
603     emit_move_insn (imagr, res);
604
605   emit_label (lab2);
606
607   return 1;
608 }
609 \f
610 /* Wrapper around expand_binop which takes an rtx code to specify
611    the operation to perform, not an optab pointer.  All other
612    arguments are the same.  */
613 rtx
614 expand_simple_binop (mode, code, op0, op1, target, unsignedp, methods)
615      enum machine_mode mode;
616      enum rtx_code code;
617      rtx op0, op1;
618      rtx target;
619      int unsignedp;
620      enum optab_methods methods;
621 {
622   optab binop = code_to_optab [(int) code];
623   if (binop == 0)
624     abort ();
625
626   return expand_binop (mode, binop, op0, op1, target, unsignedp, methods);
627 }
628
629 /* Generate code to perform an operation specified by BINOPTAB
630    on operands OP0 and OP1, with result having machine-mode MODE.
631
632    UNSIGNEDP is for the case where we have to widen the operands
633    to perform the operation.  It says to use zero-extension.
634
635    If TARGET is nonzero, the value
636    is generated there, if it is convenient to do so.
637    In all cases an rtx is returned for the locus of the value;
638    this may or may not be TARGET.  */
639
640 rtx
641 expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
642      enum machine_mode mode;
643      optab binoptab;
644      rtx op0, op1;
645      rtx target;
646      int unsignedp;
647      enum optab_methods methods;
648 {
649   enum optab_methods next_methods
650     = (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN
651        ? OPTAB_WIDEN : methods);
652   enum mode_class class;
653   enum machine_mode wider_mode;
654   rtx temp;
655   int commutative_op = 0;
656   int shift_op = (binoptab->code ==  ASHIFT
657                   || binoptab->code == ASHIFTRT
658                   || binoptab->code == LSHIFTRT
659                   || binoptab->code == ROTATE
660                   || binoptab->code == ROTATERT);
661   rtx entry_last = get_last_insn ();
662   rtx last;
663
664   class = GET_MODE_CLASS (mode);
665
666   op0 = protect_from_queue (op0, 0);
667   op1 = protect_from_queue (op1, 0);
668   if (target)
669     target = protect_from_queue (target, 1);
670
671   if (flag_force_mem)
672     {
673       op0 = force_not_mem (op0);
674       op1 = force_not_mem (op1);
675     }
676
677   /* If subtracting an integer constant, convert this into an addition of
678      the negated constant.  */
679
680   if (binoptab == sub_optab && GET_CODE (op1) == CONST_INT)
681     {
682       op1 = negate_rtx (mode, op1);
683       binoptab = add_optab;
684     }
685
686   /* If we are inside an appropriately-short loop and one operand is an
687      expensive constant, force it into a register.  */
688   if (CONSTANT_P (op0) && preserve_subexpressions_p ()
689       && rtx_cost (op0, binoptab->code) > COSTS_N_INSNS (1))
690     op0 = force_reg (mode, op0);
691
692   if (CONSTANT_P (op1) && preserve_subexpressions_p ()
693       && ! shift_op && rtx_cost (op1, binoptab->code) > COSTS_N_INSNS (1))
694     op1 = force_reg (mode, op1);
695
696   /* Record where to delete back to if we backtrack.  */
697   last = get_last_insn ();
698
699   /* If operation is commutative,
700      try to make the first operand a register.
701      Even better, try to make it the same as the target.
702      Also try to make the last operand a constant.  */
703   if (GET_RTX_CLASS (binoptab->code) == 'c'
704       || binoptab == smul_widen_optab
705       || binoptab == umul_widen_optab
706       || binoptab == smul_highpart_optab
707       || binoptab == umul_highpart_optab)
708     {
709       commutative_op = 1;
710
711       if (((target == 0 || GET_CODE (target) == REG)
712            ? ((GET_CODE (op1) == REG
713                && GET_CODE (op0) != REG)
714               || target == op1)
715            : rtx_equal_p (op1, target))
716           || GET_CODE (op0) == CONST_INT)
717         {
718           temp = op1;
719           op1 = op0;
720           op0 = temp;
721         }
722     }
723
724   /* If we can do it with a three-operand insn, do so.  */
725
726   if (methods != OPTAB_MUST_WIDEN
727       && binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
728     {
729       int icode = (int) binoptab->handlers[(int) mode].insn_code;
730       enum machine_mode mode0 = insn_data[icode].operand[1].mode;
731       enum machine_mode mode1 = insn_data[icode].operand[2].mode;
732       rtx pat;
733       rtx xop0 = op0, xop1 = op1;
734
735       if (target)
736         temp = target;
737       else
738         temp = gen_reg_rtx (mode);
739
740       /* If it is a commutative operator and the modes would match
741          if we would swap the operands, we can save the conversions.  */
742       if (commutative_op)
743         {
744           if (GET_MODE (op0) != mode0 && GET_MODE (op1) != mode1
745               && GET_MODE (op0) == mode1 && GET_MODE (op1) == mode0)
746             {
747               rtx tmp;
748
749               tmp = op0; op0 = op1; op1 = tmp;
750               tmp = xop0; xop0 = xop1; xop1 = tmp;
751             }
752         }
753
754       /* In case the insn wants input operands in modes different from
755          those of the actual operands, convert the operands.  It would
756          seem that we don't need to convert CONST_INTs, but we do, so
757          that they're properly zero-extended or sign-extended for their
758          modes; shift operations are an exception, because the second
759          operand needs not be extended to the mode of the result.  */
760
761       if (GET_MODE (op0) != mode0
762           && mode0 != VOIDmode)
763         xop0 = convert_modes (mode0,
764                               GET_MODE (op0) != VOIDmode
765                               ? GET_MODE (op0)
766                               : mode,
767                               xop0, unsignedp);
768
769       if (GET_MODE (xop1) != mode1
770           && mode1 != VOIDmode)
771         xop1 = convert_modes (mode1,
772                               GET_MODE (op1) != VOIDmode
773                               ? GET_MODE (op1)
774                               : ! shift_op
775                               ? mode
776                               : mode1,
777                               xop1, unsignedp);
778
779       /* Now, if insn's predicates don't allow our operands, put them into
780          pseudo regs.  */
781
782       if (! (*insn_data[icode].operand[1].predicate) (xop0, mode0)
783           && mode0 != VOIDmode)
784         xop0 = copy_to_mode_reg (mode0, xop0);
785
786       if (! (*insn_data[icode].operand[2].predicate) (xop1, mode1)
787           && mode1 != VOIDmode)
788         xop1 = copy_to_mode_reg (mode1, xop1);
789
790       if (! (*insn_data[icode].operand[0].predicate) (temp, mode))
791         temp = gen_reg_rtx (mode);
792
793       pat = GEN_FCN (icode) (temp, xop0, xop1);
794       if (pat)
795         {
796           /* If PAT is a multi-insn sequence, try to add an appropriate
797              REG_EQUAL note to it.  If we can't because TEMP conflicts with an
798              operand, call ourselves again, this time without a target.  */
799           if (GET_CODE (pat) == SEQUENCE
800               && ! add_equal_note (pat, temp, binoptab->code, xop0, xop1))
801             {
802               delete_insns_since (last);
803               return expand_binop (mode, binoptab, op0, op1, NULL_RTX,
804                                    unsignedp, methods);
805             }
806
807           emit_insn (pat);
808           return temp;
809         }
810       else
811         delete_insns_since (last);
812     }
813
814   /* If this is a multiply, see if we can do a widening operation that
815      takes operands of this mode and makes a wider mode.  */
816
817   if (binoptab == smul_optab && GET_MODE_WIDER_MODE (mode) != VOIDmode
818       && (((unsignedp ? umul_widen_optab : smul_widen_optab)
819            ->handlers[(int) GET_MODE_WIDER_MODE (mode)].insn_code)
820           != CODE_FOR_nothing))
821     {
822       temp = expand_binop (GET_MODE_WIDER_MODE (mode),
823                            unsignedp ? umul_widen_optab : smul_widen_optab,
824                            op0, op1, NULL_RTX, unsignedp, OPTAB_DIRECT);
825
826       if (temp != 0)
827         {
828           if (GET_MODE_CLASS (mode) == MODE_INT)
829             return gen_lowpart (mode, temp);
830           else
831             return convert_to_mode (mode, temp, unsignedp);
832         }
833     }
834
835   /* Look for a wider mode of the same class for which we think we
836      can open-code the operation.  Check for a widening multiply at the
837      wider mode as well.  */
838
839   if ((class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
840       && methods != OPTAB_DIRECT && methods != OPTAB_LIB)
841     for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
842          wider_mode = GET_MODE_WIDER_MODE (wider_mode))
843       {
844         if (binoptab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing
845             || (binoptab == smul_optab
846                 && GET_MODE_WIDER_MODE (wider_mode) != VOIDmode
847                 && (((unsignedp ? umul_widen_optab : smul_widen_optab)
848                      ->handlers[(int) GET_MODE_WIDER_MODE (wider_mode)].insn_code)
849                     != CODE_FOR_nothing)))
850           {
851             rtx xop0 = op0, xop1 = op1;
852             int no_extend = 0;
853
854             /* For certain integer operations, we need not actually extend
855                the narrow operands, as long as we will truncate
856                the results to the same narrowness.  */
857
858             if ((binoptab == ior_optab || binoptab == and_optab
859                  || binoptab == xor_optab
860                  || binoptab == add_optab || binoptab == sub_optab
861                  || binoptab == smul_optab || binoptab == ashl_optab)
862                 && class == MODE_INT)
863               no_extend = 1;
864
865             xop0 = widen_operand (xop0, wider_mode, mode, unsignedp, no_extend);
866
867             /* The second operand of a shift must always be extended.  */
868             xop1 = widen_operand (xop1, wider_mode, mode, unsignedp,
869                                   no_extend && binoptab != ashl_optab);
870
871             temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX,
872                                  unsignedp, OPTAB_DIRECT);
873             if (temp)
874               {
875                 if (class != MODE_INT)
876                   {
877                     if (target == 0)
878                       target = gen_reg_rtx (mode);
879                     convert_move (target, temp, 0);
880                     return target;
881                   }
882                 else
883                   return gen_lowpart (mode, temp);
884               }
885             else
886               delete_insns_since (last);
887           }
888       }
889
890   /* These can be done a word at a time.  */
891   if ((binoptab == and_optab || binoptab == ior_optab || binoptab == xor_optab)
892       && class == MODE_INT
893       && GET_MODE_SIZE (mode) > UNITS_PER_WORD
894       && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
895     {
896       int i;
897       rtx insns;
898       rtx equiv_value;
899
900       /* If TARGET is the same as one of the operands, the REG_EQUAL note
901          won't be accurate, so use a new target.  */
902       if (target == 0 || target == op0 || target == op1)
903         target = gen_reg_rtx (mode);
904
905       start_sequence ();
906
907       /* Do the actual arithmetic.  */
908       for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)
909         {
910           rtx target_piece = operand_subword (target, i, 1, mode);
911           rtx x = expand_binop (word_mode, binoptab,
912                                 operand_subword_force (op0, i, mode),
913                                 operand_subword_force (op1, i, mode),
914                                 target_piece, unsignedp, next_methods);
915
916           if (x == 0)
917             break;
918
919           if (target_piece != x)
920             emit_move_insn (target_piece, x);
921         }
922
923       insns = get_insns ();
924       end_sequence ();
925
926       if (i == GET_MODE_BITSIZE (mode) / BITS_PER_WORD)
927         {
928           if (binoptab->code != UNKNOWN)
929             equiv_value
930               = gen_rtx_fmt_ee (binoptab->code, mode,
931                                 copy_rtx (op0), copy_rtx (op1));
932           else
933             equiv_value = 0;
934
935           emit_no_conflict_block (insns, target, op0, op1, equiv_value);
936           return target;
937         }
938     }
939
940   /* Synthesize double word shifts from single word shifts.  */
941   if ((binoptab == lshr_optab || binoptab == ashl_optab
942        || binoptab == ashr_optab)
943       && class == MODE_INT
944       && GET_CODE (op1) == CONST_INT
945       && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
946       && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
947       && ashl_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
948       && lshr_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
949     {
950       rtx insns, inter, equiv_value;
951       rtx into_target, outof_target;
952       rtx into_input, outof_input;
953       int shift_count, left_shift, outof_word;
954
955       /* If TARGET is the same as one of the operands, the REG_EQUAL note
956          won't be accurate, so use a new target.  */
957       if (target == 0 || target == op0 || target == op1)
958         target = gen_reg_rtx (mode);
959
960       start_sequence ();
961
962       shift_count = INTVAL (op1);
963
964       /* OUTOF_* is the word we are shifting bits away from, and
965          INTO_* is the word that we are shifting bits towards, thus
966          they differ depending on the direction of the shift and
967          WORDS_BIG_ENDIAN.  */
968
969       left_shift = binoptab == ashl_optab;
970       outof_word = left_shift ^ ! WORDS_BIG_ENDIAN;
971
972       outof_target = operand_subword (target, outof_word, 1, mode);
973       into_target = operand_subword (target, 1 - outof_word, 1, mode);
974
975       outof_input = operand_subword_force (op0, outof_word, mode);
976       into_input = operand_subword_force (op0, 1 - outof_word, mode);
977
978       if (shift_count >= BITS_PER_WORD)
979         {
980           inter = expand_binop (word_mode, binoptab,
981                                outof_input,
982                                GEN_INT (shift_count - BITS_PER_WORD),
983                                into_target, unsignedp, next_methods);
984
985           if (inter != 0 && inter != into_target)
986             emit_move_insn (into_target, inter);
987
988           /* For a signed right shift, we must fill the word we are shifting
989              out of with copies of the sign bit.  Otherwise it is zeroed.  */
990           if (inter != 0 && binoptab != ashr_optab)
991             inter = CONST0_RTX (word_mode);
992           else if (inter != 0)
993             inter = expand_binop (word_mode, binoptab,
994                                   outof_input,
995                                   GEN_INT (BITS_PER_WORD - 1),
996                                   outof_target, unsignedp, next_methods);
997
998           if (inter != 0 && inter != outof_target)
999             emit_move_insn (outof_target, inter);
1000         }
1001       else
1002         {
1003           rtx carries;
1004           optab reverse_unsigned_shift, unsigned_shift;
1005
1006           /* For a shift of less then BITS_PER_WORD, to compute the carry,
1007              we must do a logical shift in the opposite direction of the
1008              desired shift.  */
1009
1010           reverse_unsigned_shift = (left_shift ? lshr_optab : ashl_optab);
1011
1012           /* For a shift of less than BITS_PER_WORD, to compute the word
1013              shifted towards, we need to unsigned shift the orig value of
1014              that word.  */
1015
1016           unsigned_shift = (left_shift ? ashl_optab : lshr_optab);
1017
1018           carries = expand_binop (word_mode, reverse_unsigned_shift,
1019                                   outof_input,
1020                                   GEN_INT (BITS_PER_WORD - shift_count),
1021                                   0, unsignedp, next_methods);
1022
1023           if (carries == 0)
1024             inter = 0;
1025           else
1026             inter = expand_binop (word_mode, unsigned_shift, into_input,
1027                                   op1, 0, unsignedp, next_methods);
1028
1029           if (inter != 0)
1030             inter = expand_binop (word_mode, ior_optab, carries, inter,
1031                                   into_target, unsignedp, next_methods);
1032
1033           if (inter != 0 && inter != into_target)
1034             emit_move_insn (into_target, inter);
1035
1036           if (inter != 0)
1037             inter = expand_binop (word_mode, binoptab, outof_input,
1038                                   op1, outof_target, unsignedp, next_methods);
1039           
1040           if (inter != 0 && inter != outof_target)
1041             emit_move_insn (outof_target, inter);
1042         }
1043
1044       insns = get_insns ();
1045       end_sequence ();
1046
1047       if (inter != 0)
1048         {
1049           if (binoptab->code != UNKNOWN)
1050             equiv_value = gen_rtx_fmt_ee (binoptab->code, mode, op0, op1);
1051           else
1052             equiv_value = 0;
1053
1054           emit_no_conflict_block (insns, target, op0, op1, equiv_value);
1055           return target;
1056         }
1057     }
1058
1059   /* Synthesize double word rotates from single word shifts.  */
1060   if ((binoptab == rotl_optab || binoptab == rotr_optab)
1061       && class == MODE_INT
1062       && GET_CODE (op1) == CONST_INT
1063       && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
1064       && ashl_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
1065       && lshr_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
1066     {
1067       rtx insns, equiv_value;
1068       rtx into_target, outof_target;
1069       rtx into_input, outof_input;
1070       rtx inter;
1071       int shift_count, left_shift, outof_word;
1072
1073       /* If TARGET is the same as one of the operands, the REG_EQUAL note
1074          won't be accurate, so use a new target.  */
1075       if (target == 0 || target == op0 || target == op1)
1076         target = gen_reg_rtx (mode);
1077
1078       start_sequence ();
1079
1080       shift_count = INTVAL (op1);
1081
1082       /* OUTOF_* is the word we are shifting bits away from, and
1083          INTO_* is the word that we are shifting bits towards, thus
1084          they differ depending on the direction of the shift and
1085          WORDS_BIG_ENDIAN.  */
1086
1087       left_shift = (binoptab == rotl_optab);
1088       outof_word = left_shift ^ ! WORDS_BIG_ENDIAN;
1089
1090       outof_target = operand_subword (target, outof_word, 1, mode);
1091       into_target = operand_subword (target, 1 - outof_word, 1, mode);
1092
1093       outof_input = operand_subword_force (op0, outof_word, mode);
1094       into_input = operand_subword_force (op0, 1 - outof_word, mode);
1095
1096       if (shift_count == BITS_PER_WORD)
1097         {
1098           /* This is just a word swap.  */
1099           emit_move_insn (outof_target, into_input);
1100           emit_move_insn (into_target, outof_input);
1101           inter = const0_rtx;
1102         }
1103       else
1104         {
1105           rtx into_temp1, into_temp2, outof_temp1, outof_temp2;
1106           rtx first_shift_count, second_shift_count;
1107           optab reverse_unsigned_shift, unsigned_shift;
1108
1109           reverse_unsigned_shift = (left_shift ^ (shift_count < BITS_PER_WORD)
1110                                     ? lshr_optab : ashl_optab);
1111
1112           unsigned_shift = (left_shift ^ (shift_count < BITS_PER_WORD)
1113                             ? ashl_optab : lshr_optab);
1114
1115           if (shift_count > BITS_PER_WORD)
1116             {
1117               first_shift_count = GEN_INT (shift_count - BITS_PER_WORD);
1118               second_shift_count = GEN_INT (2*BITS_PER_WORD - shift_count);
1119             }
1120           else
1121             {
1122               first_shift_count = GEN_INT (BITS_PER_WORD - shift_count);
1123               second_shift_count = GEN_INT (shift_count);
1124             }
1125
1126           into_temp1 = expand_binop (word_mode, unsigned_shift,
1127                                      outof_input, first_shift_count,
1128                                      NULL_RTX, unsignedp, next_methods);
1129           into_temp2 = expand_binop (word_mode, reverse_unsigned_shift,
1130                                      into_input, second_shift_count,
1131                                      into_target, unsignedp, next_methods);
1132
1133           if (into_temp1 != 0 && into_temp2 != 0)
1134             inter = expand_binop (word_mode, ior_optab, into_temp1, into_temp2,
1135                                   into_target, unsignedp, next_methods);
1136           else
1137             inter = 0;
1138
1139           if (inter != 0 && inter != into_target)
1140             emit_move_insn (into_target, inter);
1141
1142           outof_temp1 = expand_binop (word_mode, unsigned_shift,
1143                                       into_input, first_shift_count,
1144                                       NULL_RTX, unsignedp, next_methods);
1145           outof_temp2 = expand_binop (word_mode, reverse_unsigned_shift,
1146                                       outof_input, second_shift_count,
1147                                       outof_target, unsignedp, next_methods);
1148
1149           if (inter != 0 && outof_temp1 != 0 && outof_temp2 != 0)
1150             inter = expand_binop (word_mode, ior_optab,
1151                                   outof_temp1, outof_temp2,
1152                                   outof_target, unsignedp, next_methods);
1153
1154           if (inter != 0 && inter != outof_target)
1155             emit_move_insn (outof_target, inter);
1156         }
1157
1158       insns = get_insns ();
1159       end_sequence ();
1160
1161       if (inter != 0)
1162         {
1163           if (binoptab->code != UNKNOWN)
1164             equiv_value = gen_rtx_fmt_ee (binoptab->code, mode, op0, op1);
1165           else
1166             equiv_value = 0;
1167
1168           /* We can't make this a no conflict block if this is a word swap,
1169              because the word swap case fails if the input and output values
1170              are in the same register.  */
1171           if (shift_count != BITS_PER_WORD)
1172             emit_no_conflict_block (insns, target, op0, op1, equiv_value);
1173           else
1174             emit_insns (insns);
1175
1176
1177           return target;
1178         }
1179     }
1180
1181   /* These can be done a word at a time by propagating carries.  */
1182   if ((binoptab == add_optab || binoptab == sub_optab)
1183       && class == MODE_INT
1184       && GET_MODE_SIZE (mode) >= 2 * UNITS_PER_WORD
1185       && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
1186     {
1187       int i;
1188       optab otheroptab = binoptab == add_optab ? sub_optab : add_optab;
1189       int nwords = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
1190       rtx carry_in = NULL_RTX, carry_out = NULL_RTX;
1191       rtx xop0, xop1, xtarget;
1192
1193       /* We can handle either a 1 or -1 value for the carry.  If STORE_FLAG
1194          value is one of those, use it.  Otherwise, use 1 since it is the
1195          one easiest to get.  */
1196 #if STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1
1197       int normalizep = STORE_FLAG_VALUE;
1198 #else
1199       int normalizep = 1;
1200 #endif
1201
1202       /* Prepare the operands.  */
1203       xop0 = force_reg (mode, op0);
1204       xop1 = force_reg (mode, op1);
1205
1206       xtarget = gen_reg_rtx (mode);
1207
1208       if (target == 0 || GET_CODE (target) != REG)
1209         target = xtarget;
1210
1211       /* Indicate for flow that the entire target reg is being set.  */
1212       if (GET_CODE (target) == REG)
1213         emit_insn (gen_rtx_CLOBBER (VOIDmode, xtarget));
1214
1215       /* Do the actual arithmetic.  */
1216       for (i = 0; i < nwords; i++)
1217         {
1218           int index = (WORDS_BIG_ENDIAN ? nwords - i - 1 : i);
1219           rtx target_piece = operand_subword (xtarget, index, 1, mode);
1220           rtx op0_piece = operand_subword_force (xop0, index, mode);
1221           rtx op1_piece = operand_subword_force (xop1, index, mode);
1222           rtx x;
1223
1224           /* Main add/subtract of the input operands.  */
1225           x = expand_binop (word_mode, binoptab,
1226                             op0_piece, op1_piece,
1227                             target_piece, unsignedp, next_methods);
1228           if (x == 0)
1229             break;
1230
1231           if (i + 1 < nwords)
1232             {
1233               /* Store carry from main add/subtract.  */
1234               carry_out = gen_reg_rtx (word_mode);
1235               carry_out = emit_store_flag_force (carry_out,
1236                                                  (binoptab == add_optab
1237                                                   ? LT : GT),
1238                                                  x, op0_piece,
1239                                                  word_mode, 1, normalizep);
1240             }
1241
1242           if (i > 0)
1243             {
1244               rtx newx;
1245               
1246               /* Add/subtract previous carry to main result.  */
1247               newx = expand_binop (word_mode,
1248                                    normalizep == 1 ? binoptab : otheroptab,
1249                                    x, carry_in,
1250                                    NULL_RTX, 1, next_methods);
1251
1252               if (i + 1 < nwords)
1253                 {
1254                   /* Get out carry from adding/subtracting carry in.  */
1255                   rtx carry_tmp = gen_reg_rtx (word_mode);
1256                   carry_tmp = emit_store_flag_force (carry_tmp,
1257                                                      (binoptab == add_optab
1258                                                       ? LT : GT),
1259                                                      newx, x,
1260                                                      word_mode, 1, normalizep);
1261
1262                   /* Logical-ior the two poss. carry together.  */
1263                   carry_out = expand_binop (word_mode, ior_optab,
1264                                             carry_out, carry_tmp,
1265                                             carry_out, 0, next_methods);
1266                   if (carry_out == 0)
1267                     break;
1268                 }
1269               emit_move_insn (target_piece, newx);
1270             }
1271
1272           carry_in = carry_out;
1273         }       
1274
1275       if (i == GET_MODE_BITSIZE (mode) / BITS_PER_WORD)
1276         {
1277           if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1278             {
1279               rtx temp = emit_move_insn (target, xtarget);
1280
1281               set_unique_reg_note (temp,
1282                                    REG_EQUAL,
1283                                    gen_rtx_fmt_ee (binoptab->code, mode,
1284                                                    copy_rtx (xop0),
1285                                                    copy_rtx (xop1)));
1286             }
1287
1288           return target;
1289         }
1290
1291       else
1292         delete_insns_since (last);
1293     }
1294
1295   /* If we want to multiply two two-word values and have normal and widening
1296      multiplies of single-word values, we can do this with three smaller
1297      multiplications.  Note that we do not make a REG_NO_CONFLICT block here
1298      because we are not operating on one word at a time. 
1299
1300      The multiplication proceeds as follows:
1301                                  _______________________
1302                                 [__op0_high_|__op0_low__]
1303                                  _______________________
1304         *                       [__op1_high_|__op1_low__]
1305         _______________________________________________
1306                                  _______________________
1307     (1)                         [__op0_low__*__op1_low__]
1308                      _______________________
1309     (2a)            [__op0_low__*__op1_high_]
1310                      _______________________
1311     (2b)            [__op0_high_*__op1_low__]
1312          _______________________
1313     (3) [__op0_high_*__op1_high_]
1314
1315
1316     This gives a 4-word result.  Since we are only interested in the
1317     lower 2 words, partial result (3) and the upper words of (2a) and
1318     (2b) don't need to be calculated.  Hence (2a) and (2b) can be
1319     calculated using non-widening multiplication.
1320
1321     (1), however, needs to be calculated with an unsigned widening
1322     multiplication.  If this operation is not directly supported we
1323     try using a signed widening multiplication and adjust the result.
1324     This adjustment works as follows:
1325
1326       If both operands are positive then no adjustment is needed.
1327
1328       If the operands have different signs, for example op0_low < 0 and
1329       op1_low >= 0, the instruction treats the most significant bit of
1330       op0_low as a sign bit instead of a bit with significance
1331       2**(BITS_PER_WORD-1), i.e. the instruction multiplies op1_low
1332       with 2**BITS_PER_WORD - op0_low, and two's complements the
1333       result.  Conclusion: We need to add op1_low * 2**BITS_PER_WORD to
1334       the result.
1335
1336       Similarly, if both operands are negative, we need to add
1337       (op0_low + op1_low) * 2**BITS_PER_WORD.
1338
1339       We use a trick to adjust quickly.  We logically shift op0_low right
1340       (op1_low) BITS_PER_WORD-1 steps to get 0 or 1, and add this to
1341       op0_high (op1_high) before it is used to calculate 2b (2a).  If no
1342       logical shift exists, we do an arithmetic right shift and subtract
1343       the 0 or -1.  */
1344
1345   if (binoptab == smul_optab
1346       && class == MODE_INT
1347       && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
1348       && smul_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
1349       && add_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
1350       && ((umul_widen_optab->handlers[(int) mode].insn_code
1351            != CODE_FOR_nothing)
1352           || (smul_widen_optab->handlers[(int) mode].insn_code
1353               != CODE_FOR_nothing)))
1354     {
1355       int low = (WORDS_BIG_ENDIAN ? 1 : 0);
1356       int high = (WORDS_BIG_ENDIAN ? 0 : 1);
1357       rtx op0_high = operand_subword_force (op0, high, mode);
1358       rtx op0_low = operand_subword_force (op0, low, mode);
1359       rtx op1_high = operand_subword_force (op1, high, mode);
1360       rtx op1_low = operand_subword_force (op1, low, mode);
1361       rtx product = 0;
1362       rtx op0_xhigh = NULL_RTX;
1363       rtx op1_xhigh = NULL_RTX;
1364
1365       /* If the target is the same as one of the inputs, don't use it.  This
1366          prevents problems with the REG_EQUAL note.  */
1367       if (target == op0 || target == op1
1368           || (target != 0 && GET_CODE (target) != REG))
1369         target = 0;
1370
1371       /* Multiply the two lower words to get a double-word product.
1372          If unsigned widening multiplication is available, use that;
1373          otherwise use the signed form and compensate.  */
1374
1375       if (umul_widen_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1376         {
1377           product = expand_binop (mode, umul_widen_optab, op0_low, op1_low,
1378                                   target, 1, OPTAB_DIRECT);
1379
1380           /* If we didn't succeed, delete everything we did so far.  */
1381           if (product == 0)
1382             delete_insns_since (last);
1383           else
1384             op0_xhigh = op0_high, op1_xhigh = op1_high;
1385         }
1386
1387       if (product == 0
1388           && smul_widen_optab->handlers[(int) mode].insn_code
1389                != CODE_FOR_nothing)
1390         {
1391           rtx wordm1 = GEN_INT (BITS_PER_WORD - 1);
1392           product = expand_binop (mode, smul_widen_optab, op0_low, op1_low,
1393                                   target, 1, OPTAB_DIRECT);
1394           op0_xhigh = expand_binop (word_mode, lshr_optab, op0_low, wordm1,
1395                                     NULL_RTX, 1, next_methods);
1396           if (op0_xhigh)
1397             op0_xhigh = expand_binop (word_mode, add_optab, op0_high,
1398                                       op0_xhigh, op0_xhigh, 0, next_methods);
1399           else
1400             {
1401               op0_xhigh = expand_binop (word_mode, ashr_optab, op0_low, wordm1,
1402                                         NULL_RTX, 0, next_methods);
1403               if (op0_xhigh)
1404                 op0_xhigh = expand_binop (word_mode, sub_optab, op0_high,
1405                                           op0_xhigh, op0_xhigh, 0,
1406                                           next_methods);
1407             }
1408
1409           op1_xhigh = expand_binop (word_mode, lshr_optab, op1_low, wordm1,
1410                                     NULL_RTX, 1, next_methods);
1411           if (op1_xhigh)
1412             op1_xhigh = expand_binop (word_mode, add_optab, op1_high,
1413                                       op1_xhigh, op1_xhigh, 0, next_methods);
1414           else
1415             {
1416               op1_xhigh = expand_binop (word_mode, ashr_optab, op1_low, wordm1,
1417                                         NULL_RTX, 0, next_methods);
1418               if (op1_xhigh)
1419                 op1_xhigh = expand_binop (word_mode, sub_optab, op1_high,
1420                                           op1_xhigh, op1_xhigh, 0,
1421                                           next_methods);
1422             }
1423         }
1424
1425       /* If we have been able to directly compute the product of the
1426          low-order words of the operands and perform any required adjustments
1427          of the operands, we proceed by trying two more multiplications
1428          and then computing the appropriate sum.
1429
1430          We have checked above that the required addition is provided.
1431          Full-word addition will normally always succeed, especially if
1432          it is provided at all, so we don't worry about its failure.  The
1433          multiplication may well fail, however, so we do handle that.  */
1434
1435       if (product && op0_xhigh && op1_xhigh)
1436         {
1437           rtx product_high = operand_subword (product, high, 1, mode);
1438           rtx temp = expand_binop (word_mode, binoptab, op0_low, op1_xhigh,
1439                                    NULL_RTX, 0, OPTAB_DIRECT);
1440
1441           if (!REG_P (product_high))
1442             product_high = force_reg (word_mode, product_high);
1443
1444           if (temp != 0)
1445             temp = expand_binop (word_mode, add_optab, temp, product_high,
1446                                  product_high, 0, next_methods);
1447
1448           if (temp != 0 && temp != product_high)
1449             emit_move_insn (product_high, temp);
1450
1451           if (temp != 0)
1452             temp = expand_binop (word_mode, binoptab, op1_low, op0_xhigh, 
1453                                  NULL_RTX, 0, OPTAB_DIRECT);
1454
1455           if (temp != 0)
1456             temp = expand_binop (word_mode, add_optab, temp,
1457                                  product_high, product_high,
1458                                  0, next_methods);
1459
1460           if (temp != 0 && temp != product_high)
1461             emit_move_insn (product_high, temp);
1462
1463           emit_move_insn (operand_subword (product, high, 1, mode), product_high);
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, note;
2743       int i;
2744
2745       next = NEXT_INSN (insn);
2746
2747       /* Some ports (cris) create an libcall regions at their own.  We must
2748          avoid any potential nesting of LIBCALLs.  */
2749       if ((note = find_reg_note (insn, REG_LIBCALL, NULL)) != NULL)
2750         remove_note (insn, note);
2751       if ((note = find_reg_note (insn, REG_RETVAL, NULL)) != NULL)
2752         remove_note (insn, note);
2753
2754       if (GET_CODE (PATTERN (insn)) == SET || GET_CODE (PATTERN (insn)) == USE
2755           || GET_CODE (PATTERN (insn)) == CLOBBER)
2756         set = PATTERN (insn);
2757       else if (GET_CODE (PATTERN (insn)) == PARALLEL)
2758         {
2759           for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
2760             if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET)
2761               {
2762                 set = XVECEXP (PATTERN (insn), 0, i);
2763                 break;
2764               }
2765         }
2766
2767       if (set == 0)
2768         abort ();
2769
2770       if (! reg_overlap_mentioned_p (target, SET_DEST (set)))
2771         {
2772           if (PREV_INSN (insn))
2773             NEXT_INSN (PREV_INSN (insn)) = next;
2774           else
2775             insns = next;
2776
2777           if (next)
2778             PREV_INSN (next) = PREV_INSN (insn);
2779
2780           add_insn (insn);
2781         }
2782     }
2783
2784   prev = get_last_insn ();
2785
2786   /* Now write the CLOBBER of the output, followed by the setting of each
2787      of the words, followed by the final copy.  */
2788   if (target != op0 && target != op1)
2789     emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
2790
2791   for (insn = insns; insn; insn = next)
2792     {
2793       next = NEXT_INSN (insn);
2794       add_insn (insn);
2795
2796       if (op1 && GET_CODE (op1) == REG)
2797         REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_NO_CONFLICT, op1,
2798                                               REG_NOTES (insn));
2799
2800       if (op0 && GET_CODE (op0) == REG)
2801         REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_NO_CONFLICT, op0,
2802                                               REG_NOTES (insn));
2803     }
2804
2805   if (mov_optab->handlers[(int) GET_MODE (target)].insn_code
2806       != CODE_FOR_nothing)
2807     {
2808       last = emit_move_insn (target, target);
2809       if (equiv)
2810         set_unique_reg_note (last, REG_EQUAL, equiv);
2811     }
2812   else
2813     {
2814       last = get_last_insn ();
2815
2816       /* Remove any existing REG_EQUAL note from "last", or else it will
2817          be mistaken for a note referring to the full contents of the
2818          alleged libcall value when found together with the REG_RETVAL
2819          note added below.  An existing note can come from an insn
2820          expansion at "last".  */
2821       remove_note (last, find_reg_note (last, REG_EQUAL, NULL_RTX));
2822     }
2823
2824   if (prev == 0)
2825     first = get_insns ();
2826   else
2827     first = NEXT_INSN (prev);
2828
2829   /* Encapsulate the block so it gets manipulated as a unit.  */
2830   REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last,
2831                                          REG_NOTES (first));
2832   REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
2833
2834   return last;
2835 }
2836 \f
2837 /* Emit code to make a call to a constant function or a library call.
2838
2839    INSNS is a list containing all insns emitted in the call.
2840    These insns leave the result in RESULT.  Our block is to copy RESULT
2841    to TARGET, which is logically equivalent to EQUIV.
2842
2843    We first emit any insns that set a pseudo on the assumption that these are
2844    loading constants into registers; doing so allows them to be safely cse'ed
2845    between blocks.  Then we emit all the other insns in the block, followed by
2846    an insn to move RESULT to TARGET.  This last insn will have a REQ_EQUAL
2847    note with an operand of EQUIV.
2848
2849    Moving assignments to pseudos outside of the block is done to improve
2850    the generated code, but is not required to generate correct code,
2851    hence being unable to move an assignment is not grounds for not making
2852    a libcall block.  There are two reasons why it is safe to leave these
2853    insns inside the block: First, we know that these pseudos cannot be
2854    used in generated RTL outside the block since they are created for
2855    temporary purposes within the block.  Second, CSE will not record the
2856    values of anything set inside a libcall block, so we know they must
2857    be dead at the end of the block.
2858
2859    Except for the first group of insns (the ones setting pseudos), the
2860    block is delimited by REG_RETVAL and REG_LIBCALL notes.  */
2861
2862 void
2863 emit_libcall_block (insns, target, result, equiv)
2864      rtx insns;
2865      rtx target;
2866      rtx result;
2867      rtx equiv;
2868 {
2869   rtx final_dest = target;
2870   rtx prev, next, first, last, insn;
2871
2872   /* If this is a reg with REG_USERVAR_P set, then it could possibly turn
2873      into a MEM later.  Protect the libcall block from this change.  */
2874   if (! REG_P (target) || REG_USERVAR_P (target))
2875     target = gen_reg_rtx (GET_MODE (target));
2876   
2877   /* If we're using non-call exceptions, a libcall corresponding to an
2878      operation that may trap may also trap.  */
2879   if (flag_non_call_exceptions && may_trap_p (equiv))
2880     {
2881       for (insn = insns; insn; insn = NEXT_INSN (insn))
2882         if (GET_CODE (insn) == CALL_INSN)
2883           {
2884             rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
2885             
2886             if (note != 0 && INTVAL (XEXP (note, 0)) <= 0)
2887               remove_note (insn, note);
2888           }
2889     }
2890   else
2891   /* look for any CALL_INSNs in this sequence, and attach a REG_EH_REGION
2892      reg note to indicate that this call cannot throw or execute a nonlocal
2893      goto (unless there is already a REG_EH_REGION note, in which case
2894      we update it).  */
2895     for (insn = insns; insn; insn = NEXT_INSN (insn))
2896       if (GET_CODE (insn) == CALL_INSN)
2897         {
2898           rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
2899         
2900           if (note != 0)
2901             XEXP (note, 0) = GEN_INT (-1);
2902           else
2903             REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EH_REGION, GEN_INT (-1),
2904                                                   REG_NOTES (insn));
2905         }
2906
2907   /* First emit all insns that set pseudos.  Remove them from the list as
2908      we go.  Avoid insns that set pseudos which were referenced in previous
2909      insns.  These can be generated by move_by_pieces, for example,
2910      to update an address.  Similarly, avoid insns that reference things
2911      set in previous insns.  */
2912
2913   for (insn = insns; insn; insn = next)
2914     {
2915       rtx set = single_set (insn);
2916       rtx note;
2917
2918       /* Some ports (cris) create an libcall regions at their own.  We must
2919          avoid any potential nesting of LIBCALLs.  */
2920       if ((note = find_reg_note (insn, REG_LIBCALL, NULL)) != NULL)
2921         remove_note (insn, note);
2922       if ((note = find_reg_note (insn, REG_RETVAL, NULL)) != NULL)
2923         remove_note (insn, note);
2924
2925       next = NEXT_INSN (insn);
2926
2927       if (set != 0 && GET_CODE (SET_DEST (set)) == REG
2928           && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER
2929           && (insn == insns
2930               || ((! INSN_P(insns)
2931                    || ! reg_mentioned_p (SET_DEST (set), PATTERN (insns)))
2932                   && ! reg_used_between_p (SET_DEST (set), insns, insn)
2933                   && ! modified_in_p (SET_SRC (set), insns)
2934                   && ! modified_between_p (SET_SRC (set), insns, insn))))
2935         {
2936           if (PREV_INSN (insn))
2937             NEXT_INSN (PREV_INSN (insn)) = next;
2938           else
2939             insns = next;
2940
2941           if (next)
2942             PREV_INSN (next) = PREV_INSN (insn);
2943
2944           add_insn (insn);
2945         }
2946     }
2947
2948   prev = get_last_insn ();
2949
2950   /* Write the remaining insns followed by the final copy.  */
2951
2952   for (insn = insns; insn; insn = next)
2953     {
2954       next = NEXT_INSN (insn);
2955
2956       add_insn (insn);
2957     }
2958
2959   last = emit_move_insn (target, result);
2960   if (mov_optab->handlers[(int) GET_MODE (target)].insn_code
2961       != CODE_FOR_nothing)
2962     set_unique_reg_note (last, REG_EQUAL, copy_rtx (equiv));
2963   else
2964     {
2965       /* Remove any existing REG_EQUAL note from "last", or else it will
2966          be mistaken for a note referring to the full contents of the
2967          libcall value when found together with the REG_RETVAL note added
2968          below.  An existing note can come from an insn expansion at
2969          "last".  */
2970       remove_note (last, find_reg_note (last, REG_EQUAL, NULL_RTX));
2971     }
2972
2973   if (final_dest != target)
2974     emit_move_insn (final_dest, target);
2975
2976   if (prev == 0)
2977     first = get_insns ();
2978   else
2979     first = NEXT_INSN (prev);
2980
2981   /* Encapsulate the block so it gets manipulated as a unit.  */
2982   if (!flag_non_call_exceptions || !may_trap_p (equiv))
2983     {
2984       REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last,
2985                                              REG_NOTES (first));
2986       REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first,
2987                                             REG_NOTES (last));
2988     }
2989 }
2990 \f
2991 /* Generate code to store zero in X.  */
2992
2993 void
2994 emit_clr_insn (x)
2995      rtx x;
2996 {
2997   emit_move_insn (x, const0_rtx);
2998 }
2999
3000 /* Generate code to store 1 in X
3001    assuming it contains zero beforehand.  */
3002
3003 void
3004 emit_0_to_1_insn (x)
3005      rtx x;
3006 {
3007   emit_move_insn (x, const1_rtx);
3008 }
3009
3010 /* Nonzero if we can perform a comparison of mode MODE straightforwardly.
3011    PURPOSE describes how this comparison will be used.  CODE is the rtx
3012    comparison code we will be using.
3013
3014    ??? Actually, CODE is slightly weaker than that.  A target is still
3015    required to implement all of the normal bcc operations, but not 
3016    required to implement all (or any) of the unordered bcc operations.  */
3017   
3018 int
3019 can_compare_p (code, mode, purpose)
3020      enum rtx_code code;
3021      enum machine_mode mode;
3022      enum can_compare_purpose purpose;
3023 {
3024   do
3025     {
3026       if (cmp_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)
3027         {
3028           if (purpose == ccp_jump)
3029             return bcc_gen_fctn[(int)code] != NULL;
3030           else if (purpose == ccp_store_flag)
3031             return setcc_gen_code[(int)code] != CODE_FOR_nothing;
3032           else
3033             /* There's only one cmov entry point, and it's allowed to fail.  */
3034             return 1;
3035         }
3036       if (purpose == ccp_jump
3037           && cbranch_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)
3038         return 1;
3039       if (purpose == ccp_cmov
3040           && cmov_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)
3041         return 1;
3042       if (purpose == ccp_store_flag
3043           && cstore_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)
3044         return 1;
3045
3046       mode = GET_MODE_WIDER_MODE (mode);
3047     }
3048   while (mode != VOIDmode);
3049
3050   return 0;
3051 }
3052
3053 /* This function is called when we are going to emit a compare instruction that
3054    compares the values found in *PX and *PY, using the rtl operator COMPARISON.
3055
3056    *PMODE is the mode of the inputs (in case they are const_int).
3057    *PUNSIGNEDP nonzero says that the operands are unsigned;
3058    this matters if they need to be widened.
3059
3060    If they have mode BLKmode, then SIZE specifies the size of both operands.
3061
3062    This function performs all the setup necessary so that the caller only has
3063    to emit a single comparison insn.  This setup can involve doing a BLKmode
3064    comparison or emitting a library call to perform the comparison if no insn
3065    is available to handle it.
3066    The values which are passed in through pointers can be modified; the caller
3067    should perform the comparison on the modified values.  */
3068
3069 static void
3070 prepare_cmp_insn (px, py, pcomparison, size, pmode, punsignedp, purpose)
3071      rtx *px, *py;
3072      enum rtx_code *pcomparison;
3073      rtx size;
3074      enum machine_mode *pmode;
3075      int *punsignedp;
3076      enum can_compare_purpose purpose;
3077 {
3078   enum machine_mode mode = *pmode;
3079   rtx x = *px, y = *py;
3080   int unsignedp = *punsignedp;
3081   enum mode_class class;
3082
3083   class = GET_MODE_CLASS (mode);
3084
3085   /* They could both be VOIDmode if both args are immediate constants,
3086      but we should fold that at an earlier stage.
3087      With no special code here, this will call abort,
3088      reminding the programmer to implement such folding.  */
3089
3090   if (mode != BLKmode && flag_force_mem)
3091     {
3092       x = force_not_mem (x);
3093       y = force_not_mem (y);
3094     }
3095
3096   /* If we are inside an appropriately-short loop and one operand is an
3097      expensive constant, force it into a register.  */
3098   if (CONSTANT_P (x) && preserve_subexpressions_p ()
3099       && rtx_cost (x, COMPARE) > COSTS_N_INSNS (1))
3100     x = force_reg (mode, x);
3101
3102   if (CONSTANT_P (y) && preserve_subexpressions_p ()
3103       && rtx_cost (y, COMPARE) > COSTS_N_INSNS (1))
3104     y = force_reg (mode, y);
3105
3106 #ifdef HAVE_cc0
3107   /* Abort if we have a non-canonical comparison.  The RTL documentation
3108      states that canonical comparisons are required only for targets which
3109      have cc0.  */
3110   if (CONSTANT_P (x) && ! CONSTANT_P (y))
3111     abort();
3112 #endif
3113
3114   /* Don't let both operands fail to indicate the mode.  */
3115   if (GET_MODE (x) == VOIDmode && GET_MODE (y) == VOIDmode)
3116     x = force_reg (mode, x);
3117
3118   /* Handle all BLKmode compares.  */
3119
3120   if (mode == BLKmode)
3121     {
3122       rtx result;
3123       enum machine_mode result_mode;
3124       rtx opalign ATTRIBUTE_UNUSED
3125         = GEN_INT (MIN (MEM_ALIGN (x), MEM_ALIGN (y)) / BITS_PER_UNIT);
3126
3127       emit_queue ();
3128       x = protect_from_queue (x, 0);
3129       y = protect_from_queue (y, 0);
3130
3131       if (size == 0)
3132         abort ();
3133 #ifdef HAVE_cmpstrqi
3134       if (HAVE_cmpstrqi
3135           && GET_CODE (size) == CONST_INT
3136           && INTVAL (size) < (1 << GET_MODE_BITSIZE (QImode)))
3137         {
3138           result_mode = insn_data[(int) CODE_FOR_cmpstrqi].operand[0].mode;
3139           result = gen_reg_rtx (result_mode);
3140           emit_insn (gen_cmpstrqi (result, x, y, size, opalign));
3141         }
3142       else
3143 #endif
3144 #ifdef HAVE_cmpstrhi
3145       if (HAVE_cmpstrhi
3146           && GET_CODE (size) == CONST_INT
3147           && INTVAL (size) < (1 << GET_MODE_BITSIZE (HImode)))
3148         {
3149           result_mode = insn_data[(int) CODE_FOR_cmpstrhi].operand[0].mode;
3150           result = gen_reg_rtx (result_mode);
3151           emit_insn (gen_cmpstrhi (result, x, y, size, opalign));
3152         }
3153       else
3154 #endif
3155 #ifdef HAVE_cmpstrsi
3156       if (HAVE_cmpstrsi)
3157         {
3158           result_mode = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
3159           result = gen_reg_rtx (result_mode);
3160           size = protect_from_queue (size, 0);
3161           emit_insn (gen_cmpstrsi (result, x, y,
3162                                    convert_to_mode (SImode, size, 1),
3163                                    opalign));
3164         }
3165       else
3166 #endif
3167         {
3168 #ifdef TARGET_MEM_FUNCTIONS
3169           emit_library_call (memcmp_libfunc, LCT_PURE_MAKE_BLOCK,
3170                              TYPE_MODE (integer_type_node), 3,
3171                              XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
3172                              convert_to_mode (TYPE_MODE (sizetype), size,
3173                                               TREE_UNSIGNED (sizetype)),
3174                              TYPE_MODE (sizetype));
3175 #else
3176           emit_library_call (bcmp_libfunc, LCT_PURE_MAKE_BLOCK,
3177                              TYPE_MODE (integer_type_node), 3,
3178                              XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
3179                              convert_to_mode (TYPE_MODE (integer_type_node),
3180                                               size,
3181                                               TREE_UNSIGNED (integer_type_node)),
3182                              TYPE_MODE (integer_type_node));
3183 #endif
3184
3185           /* Immediately move the result of the libcall into a pseudo
3186              register so reload doesn't clobber the value if it needs
3187              the return register for a spill reg.  */
3188           result = gen_reg_rtx (TYPE_MODE (integer_type_node));
3189           result_mode = TYPE_MODE (integer_type_node);
3190           emit_move_insn (result,
3191                           hard_libcall_value (result_mode));
3192         }
3193       *px = result;
3194       *py = const0_rtx;
3195       *pmode = result_mode;
3196       return;
3197     }
3198
3199   *px = x;
3200   *py = y;
3201   if (can_compare_p (*pcomparison, mode, purpose))
3202     return;
3203
3204   /* Handle a lib call just for the mode we are using.  */
3205
3206   if (cmp_optab->handlers[(int) mode].libfunc && class != MODE_FLOAT)
3207     {
3208       rtx libfunc = cmp_optab->handlers[(int) mode].libfunc;
3209       rtx result;
3210
3211       /* If we want unsigned, and this mode has a distinct unsigned
3212          comparison routine, use that.  */
3213       if (unsignedp && ucmp_optab->handlers[(int) mode].libfunc)
3214         libfunc = ucmp_optab->handlers[(int) mode].libfunc;
3215
3216       emit_library_call (libfunc, LCT_CONST_MAKE_BLOCK, word_mode, 2, x, mode,
3217                          y, mode);
3218
3219       /* Immediately move the result of the libcall into a pseudo
3220          register so reload doesn't clobber the value if it needs
3221          the return register for a spill reg.  */
3222       result = gen_reg_rtx (word_mode);
3223       emit_move_insn (result, hard_libcall_value (word_mode));
3224
3225       /* Integer comparison returns a result that must be compared against 1,
3226          so that even if we do an unsigned compare afterward,
3227          there is still a value that can represent the result "less than".  */
3228       *px = result;
3229       *py = const1_rtx;
3230       *pmode = word_mode;
3231       return;
3232     }
3233
3234   if (class == MODE_FLOAT)
3235     prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp);
3236
3237   else
3238     abort ();
3239 }
3240
3241 /* Before emitting an insn with code ICODE, make sure that X, which is going
3242    to be used for operand OPNUM of the insn, is converted from mode MODE to
3243    WIDER_MODE (UNSIGNEDP determines whether it is an unsigned conversion), and
3244    that it is accepted by the operand predicate.  Return the new value.  */
3245
3246 rtx
3247 prepare_operand (icode, x, opnum, mode, wider_mode, unsignedp)
3248      int icode;
3249      rtx x;
3250      int opnum;
3251      enum machine_mode mode, wider_mode;
3252      int unsignedp;
3253 {
3254   x = protect_from_queue (x, 0);
3255
3256   if (mode != wider_mode)
3257     x = convert_modes (wider_mode, mode, x, unsignedp);
3258
3259   if (! (*insn_data[icode].operand[opnum].predicate)
3260       (x, insn_data[icode].operand[opnum].mode))
3261     x = copy_to_mode_reg (insn_data[icode].operand[opnum].mode, x);
3262   return x;
3263 }
3264
3265 /* Subroutine of emit_cmp_and_jump_insns; this function is called when we know
3266    we can do the comparison.
3267    The arguments are the same as for emit_cmp_and_jump_insns; but LABEL may
3268    be NULL_RTX which indicates that only a comparison is to be generated.  */
3269
3270 static void
3271 emit_cmp_and_jump_insn_1 (x, y, mode, comparison, unsignedp, label)
3272      rtx x, y;
3273      enum machine_mode mode;
3274      enum rtx_code comparison;
3275      int unsignedp;
3276      rtx label;
3277 {
3278   rtx test = gen_rtx_fmt_ee (comparison, mode, x, y);
3279   enum mode_class class = GET_MODE_CLASS (mode);
3280   enum machine_mode wider_mode = mode;
3281
3282   /* Try combined insns first.  */
3283   do
3284     {
3285       enum insn_code icode;
3286       PUT_MODE (test, wider_mode);
3287
3288       if (label)
3289         {         
3290           icode = cbranch_optab->handlers[(int)wider_mode].insn_code;
3291           
3292           if (icode != CODE_FOR_nothing
3293               && (*insn_data[icode].operand[0].predicate) (test, wider_mode))
3294             {
3295               x = prepare_operand (icode, x, 1, mode, wider_mode, unsignedp);
3296               y = prepare_operand (icode, y, 2, mode, wider_mode, unsignedp);
3297               emit_jump_insn (GEN_FCN (icode) (test, x, y, label));
3298               return;
3299             }
3300         }
3301
3302       /* Handle some compares against zero.  */
3303       icode = (int) tst_optab->handlers[(int) wider_mode].insn_code;
3304       if (y == CONST0_RTX (mode) && icode != CODE_FOR_nothing)
3305         {
3306           x = prepare_operand (icode, x, 0, mode, wider_mode, unsignedp);
3307           emit_insn (GEN_FCN (icode) (x));
3308           if (label)
3309             emit_jump_insn ((*bcc_gen_fctn[(int) comparison]) (label));
3310           return;
3311         }
3312
3313       /* Handle compares for which there is a directly suitable insn.  */
3314
3315       icode = (int) cmp_optab->handlers[(int) wider_mode].insn_code;
3316       if (icode != CODE_FOR_nothing)
3317         {
3318           x = prepare_operand (icode, x, 0, mode, wider_mode, unsignedp);
3319           y = prepare_operand (icode, y, 1, mode, wider_mode, unsignedp);
3320           emit_insn (GEN_FCN (icode) (x, y));
3321           if (label)
3322             emit_jump_insn ((*bcc_gen_fctn[(int) comparison]) (label));
3323           return;
3324         }
3325
3326       if (class != MODE_INT && class != MODE_FLOAT
3327           && class != MODE_COMPLEX_FLOAT)
3328         break;
3329
3330       wider_mode = GET_MODE_WIDER_MODE (wider_mode);
3331     } while (wider_mode != VOIDmode);
3332
3333   abort ();
3334 }
3335
3336 /* Generate code to compare X with Y so that the condition codes are
3337    set and to jump to LABEL if the condition is true.  If X is a
3338    constant and Y is not a constant, then the comparison is swapped to
3339    ensure that the comparison RTL has the canonical form.
3340
3341    UNSIGNEDP nonzero says that X and Y are unsigned; this matters if they
3342    need to be widened by emit_cmp_insn.  UNSIGNEDP is also used to select
3343    the proper branch condition code.
3344
3345    If X and Y have mode BLKmode, then SIZE specifies the size of both X and Y.
3346
3347    MODE is the mode of the inputs (in case they are const_int).
3348
3349    COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).  It will
3350    be passed unchanged to emit_cmp_insn, then potentially converted into an
3351    unsigned variant based on UNSIGNEDP to select a proper jump instruction.  */
3352
3353 void
3354 emit_cmp_and_jump_insns (x, y, comparison, size, mode, unsignedp, label)
3355      rtx x, y;
3356      enum rtx_code comparison;
3357      rtx size;
3358      enum machine_mode mode;
3359      int unsignedp;
3360      rtx label;
3361 {
3362   rtx op0 = x, op1 = y;
3363
3364   /* Swap operands and condition to ensure canonical RTL.  */
3365   if (swap_commutative_operands_p (x, y))
3366     {
3367       /* If we're not emitting a branch, this means some caller
3368          is out of sync.  */
3369       if (! label)
3370         abort ();
3371
3372       op0 = y, op1 = x;
3373       comparison = swap_condition (comparison);
3374     }
3375
3376 #ifdef HAVE_cc0
3377   /* If OP0 is still a constant, then both X and Y must be constants.  Force
3378      X into a register to avoid aborting in emit_cmp_insn due to non-canonical
3379      RTL.  */
3380   if (CONSTANT_P (op0))
3381     op0 = force_reg (mode, op0);
3382 #endif
3383
3384   emit_queue ();
3385   if (unsignedp)
3386     comparison = unsigned_condition (comparison);
3387
3388   prepare_cmp_insn (&op0, &op1, &comparison, size, &mode, &unsignedp,
3389                     ccp_jump);
3390   emit_cmp_and_jump_insn_1 (op0, op1, mode, comparison, unsignedp, label);
3391 }
3392
3393 /* Like emit_cmp_and_jump_insns, but generate only the comparison.  */
3394
3395 void
3396 emit_cmp_insn (x, y, comparison, size, mode, unsignedp)
3397      rtx x, y;
3398      enum rtx_code comparison;
3399      rtx size;
3400      enum machine_mode mode;
3401      int unsignedp;
3402 {
3403   emit_cmp_and_jump_insns (x, y, comparison, size, mode, unsignedp, 0);
3404 }
3405 \f
3406 /* Emit a library call comparison between floating point X and Y.
3407    COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).  */
3408
3409 static void
3410 prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp)
3411      rtx *px, *py;
3412      enum rtx_code *pcomparison;
3413      enum machine_mode *pmode;
3414      int *punsignedp;
3415 {
3416   enum rtx_code comparison = *pcomparison;
3417   rtx x = *px = protect_from_queue (*px, 0);
3418   rtx y = *py = protect_from_queue (*py, 0);
3419   enum machine_mode mode = GET_MODE (x);
3420   rtx libfunc = 0;
3421   rtx result;
3422
3423   if (mode == HFmode)
3424     switch (comparison)
3425       {
3426       case EQ:
3427         libfunc = eqhf2_libfunc;
3428         break;
3429
3430       case NE:
3431         libfunc = nehf2_libfunc;
3432         break;
3433
3434       case GT:
3435         libfunc = gthf2_libfunc;
3436         break;
3437
3438       case GE:
3439         libfunc = gehf2_libfunc;
3440         break;
3441
3442       case LT:
3443         libfunc = lthf2_libfunc;
3444         break;
3445
3446       case LE:
3447         libfunc = lehf2_libfunc;
3448         break;
3449
3450       case UNORDERED:
3451         libfunc = unordhf2_libfunc;
3452         break;
3453
3454       default:
3455         break;
3456       }
3457   else if (mode == SFmode)
3458     switch (comparison)
3459       {
3460       case EQ:
3461         libfunc = eqsf2_libfunc;
3462         break;
3463
3464       case NE:
3465         libfunc = nesf2_libfunc;
3466         break;
3467
3468       case GT:
3469         libfunc = gtsf2_libfunc;
3470         break;
3471
3472       case GE:
3473         libfunc = gesf2_libfunc;
3474         break;
3475
3476       case LT:
3477         libfunc = ltsf2_libfunc;
3478         break;
3479
3480       case LE:
3481         libfunc = lesf2_libfunc;
3482         break;
3483
3484       case UNORDERED:
3485         libfunc = unordsf2_libfunc;
3486         break;
3487
3488       default:
3489         break;
3490       }
3491   else if (mode == DFmode)
3492     switch (comparison)
3493       {
3494       case EQ:
3495         libfunc = eqdf2_libfunc;
3496         break;
3497
3498       case NE:
3499         libfunc = nedf2_libfunc;
3500         break;
3501
3502       case GT:
3503         libfunc = gtdf2_libfunc;
3504         break;
3505
3506       case GE:
3507         libfunc = gedf2_libfunc;
3508         break;
3509
3510       case LT:
3511         libfunc = ltdf2_libfunc;
3512         break;
3513
3514       case LE:
3515         libfunc = ledf2_libfunc;
3516         break;
3517
3518       case UNORDERED:
3519         libfunc = unorddf2_libfunc;
3520         break;
3521
3522       default:
3523         break;
3524       }
3525   else if (mode == XFmode)
3526     switch (comparison)
3527       {
3528       case EQ:
3529         libfunc = eqxf2_libfunc;
3530         break;
3531
3532       case NE:
3533         libfunc = nexf2_libfunc;
3534         break;
3535
3536       case GT:
3537         libfunc = gtxf2_libfunc;
3538         break;
3539
3540       case GE:
3541         libfunc = gexf2_libfunc;
3542         break;
3543
3544       case LT:
3545         libfunc = ltxf2_libfunc;
3546         break;
3547
3548       case LE:
3549         libfunc = lexf2_libfunc;
3550         break;
3551
3552       case UNORDERED:
3553         libfunc = unordxf2_libfunc;
3554         break;
3555
3556       default:
3557         break;
3558       }
3559   else if (mode == TFmode)
3560     switch (comparison)
3561       {
3562       case EQ:
3563         libfunc = eqtf2_libfunc;
3564         break;
3565
3566       case NE:
3567         libfunc = netf2_libfunc;
3568         break;
3569
3570       case GT:
3571         libfunc = gttf2_libfunc;
3572         break;
3573
3574       case GE:
3575         libfunc = getf2_libfunc;
3576         break;
3577
3578       case LT:
3579         libfunc = lttf2_libfunc;
3580         break;
3581
3582       case LE:
3583         libfunc = letf2_libfunc;
3584         break;
3585
3586       case UNORDERED:
3587         libfunc = unordtf2_libfunc;
3588         break;
3589
3590       default:
3591         break;
3592       }
3593   else
3594     {
3595       enum machine_mode wider_mode;
3596
3597       for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
3598            wider_mode = GET_MODE_WIDER_MODE (wider_mode))
3599         {
3600           if ((cmp_optab->handlers[(int) wider_mode].insn_code
3601                != CODE_FOR_nothing)
3602               || (cmp_optab->handlers[(int) wider_mode].libfunc != 0))
3603             {
3604               x = protect_from_queue (x, 0);
3605               y = protect_from_queue (y, 0);
3606               *px = convert_to_mode (wider_mode, x, 0);
3607               *py = convert_to_mode (wider_mode, y, 0);
3608               prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp);
3609               return;
3610             }
3611         }
3612       abort ();
3613     }
3614
3615   if (libfunc == 0)
3616     abort ();
3617
3618   emit_library_call (libfunc, LCT_CONST_MAKE_BLOCK, word_mode, 2, x, mode, y,
3619                      mode);
3620
3621   /* Immediately move the result of the libcall into a pseudo
3622      register so reload doesn't clobber the value if it needs
3623      the return register for a spill reg.  */
3624   result = gen_reg_rtx (word_mode);
3625   emit_move_insn (result, hard_libcall_value (word_mode));
3626   *px = result;
3627   *py = const0_rtx;
3628   *pmode = word_mode;
3629   if (comparison == UNORDERED)
3630     *pcomparison = NE;
3631 #ifdef FLOAT_LIB_COMPARE_RETURNS_BOOL
3632   else if (FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, comparison))
3633     *pcomparison = NE;
3634 #endif
3635   *punsignedp = 0;
3636 }
3637 \f
3638 /* Generate code to indirectly jump to a location given in the rtx LOC.  */
3639
3640 void
3641 emit_indirect_jump (loc)
3642      rtx loc;
3643 {
3644   if (! ((*insn_data[(int)CODE_FOR_indirect_jump].operand[0].predicate)
3645          (loc, Pmode)))
3646     loc = copy_to_mode_reg (Pmode, loc);
3647
3648   emit_jump_insn (gen_indirect_jump (loc));
3649   emit_barrier ();
3650 }
3651 \f
3652 #ifdef HAVE_conditional_move
3653
3654 /* Emit a conditional move instruction if the machine supports one for that
3655    condition and machine mode.
3656
3657    OP0 and OP1 are the operands that should be compared using CODE.  CMODE is
3658    the mode to use should they be constants.  If it is VOIDmode, they cannot
3659    both be constants.
3660
3661    OP2 should be stored in TARGET if the comparison is true, otherwise OP3
3662    should be stored there.  MODE is the mode to use should they be constants.
3663    If it is VOIDmode, they cannot both be constants.
3664
3665    The result is either TARGET (perhaps modified) or NULL_RTX if the operation
3666    is not supported.  */
3667
3668 rtx
3669 emit_conditional_move (target, code, op0, op1, cmode, op2, op3, mode,
3670                        unsignedp)
3671      rtx target;
3672      enum rtx_code code;
3673      rtx op0, op1;
3674      enum machine_mode cmode;
3675      rtx op2, op3;
3676      enum machine_mode mode;
3677      int unsignedp;
3678 {
3679   rtx tem, subtarget, comparison, insn;
3680   enum insn_code icode;
3681   enum rtx_code reversed;
3682
3683   /* If one operand is constant, make it the second one.  Only do this
3684      if the other operand is not constant as well.  */
3685
3686   if (swap_commutative_operands_p (op0, op1))
3687     {
3688       tem = op0;
3689       op0 = op1;
3690       op1 = tem;
3691       code = swap_condition (code);
3692     }
3693
3694   /* get_condition will prefer to generate LT and GT even if the old
3695      comparison was against zero, so undo that canonicalization here since
3696      comparisons against zero are cheaper.  */
3697   if (code == LT && GET_CODE (op1) == CONST_INT && INTVAL (op1) == 1)
3698     code = LE, op1 = const0_rtx;
3699   else if (code == GT && GET_CODE (op1) == CONST_INT && INTVAL (op1) == -1)
3700     code = GE, op1 = const0_rtx;
3701
3702   if (cmode == VOIDmode)
3703     cmode = GET_MODE (op0);
3704
3705   if (swap_commutative_operands_p (op2, op3)
3706       && ((reversed = reversed_comparison_code_parts (code, op0, op1, NULL))
3707           != UNKNOWN))
3708     {
3709       tem = op2;
3710       op2 = op3;
3711       op3 = tem;
3712       code = reversed;
3713     }
3714
3715   if (mode == VOIDmode)
3716     mode = GET_MODE (op2);
3717
3718   icode = movcc_gen_code[mode];
3719
3720   if (icode == CODE_FOR_nothing)
3721     return 0;
3722
3723   if (flag_force_mem)
3724     {
3725       op2 = force_not_mem (op2);
3726       op3 = force_not_mem (op3);
3727     }
3728
3729   if (target)
3730     target = protect_from_queue (target, 1);
3731   else
3732     target = gen_reg_rtx (mode);
3733
3734   subtarget = target;
3735
3736   emit_queue ();
3737
3738   op2 = protect_from_queue (op2, 0);
3739   op3 = protect_from_queue (op3, 0);
3740
3741   /* If the insn doesn't accept these operands, put them in pseudos.  */
3742
3743   if (! (*insn_data[icode].operand[0].predicate)
3744       (subtarget, insn_data[icode].operand[0].mode))
3745     subtarget = gen_reg_rtx (insn_data[icode].operand[0].mode);
3746
3747   if (! (*insn_data[icode].operand[2].predicate)
3748       (op2, insn_data[icode].operand[2].mode))
3749     op2 = copy_to_mode_reg (insn_data[icode].operand[2].mode, op2);
3750
3751   if (! (*insn_data[icode].operand[3].predicate)
3752       (op3, insn_data[icode].operand[3].mode))
3753     op3 = copy_to_mode_reg (insn_data[icode].operand[3].mode, op3);
3754
3755   /* Everything should now be in the suitable form, so emit the compare insn
3756      and then the conditional move.  */
3757
3758   comparison 
3759     = compare_from_rtx (op0, op1, code, unsignedp, cmode, NULL_RTX);
3760
3761   /* ??? Watch for const0_rtx (nop) and const_true_rtx (unconditional)?  */
3762   /* We can get const0_rtx or const_true_rtx in some circumstances.  Just
3763      return NULL and let the caller figure out how best to deal with this
3764      situation.  */
3765   if (GET_CODE (comparison) != code)
3766     return NULL_RTX;
3767   
3768   insn = GEN_FCN (icode) (subtarget, comparison, op2, op3);
3769
3770   /* If that failed, then give up.  */
3771   if (insn == 0)
3772     return 0;
3773
3774   emit_insn (insn);
3775
3776   if (subtarget != target)
3777     convert_move (target, subtarget, 0);
3778
3779   return target;
3780 }
3781
3782 /* Return non-zero if a conditional move of mode MODE is supported.
3783
3784    This function is for combine so it can tell whether an insn that looks
3785    like a conditional move is actually supported by the hardware.  If we
3786    guess wrong we lose a bit on optimization, but that's it.  */
3787 /* ??? sparc64 supports conditionally moving integers values based on fp
3788    comparisons, and vice versa.  How do we handle them?  */
3789
3790 int
3791 can_conditionally_move_p (mode)
3792      enum machine_mode mode;
3793 {
3794   if (movcc_gen_code[mode] != CODE_FOR_nothing)
3795     return 1;
3796
3797   return 0;
3798 }
3799
3800 #endif /* HAVE_conditional_move */
3801 \f
3802 /* These functions generate an insn body and return it
3803    rather than emitting the insn.
3804
3805    They do not protect from queued increments,
3806    because they may be used 1) in protect_from_queue itself
3807    and 2) in other passes where there is no queue.  */
3808
3809 /* Generate and return an insn body to add Y to X.  */
3810
3811 rtx
3812 gen_add2_insn (x, y)
3813      rtx x, y;
3814 {
3815   int icode = (int) add_optab->handlers[(int) GET_MODE (x)].insn_code; 
3816
3817   if (! ((*insn_data[icode].operand[0].predicate)
3818          (x, insn_data[icode].operand[0].mode))
3819       || ! ((*insn_data[icode].operand[1].predicate)
3820             (x, insn_data[icode].operand[1].mode))
3821       || ! ((*insn_data[icode].operand[2].predicate)
3822             (y, insn_data[icode].operand[2].mode)))
3823     abort ();
3824
3825   return (GEN_FCN (icode) (x, x, y));
3826 }
3827
3828 /* Generate and return an insn body to add r1 and c,
3829    storing the result in r0.  */
3830 rtx
3831 gen_add3_insn (r0, r1, c)
3832      rtx r0, r1, c;
3833 {
3834   int icode = (int) add_optab->handlers[(int) GET_MODE (r0)].insn_code;
3835
3836     if (icode == CODE_FOR_nothing
3837       || ! ((*insn_data[icode].operand[0].predicate)
3838             (r0, insn_data[icode].operand[0].mode))
3839       || ! ((*insn_data[icode].operand[1].predicate)
3840             (r1, insn_data[icode].operand[1].mode))
3841       || ! ((*insn_data[icode].operand[2].predicate)
3842             (c, insn_data[icode].operand[2].mode)))
3843     return NULL_RTX;
3844
3845   return (GEN_FCN (icode) (r0, r1, c));
3846 }
3847
3848 int
3849 have_add2_insn (x, y)
3850      rtx x, y;
3851 {
3852   int icode;
3853
3854   if (GET_MODE (x) == VOIDmode)
3855     abort ();
3856
3857   icode = (int) add_optab->handlers[(int) GET_MODE (x)].insn_code; 
3858
3859   if (icode == CODE_FOR_nothing)
3860     return 0;
3861
3862   if (! ((*insn_data[icode].operand[0].predicate)
3863          (x, insn_data[icode].operand[0].mode))
3864       || ! ((*insn_data[icode].operand[1].predicate)
3865             (x, insn_data[icode].operand[1].mode))
3866       || ! ((*insn_data[icode].operand[2].predicate)
3867             (y, insn_data[icode].operand[2].mode)))
3868     return 0;
3869
3870   return 1;
3871 }
3872
3873 /* Generate and return an insn body to subtract Y from X.  */
3874
3875 rtx
3876 gen_sub2_insn (x, y)
3877      rtx x, y;
3878 {
3879   int icode = (int) sub_optab->handlers[(int) GET_MODE (x)].insn_code; 
3880
3881   if (! ((*insn_data[icode].operand[0].predicate)
3882          (x, insn_data[icode].operand[0].mode))
3883       || ! ((*insn_data[icode].operand[1].predicate)
3884             (x, insn_data[icode].operand[1].mode))
3885       || ! ((*insn_data[icode].operand[2].predicate)
3886             (y, insn_data[icode].operand[2].mode)))
3887     abort ();
3888
3889   return (GEN_FCN (icode) (x, x, y));
3890 }
3891
3892 /* Generate and return an insn body to subtract r1 and c,
3893    storing the result in r0.  */
3894 rtx
3895 gen_sub3_insn (r0, r1, c)
3896      rtx r0, r1, c;
3897 {
3898   int icode = (int) sub_optab->handlers[(int) GET_MODE (r0)].insn_code;
3899
3900     if (icode == CODE_FOR_nothing
3901       || ! ((*insn_data[icode].operand[0].predicate)
3902             (r0, insn_data[icode].operand[0].mode))
3903       || ! ((*insn_data[icode].operand[1].predicate)
3904             (r1, insn_data[icode].operand[1].mode))
3905       || ! ((*insn_data[icode].operand[2].predicate)
3906             (c, insn_data[icode].operand[2].mode)))
3907     return NULL_RTX;
3908
3909   return (GEN_FCN (icode) (r0, r1, c));
3910 }
3911
3912 int
3913 have_sub2_insn (x, y)
3914      rtx x, y;
3915 {
3916   int icode;
3917
3918   if (GET_MODE (x) == VOIDmode)
3919     abort ();
3920
3921   icode = (int) sub_optab->handlers[(int) GET_MODE (x)].insn_code; 
3922
3923   if (icode == CODE_FOR_nothing)
3924     return 0;
3925
3926   if (! ((*insn_data[icode].operand[0].predicate)
3927          (x, insn_data[icode].operand[0].mode))
3928       || ! ((*insn_data[icode].operand[1].predicate)
3929             (x, insn_data[icode].operand[1].mode))
3930       || ! ((*insn_data[icode].operand[2].predicate)
3931             (y, insn_data[icode].operand[2].mode)))
3932     return 0;
3933
3934   return 1;
3935 }
3936
3937 /* Generate the body of an instruction to copy Y into X.
3938    It may be a SEQUENCE, if one insn isn't enough.  */
3939
3940 rtx
3941 gen_move_insn (x, y)
3942      rtx x, y;
3943 {
3944   enum machine_mode mode = GET_MODE (x);
3945   enum insn_code insn_code;
3946   rtx seq;
3947
3948   if (mode == VOIDmode)
3949     mode = GET_MODE (y); 
3950
3951   insn_code = mov_optab->handlers[(int) mode].insn_code;
3952
3953   /* Handle MODE_CC modes:  If we don't have a special move insn for this mode,
3954      find a mode to do it in.  If we have a movcc, use it.  Otherwise,
3955      find the MODE_INT mode of the same width.  */
3956
3957   if (GET_MODE_CLASS (mode) == MODE_CC && insn_code == CODE_FOR_nothing)
3958     {
3959       enum machine_mode tmode = VOIDmode;
3960       rtx x1 = x, y1 = y;
3961
3962       if (mode != CCmode
3963           && mov_optab->handlers[(int) CCmode].insn_code != CODE_FOR_nothing)
3964         tmode = CCmode;
3965       else
3966         for (tmode = QImode; tmode != VOIDmode;
3967              tmode = GET_MODE_WIDER_MODE (tmode))
3968           if (GET_MODE_SIZE (tmode) == GET_MODE_SIZE (mode))
3969             break;
3970
3971       if (tmode == VOIDmode)
3972         abort ();
3973
3974       /* Get X and Y in TMODE.  We can't use gen_lowpart here because it
3975          may call change_address which is not appropriate if we were
3976          called when a reload was in progress.  We don't have to worry
3977          about changing the address since the size in bytes is supposed to
3978          be the same.  Copy the MEM to change the mode and move any
3979          substitutions from the old MEM to the new one.  */
3980
3981       if (reload_in_progress)
3982         {
3983           x = gen_lowpart_common (tmode, x1);
3984           if (x == 0 && GET_CODE (x1) == MEM)
3985             {
3986               x = adjust_address_nv (x1, tmode, 0);
3987               copy_replacements (x1, x);
3988             }
3989
3990           y = gen_lowpart_common (tmode, y1);
3991           if (y == 0 && GET_CODE (y1) == MEM)
3992             {
3993               y = adjust_address_nv (y1, tmode, 0);
3994               copy_replacements (y1, y);
3995             }
3996         }
3997       else
3998         {
3999           x = gen_lowpart (tmode, x);
4000           y = gen_lowpart (tmode, y);
4001         }
4002           
4003       insn_code = mov_optab->handlers[(int) tmode].insn_code;
4004       return (GEN_FCN (insn_code) (x, y));
4005     }
4006
4007   start_sequence ();
4008   emit_move_insn_1 (x, y);
4009   seq = gen_sequence ();
4010   end_sequence ();
4011   return seq;
4012 }
4013 \f
4014 /* Return the insn code used to extend FROM_MODE to TO_MODE.
4015    UNSIGNEDP specifies zero-extension instead of sign-extension.  If
4016    no such operation exists, CODE_FOR_nothing will be returned.  */
4017
4018 enum insn_code
4019 can_extend_p (to_mode, from_mode, unsignedp)
4020      enum machine_mode to_mode, from_mode;
4021      int unsignedp;
4022 {
4023 #ifdef HAVE_ptr_extend
4024   if (unsignedp < 0)
4025     return CODE_FOR_ptr_extend;
4026   else
4027 #endif
4028     return extendtab[(int) to_mode][(int) from_mode][unsignedp != 0];
4029 }
4030
4031 /* Generate the body of an insn to extend Y (with mode MFROM)
4032    into X (with mode MTO).  Do zero-extension if UNSIGNEDP is nonzero.  */
4033
4034 rtx
4035 gen_extend_insn (x, y, mto, mfrom, unsignedp)
4036      rtx x, y;
4037      enum machine_mode mto, mfrom;
4038      int unsignedp;
4039 {
4040   return (GEN_FCN (extendtab[(int) mto][(int) mfrom][unsignedp != 0]) (x, y));
4041 }
4042 \f
4043 /* can_fix_p and can_float_p say whether the target machine
4044    can directly convert a given fixed point type to
4045    a given floating point type, or vice versa.
4046    The returned value is the CODE_FOR_... value to use,
4047    or CODE_FOR_nothing if these modes cannot be directly converted.
4048
4049    *TRUNCP_PTR is set to 1 if it is necessary to output
4050    an explicit FTRUNC insn before the fix insn; otherwise 0.  */
4051
4052 static enum insn_code
4053 can_fix_p (fixmode, fltmode, unsignedp, truncp_ptr)
4054      enum machine_mode fltmode, fixmode;
4055      int unsignedp;
4056      int *truncp_ptr;
4057 {
4058   *truncp_ptr = 0;
4059   if (fixtrunctab[(int) fltmode][(int) fixmode][unsignedp != 0]
4060       != CODE_FOR_nothing)
4061     return fixtrunctab[(int) fltmode][(int) fixmode][unsignedp != 0];
4062
4063   if (ftrunc_optab->handlers[(int) fltmode].insn_code != CODE_FOR_nothing)
4064     {
4065       *truncp_ptr = 1;
4066       return fixtab[(int) fltmode][(int) fixmode][unsignedp != 0];
4067     }
4068   return CODE_FOR_nothing;
4069 }
4070
4071 static enum insn_code
4072 can_float_p (fltmode, fixmode, unsignedp)
4073      enum machine_mode fixmode, fltmode;
4074      int unsignedp;
4075 {
4076   return floattab[(int) fltmode][(int) fixmode][unsignedp != 0];
4077 }
4078 \f
4079 /* Generate code to convert FROM to floating point
4080    and store in TO.  FROM must be fixed point and not VOIDmode.
4081    UNSIGNEDP nonzero means regard FROM as unsigned.
4082    Normally this is done by correcting the final value
4083    if it is negative.  */
4084
4085 void
4086 expand_float (to, from, unsignedp)
4087      rtx to, from;
4088      int unsignedp;
4089 {
4090   enum insn_code icode;
4091   rtx target = to;
4092   enum machine_mode fmode, imode;
4093
4094   /* Crash now, because we won't be able to decide which mode to use.  */
4095   if (GET_MODE (from) == VOIDmode)
4096     abort ();
4097
4098   /* Look for an insn to do the conversion.  Do it in the specified
4099      modes if possible; otherwise convert either input, output or both to
4100      wider mode.  If the integer mode is wider than the mode of FROM,
4101      we can do the conversion signed even if the input is unsigned.  */
4102
4103   for (imode = GET_MODE (from); imode != VOIDmode;
4104        imode = GET_MODE_WIDER_MODE (imode))
4105     for (fmode = GET_MODE (to); fmode != VOIDmode;
4106          fmode = GET_MODE_WIDER_MODE (fmode))
4107       {
4108         int doing_unsigned = unsignedp;
4109
4110         if (fmode != GET_MODE (to)
4111             && significand_size (fmode) < GET_MODE_BITSIZE (GET_MODE (from)))
4112           continue;
4113
4114         icode = can_float_p (fmode, imode, unsignedp);
4115         if (icode == CODE_FOR_nothing && imode != GET_MODE (from) && unsignedp)
4116           icode = can_float_p (fmode, imode, 0), doing_unsigned = 0;
4117
4118         if (icode != CODE_FOR_nothing)
4119           {
4120             to = protect_from_queue (to, 1);
4121             from = protect_from_queue (from, 0);
4122
4123             if (imode != GET_MODE (from))
4124               from = convert_to_mode (imode, from, unsignedp);
4125
4126             if (fmode != GET_MODE (to))
4127               target = gen_reg_rtx (fmode);
4128
4129             emit_unop_insn (icode, target, from,
4130                             doing_unsigned ? UNSIGNED_FLOAT : FLOAT);
4131
4132             if (target != to)
4133               convert_move (to, target, 0);
4134             return;
4135           }
4136     }
4137
4138 #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
4139
4140   /* Unsigned integer, and no way to convert directly.
4141      Convert as signed, then conditionally adjust the result.  */
4142   if (unsignedp)
4143     {
4144       rtx label = gen_label_rtx ();
4145       rtx temp;
4146       REAL_VALUE_TYPE offset;
4147
4148       emit_queue ();
4149
4150       to = protect_from_queue (to, 1);
4151       from = protect_from_queue (from, 0);
4152
4153       if (flag_force_mem)
4154         from = force_not_mem (from);
4155
4156       /* Look for a usable floating mode FMODE wider than the source and at
4157          least as wide as the target.  Using FMODE will avoid rounding woes
4158          with unsigned values greater than the signed maximum value.  */
4159
4160       for (fmode = GET_MODE (to);  fmode != VOIDmode;
4161            fmode = GET_MODE_WIDER_MODE (fmode))
4162         if (GET_MODE_BITSIZE (GET_MODE (from)) < GET_MODE_BITSIZE (fmode)
4163             && can_float_p (fmode, GET_MODE (from), 0) != CODE_FOR_nothing)
4164           break;
4165
4166       if (fmode == VOIDmode)
4167         {
4168           /* There is no such mode.  Pretend the target is wide enough.  */
4169           fmode = GET_MODE (to);
4170
4171           /* Avoid double-rounding when TO is narrower than FROM.  */
4172           if ((significand_size (fmode) + 1)
4173               < GET_MODE_BITSIZE (GET_MODE (from)))
4174             {
4175               rtx temp1;
4176               rtx neglabel = gen_label_rtx ();
4177
4178               /* Don't use TARGET if it isn't a register, is a hard register, 
4179                  or is the wrong mode.  */
4180               if (GET_CODE (target) != REG
4181                   || REGNO (target) < FIRST_PSEUDO_REGISTER
4182                   || GET_MODE (target) != fmode)
4183                 target = gen_reg_rtx (fmode);
4184
4185               imode = GET_MODE (from);
4186               do_pending_stack_adjust ();
4187
4188               /* Test whether the sign bit is set.  */
4189               emit_cmp_and_jump_insns (from, const0_rtx, LT, NULL_RTX, imode,
4190                                        0, neglabel);
4191
4192               /* The sign bit is not set.  Convert as signed.  */
4193               expand_float (target, from, 0);
4194               emit_jump_insn (gen_jump (label));
4195               emit_barrier ();
4196
4197               /* The sign bit is set.
4198                  Convert to a usable (positive signed) value by shifting right
4199                  one bit, while remembering if a nonzero bit was shifted
4200                  out; i.e., compute  (from & 1) | (from >> 1).  */
4201
4202               emit_label (neglabel);
4203               temp = expand_binop (imode, and_optab, from, const1_rtx,
4204                                    NULL_RTX, 1, OPTAB_LIB_WIDEN);
4205               temp1 = expand_shift (RSHIFT_EXPR, imode, from, integer_one_node,
4206                                     NULL_RTX, 1);
4207               temp = expand_binop (imode, ior_optab, temp, temp1, temp, 1, 
4208                                    OPTAB_LIB_WIDEN);
4209               expand_float (target, temp, 0);
4210
4211               /* Multiply by 2 to undo the shift above.  */
4212               temp = expand_binop (fmode, add_optab, target, target,
4213                                      target, 0, OPTAB_LIB_WIDEN);
4214               if (temp != target)
4215                 emit_move_insn (target, temp);
4216
4217               do_pending_stack_adjust ();
4218               emit_label (label);
4219               goto done;
4220             }
4221         }
4222
4223       /* If we are about to do some arithmetic to correct for an
4224          unsigned operand, do it in a pseudo-register.  */
4225
4226       if (GET_MODE (to) != fmode
4227           || GET_CODE (to) != REG || REGNO (to) < FIRST_PSEUDO_REGISTER)
4228         target = gen_reg_rtx (fmode);
4229
4230       /* Convert as signed integer to floating.  */
4231       expand_float (target, from, 0);
4232
4233       /* If FROM is negative (and therefore TO is negative),
4234          correct its value by 2**bitwidth.  */
4235
4236       do_pending_stack_adjust ();
4237       emit_cmp_and_jump_insns (from, const0_rtx, GE, NULL_RTX, GET_MODE (from),
4238                                0, label);
4239
4240       /* On SCO 3.2.1, ldexp rejects values outside [0.5, 1).
4241          Rather than setting up a dconst_dot_5, let's hope SCO
4242          fixes the bug.  */
4243       offset = REAL_VALUE_LDEXP (dconst1, GET_MODE_BITSIZE (GET_MODE (from)));
4244       temp = expand_binop (fmode, add_optab, target,
4245                            CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode),
4246                            target, 0, OPTAB_LIB_WIDEN);
4247       if (temp != target)
4248         emit_move_insn (target, temp);
4249
4250       do_pending_stack_adjust ();
4251       emit_label (label);
4252       goto done;
4253     }
4254 #endif
4255
4256   /* No hardware instruction available; call a library routine to convert from
4257      SImode, DImode, or TImode into SFmode, DFmode, XFmode, or TFmode.  */
4258     {
4259       rtx libfcn;
4260       rtx insns;
4261       rtx value;
4262
4263       to = protect_from_queue (to, 1);
4264       from = protect_from_queue (from, 0);
4265
4266       if (GET_MODE_SIZE (GET_MODE (from)) < GET_MODE_SIZE (SImode))
4267         from = convert_to_mode (SImode, from, unsignedp);
4268
4269       if (flag_force_mem)
4270         from = force_not_mem (from);
4271
4272       if (GET_MODE (to) == SFmode)
4273         {
4274           if (GET_MODE (from) == SImode)
4275             libfcn = floatsisf_libfunc;
4276           else if (GET_MODE (from) == DImode)
4277             libfcn = floatdisf_libfunc;
4278           else if (GET_MODE (from) == TImode)
4279             libfcn = floattisf_libfunc;
4280           else
4281             abort ();
4282         }
4283       else if (GET_MODE (to) == DFmode)
4284         {
4285           if (GET_MODE (from) == SImode)
4286             libfcn = floatsidf_libfunc;
4287           else if (GET_MODE (from) == DImode)
4288             libfcn = floatdidf_libfunc;
4289           else if (GET_MODE (from) == TImode)
4290             libfcn = floattidf_libfunc;
4291           else
4292             abort ();
4293         }
4294       else if (GET_MODE (to) == XFmode)
4295         {
4296           if (GET_MODE (from) == SImode)
4297             libfcn = floatsixf_libfunc;
4298           else if (GET_MODE (from) == DImode)
4299             libfcn = floatdixf_libfunc;
4300           else if (GET_MODE (from) == TImode)
4301             libfcn = floattixf_libfunc;
4302           else
4303             abort ();
4304         }
4305       else if (GET_MODE (to) == TFmode)
4306         {
4307           if (GET_MODE (from) == SImode)
4308             libfcn = floatsitf_libfunc;
4309           else if (GET_MODE (from) == DImode)
4310             libfcn = floatditf_libfunc;
4311           else if (GET_MODE (from) == TImode)
4312             libfcn = floattitf_libfunc;
4313           else
4314             abort ();
4315         }
4316       else
4317         abort ();
4318
4319       start_sequence ();
4320
4321       value = emit_library_call_value (libfcn, NULL_RTX, LCT_CONST,
4322                                        GET_MODE (to), 1, from,
4323                                        GET_MODE (from));
4324       insns = get_insns ();
4325       end_sequence ();
4326
4327       emit_libcall_block (insns, target, value,
4328                           gen_rtx_FLOAT (GET_MODE (to), from));
4329     }
4330
4331  done:
4332
4333   /* Copy result to requested destination
4334      if we have been computing in a temp location.  */
4335
4336   if (target != to)
4337     {
4338       if (GET_MODE (target) == GET_MODE (to))
4339         emit_move_insn (to, target);
4340       else
4341         convert_move (to, target, 0);
4342     }
4343 }
4344 \f
4345 /* expand_fix: generate code to convert FROM to fixed point
4346    and store in TO.  FROM must be floating point.  */
4347
4348 static rtx
4349 ftruncify (x)
4350      rtx x;
4351 {
4352   rtx temp = gen_reg_rtx (GET_MODE (x));
4353   return expand_unop (GET_MODE (x), ftrunc_optab, x, temp, 0);
4354 }
4355
4356 void
4357 expand_fix (to, from, unsignedp)
4358      rtx to, from;
4359      int unsignedp;
4360 {
4361   enum insn_code icode;
4362   rtx target = to;
4363   enum machine_mode fmode, imode;
4364   int must_trunc = 0;
4365   rtx libfcn = 0;
4366
4367   /* We first try to find a pair of modes, one real and one integer, at
4368      least as wide as FROM and TO, respectively, in which we can open-code
4369      this conversion.  If the integer mode is wider than the mode of TO,
4370      we can do the conversion either signed or unsigned.  */
4371
4372   for (fmode = GET_MODE (from); fmode != VOIDmode;
4373        fmode = GET_MODE_WIDER_MODE (fmode))
4374     for (imode = GET_MODE (to); imode != VOIDmode;
4375          imode = GET_MODE_WIDER_MODE (imode))
4376       {
4377         int doing_unsigned = unsignedp;
4378
4379         icode = can_fix_p (imode, fmode, unsignedp, &must_trunc);
4380         if (icode == CODE_FOR_nothing && imode != GET_MODE (to) && unsignedp)
4381           icode = can_fix_p (imode, fmode, 0, &must_trunc), doing_unsigned = 0;
4382
4383         if (icode != CODE_FOR_nothing)
4384           {
4385             to = protect_from_queue (to, 1);
4386             from = protect_from_queue (from, 0);
4387
4388             if (fmode != GET_MODE (from))
4389               from = convert_to_mode (fmode, from, 0);
4390
4391             if (must_trunc)
4392               from = ftruncify (from);
4393
4394             if (imode != GET_MODE (to))
4395               target = gen_reg_rtx (imode);
4396
4397             emit_unop_insn (icode, target, from,
4398                             doing_unsigned ? UNSIGNED_FIX : FIX);
4399             if (target != to)
4400               convert_move (to, target, unsignedp);
4401             return;
4402           }
4403       }
4404
4405 #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
4406   /* For an unsigned conversion, there is one more way to do it.
4407      If we have a signed conversion, we generate code that compares
4408      the real value to the largest representable positive number.  If if
4409      is smaller, the conversion is done normally.  Otherwise, subtract
4410      one plus the highest signed number, convert, and add it back.
4411
4412      We only need to check all real modes, since we know we didn't find
4413      anything with a wider integer mode.  */
4414
4415   if (unsignedp && GET_MODE_BITSIZE (GET_MODE (to)) <= HOST_BITS_PER_WIDE_INT)
4416     for (fmode = GET_MODE (from); fmode != VOIDmode;
4417          fmode = GET_MODE_WIDER_MODE (fmode))
4418       /* Make sure we won't lose significant bits doing this.  */
4419       if (GET_MODE_BITSIZE (fmode) > GET_MODE_BITSIZE (GET_MODE (to))
4420           && CODE_FOR_nothing != can_fix_p (GET_MODE (to), fmode, 0,
4421                                             &must_trunc))
4422         {
4423           int bitsize;
4424           REAL_VALUE_TYPE offset;
4425           rtx limit, lab1, lab2, insn;
4426
4427           bitsize = GET_MODE_BITSIZE (GET_MODE (to));
4428           offset = REAL_VALUE_LDEXP (dconst1, bitsize - 1);
4429           limit = CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode);
4430           lab1 = gen_label_rtx ();
4431           lab2 = gen_label_rtx ();
4432
4433           emit_queue ();
4434           to = protect_from_queue (to, 1);
4435           from = protect_from_queue (from, 0);
4436
4437           if (flag_force_mem)
4438             from = force_not_mem (from);
4439
4440           if (fmode != GET_MODE (from))
4441             from = convert_to_mode (fmode, from, 0);
4442
4443           /* See if we need to do the subtraction.  */
4444           do_pending_stack_adjust ();
4445           emit_cmp_and_jump_insns (from, limit, GE, NULL_RTX, GET_MODE (from),
4446                                    0, lab1);
4447
4448           /* If not, do the signed "fix" and branch around fixup code.  */
4449           expand_fix (to, from, 0);
4450           emit_jump_insn (gen_jump (lab2));
4451           emit_barrier ();
4452
4453           /* Otherwise, subtract 2**(N-1), convert to signed number,
4454              then add 2**(N-1).  Do the addition using XOR since this
4455              will often generate better code.  */
4456           emit_label (lab1);
4457           target = expand_binop (GET_MODE (from), sub_optab, from, limit,
4458                                  NULL_RTX, 0, OPTAB_LIB_WIDEN);
4459           expand_fix (to, target, 0);
4460           target = expand_binop (GET_MODE (to), xor_optab, to,
4461                                  GEN_INT (trunc_int_for_mode
4462                                           ((HOST_WIDE_INT) 1 << (bitsize - 1),
4463                                            GET_MODE (to))),
4464                                  to, 1, OPTAB_LIB_WIDEN);
4465
4466           if (target != to)
4467             emit_move_insn (to, target);
4468
4469           emit_label (lab2);
4470
4471           if (mov_optab->handlers[(int) GET_MODE (to)].insn_code
4472               != CODE_FOR_nothing)
4473             {
4474               /* Make a place for a REG_NOTE and add it.  */
4475               insn = emit_move_insn (to, to);
4476               set_unique_reg_note (insn,
4477                                    REG_EQUAL,
4478                                    gen_rtx_fmt_e (UNSIGNED_FIX,
4479                                                   GET_MODE (to),
4480                                                   copy_rtx (from)));
4481             }
4482
4483           return;
4484         }
4485 #endif
4486
4487   /* We can't do it with an insn, so use a library call.  But first ensure
4488      that the mode of TO is at least as wide as SImode, since those are the
4489      only library calls we know about.  */
4490
4491   if (GET_MODE_SIZE (GET_MODE (to)) < GET_MODE_SIZE (SImode))
4492     {
4493       target = gen_reg_rtx (SImode);
4494
4495       expand_fix (target, from, unsignedp);
4496     }
4497   else if (GET_MODE (from) == SFmode)
4498     {
4499       if (GET_MODE (to) == SImode)
4500         libfcn = unsignedp ? fixunssfsi_libfunc : fixsfsi_libfunc;
4501       else if (GET_MODE (to) == DImode)
4502         libfcn = unsignedp ? fixunssfdi_libfunc : fixsfdi_libfunc;
4503       else if (GET_MODE (to) == TImode)
4504         libfcn = unsignedp ? fixunssfti_libfunc : fixsfti_libfunc;
4505       else
4506         abort ();
4507     }
4508   else if (GET_MODE (from) == DFmode)
4509     {
4510       if (GET_MODE (to) == SImode)
4511         libfcn = unsignedp ? fixunsdfsi_libfunc : fixdfsi_libfunc;
4512       else if (GET_MODE (to) == DImode)
4513         libfcn = unsignedp ? fixunsdfdi_libfunc : fixdfdi_libfunc;
4514       else if (GET_MODE (to) == TImode)
4515         libfcn = unsignedp ? fixunsdfti_libfunc : fixdfti_libfunc;
4516       else
4517         abort ();
4518     }
4519   else if (GET_MODE (from) == XFmode)
4520     {
4521       if (GET_MODE (to) == SImode)
4522         libfcn = unsignedp ? fixunsxfsi_libfunc : fixxfsi_libfunc;
4523       else if (GET_MODE (to) == DImode)
4524         libfcn = unsignedp ? fixunsxfdi_libfunc : fixxfdi_libfunc;
4525       else if (GET_MODE (to) == TImode)
4526         libfcn = unsignedp ? fixunsxfti_libfunc : fixxfti_libfunc;
4527       else
4528         abort ();
4529     }
4530   else if (GET_MODE (from) == TFmode)
4531     {
4532       if (GET_MODE (to) == SImode)
4533         libfcn = unsignedp ? fixunstfsi_libfunc : fixtfsi_libfunc;
4534       else if (GET_MODE (to) == DImode)
4535         libfcn = unsignedp ? fixunstfdi_libfunc : fixtfdi_libfunc;
4536       else if (GET_MODE (to) == TImode)
4537         libfcn = unsignedp ? fixunstfti_libfunc : fixtfti_libfunc;
4538       else
4539         abort ();
4540     }
4541   else
4542     abort ();
4543
4544   if (libfcn)
4545     {
4546       rtx insns;
4547       rtx value;
4548
4549       to = protect_from_queue (to, 1);
4550       from = protect_from_queue (from, 0);
4551
4552       if (flag_force_mem)
4553         from = force_not_mem (from);
4554
4555       start_sequence ();
4556
4557       value = emit_library_call_value (libfcn, NULL_RTX, LCT_CONST,
4558                                        GET_MODE (to), 1, from,
4559                                        GET_MODE (from));
4560       insns = get_insns ();
4561       end_sequence ();
4562
4563       emit_libcall_block (insns, target, value,
4564                           gen_rtx_fmt_e (unsignedp ? UNSIGNED_FIX : FIX,
4565                                          GET_MODE (to), from));
4566     }
4567       
4568   if (target != to)
4569     {
4570       if (GET_MODE (to) == GET_MODE (target))
4571         emit_move_insn (to, target);
4572       else
4573         convert_move (to, target, 0);
4574     }
4575 }
4576 \f
4577 /* Report whether we have an instruction to perform the operation
4578    specified by CODE on operands of mode MODE.  */
4579 int
4580 have_insn_for (code, mode)
4581      enum rtx_code code;
4582      enum machine_mode mode;
4583 {
4584   return (code_to_optab[(int) code] != 0
4585           && (code_to_optab[(int) code]->handlers[(int) mode].insn_code
4586               != CODE_FOR_nothing));
4587 }
4588
4589 /* Create a blank optab.  */
4590 static optab
4591 new_optab ()
4592 {
4593   int i;
4594   optab op = (optab) xmalloc (sizeof (struct optab));
4595   for (i = 0; i < NUM_MACHINE_MODES; i++)
4596     {
4597       op->handlers[i].insn_code = CODE_FOR_nothing;
4598       op->handlers[i].libfunc = 0;
4599     }
4600
4601   return op;
4602 }
4603
4604 /* Same, but fill in its code as CODE, and write it into the
4605    code_to_optab table.  */
4606 static inline optab
4607 init_optab (code)
4608      enum rtx_code code;
4609 {
4610   optab op = new_optab ();
4611   op->code = code;
4612   code_to_optab[(int) code] = op;
4613   return op;
4614 }
4615
4616 /* Same, but fill in its code as CODE, and do _not_ write it into
4617    the code_to_optab table.  */
4618 static inline optab
4619 init_optabv (code)
4620      enum rtx_code code;
4621 {
4622   optab op = new_optab ();
4623   op->code = code;
4624   return op;
4625 }
4626
4627 /* Initialize the libfunc fields of an entire group of entries in some
4628    optab.  Each entry is set equal to a string consisting of a leading
4629    pair of underscores followed by a generic operation name followed by
4630    a mode name (downshifted to lower case) followed by a single character
4631    representing the number of operands for the given operation (which is
4632    usually one of the characters '2', '3', or '4').
4633
4634    OPTABLE is the table in which libfunc fields are to be initialized.
4635    FIRST_MODE is the first machine mode index in the given optab to
4636      initialize.
4637    LAST_MODE is the last machine mode index in the given optab to
4638      initialize.
4639    OPNAME is the generic (string) name of the operation.
4640    SUFFIX is the character which specifies the number of operands for
4641      the given generic operation.
4642 */
4643
4644 static void
4645 init_libfuncs (optable, first_mode, last_mode, opname, suffix)
4646     optab optable;
4647     int first_mode;
4648     int last_mode;
4649     const char *opname;
4650     int suffix;
4651 {
4652   int mode;
4653   unsigned opname_len = strlen (opname);
4654
4655   for (mode = first_mode; (int) mode <= (int) last_mode;
4656        mode = (enum machine_mode) ((int) mode + 1))
4657     {
4658       const char *mname = GET_MODE_NAME(mode);
4659       unsigned mname_len = strlen (mname);
4660       char *libfunc_name = alloca (2 + opname_len + mname_len + 1 + 1);
4661       char *p;
4662       const char *q;
4663
4664       p = libfunc_name;
4665       *p++ = '_';
4666       *p++ = '_';
4667       for (q = opname; *q; )
4668         *p++ = *q++;
4669       for (q = mname; *q; q++)
4670         *p++ = TOLOWER (*q);
4671       *p++ = suffix;
4672       *p = '\0';
4673
4674       optable->handlers[(int) mode].libfunc
4675         = gen_rtx_SYMBOL_REF (Pmode, ggc_alloc_string (libfunc_name,
4676                                                        p - libfunc_name));
4677     }
4678 }
4679
4680 /* Initialize the libfunc fields of an entire group of entries in some
4681    optab which correspond to all integer mode operations.  The parameters
4682    have the same meaning as similarly named ones for the `init_libfuncs'
4683    routine.  (See above).  */
4684
4685 static void
4686 init_integral_libfuncs (optable, opname, suffix)
4687     optab optable;
4688     const char *opname;
4689     int suffix;
4690 {
4691   init_libfuncs (optable, SImode, TImode, opname, suffix);
4692 }
4693
4694 /* Initialize the libfunc fields of an entire group of entries in some
4695    optab which correspond to all real mode operations.  The parameters
4696    have the same meaning as similarly named ones for the `init_libfuncs'
4697    routine.  (See above).  */
4698
4699 static void
4700 init_floating_libfuncs (optable, opname, suffix)
4701     optab optable;
4702     const char *opname;
4703     int suffix;
4704 {
4705   init_libfuncs (optable, SFmode, TFmode, opname, suffix);
4706 }
4707
4708 rtx
4709 init_one_libfunc (name)
4710      const char *name;
4711 {
4712   /* Create a FUNCTION_DECL that can be passed to ENCODE_SECTION_INFO.  */
4713   /* ??? We don't have any type information except for this is
4714      a function.  Pretend this is "int foo()".  */
4715   tree decl = build_decl (FUNCTION_DECL, get_identifier (name),
4716                           build_function_type (integer_type_node, NULL_TREE));
4717   DECL_ARTIFICIAL (decl) = 1;
4718   DECL_EXTERNAL (decl) = 1;
4719   TREE_PUBLIC (decl) = 1;
4720
4721   /* Return the symbol_ref from the mem rtx.  */
4722   return XEXP (DECL_RTL (decl), 0);
4723 }
4724
4725 /* Mark ARG (which is really an OPTAB *) for GC.  */
4726
4727 void
4728 mark_optab (arg)
4729      void *arg;
4730 {
4731   optab o = *(optab *) arg;
4732   int i;
4733
4734   for (i = 0; i < NUM_MACHINE_MODES; ++i)
4735     ggc_mark_rtx (o->handlers[i].libfunc);
4736 }
4737
4738 /* Call this once to initialize the contents of the optabs
4739    appropriately for the current target machine.  */
4740
4741 void
4742 init_optabs ()
4743 {
4744   unsigned int i, j, k;
4745
4746   /* Start by initializing all tables to contain CODE_FOR_nothing.  */
4747
4748   for (i = 0; i < ARRAY_SIZE (fixtab); i++)
4749     for (j = 0; j < ARRAY_SIZE (fixtab[0]); j++)
4750       for (k = 0; k < ARRAY_SIZE (fixtab[0][0]); k++)
4751         fixtab[i][j][k] = CODE_FOR_nothing;
4752
4753   for (i = 0; i < ARRAY_SIZE (fixtrunctab); i++)
4754     for (j = 0; j < ARRAY_SIZE (fixtrunctab[0]); j++)
4755       for (k = 0; k < ARRAY_SIZE (fixtrunctab[0][0]); k++)
4756         fixtrunctab[i][j][k] = CODE_FOR_nothing;
4757
4758   for (i = 0; i < ARRAY_SIZE (floattab); i++)
4759     for (j = 0; j < ARRAY_SIZE (floattab[0]); j++)
4760       for (k = 0; k < ARRAY_SIZE (floattab[0][0]); k++)
4761         floattab[i][j][k] = CODE_FOR_nothing;
4762
4763   for (i = 0; i < ARRAY_SIZE (extendtab); i++)
4764     for (j = 0; j < ARRAY_SIZE (extendtab[0]); j++)
4765       for (k = 0; k < ARRAY_SIZE (extendtab[0][0]); k++)
4766         extendtab[i][j][k] = CODE_FOR_nothing;
4767
4768   for (i = 0; i < NUM_RTX_CODE; i++)
4769     setcc_gen_code[i] = CODE_FOR_nothing;
4770
4771 #ifdef HAVE_conditional_move
4772   for (i = 0; i < NUM_MACHINE_MODES; i++)
4773     movcc_gen_code[i] = CODE_FOR_nothing;
4774 #endif
4775
4776   add_optab = init_optab (PLUS);
4777   addv_optab = init_optabv (PLUS);
4778   sub_optab = init_optab (MINUS);
4779   subv_optab = init_optabv (MINUS);
4780   smul_optab = init_optab (MULT);
4781   smulv_optab = init_optabv (MULT);
4782   smul_highpart_optab = init_optab (UNKNOWN);
4783   umul_highpart_optab = init_optab (UNKNOWN);
4784   smul_widen_optab = init_optab (UNKNOWN);
4785   umul_widen_optab = init_optab (UNKNOWN);
4786   sdiv_optab = init_optab (DIV);
4787   sdivv_optab = init_optabv (DIV);
4788   sdivmod_optab = init_optab (UNKNOWN);
4789   udiv_optab = init_optab (UDIV);
4790   udivmod_optab = init_optab (UNKNOWN);
4791   smod_optab = init_optab (MOD);
4792   umod_optab = init_optab (UMOD);
4793   ftrunc_optab = init_optab (UNKNOWN);
4794   and_optab = init_optab (AND);
4795   ior_optab = init_optab (IOR);
4796   xor_optab = init_optab (XOR);
4797   ashl_optab = init_optab (ASHIFT);
4798   ashr_optab = init_optab (ASHIFTRT);
4799   lshr_optab = init_optab (LSHIFTRT);
4800   rotl_optab = init_optab (ROTATE);
4801   rotr_optab = init_optab (ROTATERT);
4802   smin_optab = init_optab (SMIN);
4803   smax_optab = init_optab (SMAX);
4804   umin_optab = init_optab (UMIN);
4805   umax_optab = init_optab (UMAX);
4806
4807   /* These three have codes assigned exclusively for the sake of
4808      have_insn_for.  */
4809   mov_optab = init_optab (SET);
4810   movstrict_optab = init_optab (STRICT_LOW_PART);
4811   cmp_optab = init_optab (COMPARE);
4812
4813   ucmp_optab = init_optab (UNKNOWN);
4814   tst_optab = init_optab (UNKNOWN);
4815   neg_optab = init_optab (NEG);
4816   negv_optab = init_optabv (NEG);
4817   abs_optab = init_optab (ABS);
4818   absv_optab = init_optabv (ABS);
4819   one_cmpl_optab = init_optab (NOT);
4820   ffs_optab = init_optab (FFS);
4821   sqrt_optab = init_optab (SQRT);
4822   sin_optab = init_optab (UNKNOWN);
4823   cos_optab = init_optab (UNKNOWN);
4824   strlen_optab = init_optab (UNKNOWN);
4825   cbranch_optab = init_optab (UNKNOWN);
4826   cmov_optab = init_optab (UNKNOWN);
4827   cstore_optab = init_optab (UNKNOWN);
4828   push_optab = init_optab (UNKNOWN);
4829
4830   for (i = 0; i < NUM_MACHINE_MODES; i++)
4831     {
4832       movstr_optab[i] = CODE_FOR_nothing;
4833       clrstr_optab[i] = CODE_FOR_nothing;
4834
4835 #ifdef HAVE_SECONDARY_RELOADS
4836       reload_in_optab[i] = reload_out_optab[i] = CODE_FOR_nothing;
4837 #endif
4838     }
4839
4840   /* Fill in the optabs with the insns we support.  */
4841   init_all_optabs ();
4842
4843 #ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC
4844   /* This flag says the same insns that convert to a signed fixnum
4845      also convert validly to an unsigned one.  */
4846   for (i = 0; i < NUM_MACHINE_MODES; i++)
4847     for (j = 0; j < NUM_MACHINE_MODES; j++)
4848       fixtrunctab[i][j][1] = fixtrunctab[i][j][0];
4849 #endif
4850
4851   /* Initialize the optabs with the names of the library functions.  */
4852   init_integral_libfuncs (add_optab, "add", '3');
4853   init_floating_libfuncs (add_optab, "add", '3');
4854   init_integral_libfuncs (addv_optab, "addv", '3');
4855   init_floating_libfuncs (addv_optab, "add", '3');
4856   init_integral_libfuncs (sub_optab, "sub", '3');
4857   init_floating_libfuncs (sub_optab, "sub", '3');
4858   init_integral_libfuncs (subv_optab, "subv", '3');
4859   init_floating_libfuncs (subv_optab, "sub", '3');
4860   init_integral_libfuncs (smul_optab, "mul", '3');
4861   init_floating_libfuncs (smul_optab, "mul", '3');
4862   init_integral_libfuncs (smulv_optab, "mulv", '3');
4863   init_floating_libfuncs (smulv_optab, "mul", '3');
4864   init_integral_libfuncs (sdiv_optab, "div", '3');
4865   init_floating_libfuncs (sdiv_optab, "div", '3');
4866   init_integral_libfuncs (sdivv_optab, "divv", '3');
4867   init_integral_libfuncs (udiv_optab, "udiv", '3');
4868   init_integral_libfuncs (sdivmod_optab, "divmod", '4');
4869   init_integral_libfuncs (udivmod_optab, "udivmod", '4');
4870   init_integral_libfuncs (smod_optab, "mod", '3');
4871   init_integral_libfuncs (umod_optab, "umod", '3');
4872   init_floating_libfuncs (ftrunc_optab, "ftrunc", '2');
4873   init_integral_libfuncs (and_optab, "and", '3');
4874   init_integral_libfuncs (ior_optab, "ior", '3');
4875   init_integral_libfuncs (xor_optab, "xor", '3');
4876   init_integral_libfuncs (ashl_optab, "ashl", '3');
4877   init_integral_libfuncs (ashr_optab, "ashr", '3');
4878   init_integral_libfuncs (lshr_optab, "lshr", '3');
4879   init_integral_libfuncs (smin_optab, "min", '3');
4880   init_floating_libfuncs (smin_optab, "min", '3');
4881   init_integral_libfuncs (smax_optab, "max", '3');
4882   init_floating_libfuncs (smax_optab, "max", '3');
4883   init_integral_libfuncs (umin_optab, "umin", '3');
4884   init_integral_libfuncs (umax_optab, "umax", '3');
4885   init_integral_libfuncs (neg_optab, "neg", '2');
4886   init_floating_libfuncs (neg_optab, "neg", '2');
4887   init_integral_libfuncs (negv_optab, "negv", '2');
4888   init_floating_libfuncs (negv_optab, "neg", '2');
4889   init_integral_libfuncs (one_cmpl_optab, "one_cmpl", '2');
4890   init_integral_libfuncs (ffs_optab, "ffs", '2');
4891
4892   /* Comparison libcalls for integers MUST come in pairs, signed/unsigned.  */
4893   init_integral_libfuncs (cmp_optab, "cmp", '2');
4894   init_integral_libfuncs (ucmp_optab, "ucmp", '2');
4895   init_floating_libfuncs (cmp_optab, "cmp", '2');
4896
4897 #ifdef MULSI3_LIBCALL
4898   smul_optab->handlers[(int) SImode].libfunc
4899     = init_one_libfunc (MULSI3_LIBCALL);
4900 #endif
4901 #ifdef MULDI3_LIBCALL
4902   smul_optab->handlers[(int) DImode].libfunc
4903     = init_one_libfunc (MULDI3_LIBCALL);
4904 #endif
4905
4906 #ifdef DIVSI3_LIBCALL
4907   sdiv_optab->handlers[(int) SImode].libfunc
4908     = init_one_libfunc (DIVSI3_LIBCALL);
4909 #endif
4910 #ifdef DIVDI3_LIBCALL
4911   sdiv_optab->handlers[(int) DImode].libfunc
4912     = init_one_libfunc (DIVDI3_LIBCALL);
4913 #endif
4914
4915 #ifdef UDIVSI3_LIBCALL
4916   udiv_optab->handlers[(int) SImode].libfunc
4917     = init_one_libfunc (UDIVSI3_LIBCALL);
4918 #endif
4919 #ifdef UDIVDI3_LIBCALL
4920   udiv_optab->handlers[(int) DImode].libfunc
4921     = init_one_libfunc (UDIVDI3_LIBCALL);
4922 #endif
4923
4924 #ifdef MODSI3_LIBCALL
4925   smod_optab->handlers[(int) SImode].libfunc
4926     = init_one_libfunc (MODSI3_LIBCALL);
4927 #endif
4928 #ifdef MODDI3_LIBCALL
4929   smod_optab->handlers[(int) DImode].libfunc
4930     = init_one_libfunc (MODDI3_LIBCALL);
4931 #endif
4932
4933 #ifdef UMODSI3_LIBCALL
4934   umod_optab->handlers[(int) SImode].libfunc
4935     = init_one_libfunc (UMODSI3_LIBCALL);
4936 #endif
4937 #ifdef UMODDI3_LIBCALL
4938   umod_optab->handlers[(int) DImode].libfunc
4939     = init_one_libfunc (UMODDI3_LIBCALL);
4940 #endif
4941
4942   /* Use cabs for DC complex abs, since systems generally have cabs.
4943      Don't define any libcall for SCmode, so that cabs will be used.  */
4944   abs_optab->handlers[(int) DCmode].libfunc
4945     = init_one_libfunc ("cabs");
4946
4947   /* The ffs function operates on `int'.  */
4948   ffs_optab->handlers[(int) mode_for_size (INT_TYPE_SIZE, MODE_INT, 0)].libfunc
4949     = init_one_libfunc ("ffs");
4950
4951   extendsfdf2_libfunc = init_one_libfunc ("__extendsfdf2");
4952   extendsfxf2_libfunc = init_one_libfunc ("__extendsfxf2");
4953   extendsftf2_libfunc = init_one_libfunc ("__extendsftf2");
4954   extenddfxf2_libfunc = init_one_libfunc ("__extenddfxf2");
4955   extenddftf2_libfunc = init_one_libfunc ("__extenddftf2");
4956
4957   truncdfsf2_libfunc = init_one_libfunc ("__truncdfsf2");
4958   truncxfsf2_libfunc = init_one_libfunc ("__truncxfsf2");
4959   trunctfsf2_libfunc = init_one_libfunc ("__trunctfsf2");
4960   truncxfdf2_libfunc = init_one_libfunc ("__truncxfdf2");
4961   trunctfdf2_libfunc = init_one_libfunc ("__trunctfdf2");
4962
4963   abort_libfunc = init_one_libfunc ("abort");
4964   memcpy_libfunc = init_one_libfunc ("memcpy");
4965   memmove_libfunc = init_one_libfunc ("memmove");
4966   bcopy_libfunc = init_one_libfunc ("bcopy");
4967   memcmp_libfunc = init_one_libfunc ("memcmp");
4968   bcmp_libfunc = init_one_libfunc ("__gcc_bcmp");
4969   memset_libfunc = init_one_libfunc ("memset");
4970   bzero_libfunc = init_one_libfunc ("bzero");
4971
4972   unwind_resume_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
4973                                             ? "_Unwind_SjLj_Resume"
4974                                             : "_Unwind_Resume");
4975 #ifndef DONT_USE_BUILTIN_SETJMP
4976   setjmp_libfunc = init_one_libfunc ("__builtin_setjmp");
4977   longjmp_libfunc = init_one_libfunc ("__builtin_longjmp");
4978 #else
4979   setjmp_libfunc = init_one_libfunc ("setjmp");
4980   longjmp_libfunc = init_one_libfunc ("longjmp");
4981 #endif
4982   unwind_sjlj_register_libfunc = init_one_libfunc ("_Unwind_SjLj_Register");
4983   unwind_sjlj_unregister_libfunc
4984     = init_one_libfunc ("_Unwind_SjLj_Unregister");
4985
4986   eqhf2_libfunc = init_one_libfunc ("__eqhf2");
4987   nehf2_libfunc = init_one_libfunc ("__nehf2");
4988   gthf2_libfunc = init_one_libfunc ("__gthf2");
4989   gehf2_libfunc = init_one_libfunc ("__gehf2");
4990   lthf2_libfunc = init_one_libfunc ("__lthf2");
4991   lehf2_libfunc = init_one_libfunc ("__lehf2");
4992   unordhf2_libfunc = init_one_libfunc ("__unordhf2");
4993
4994   eqsf2_libfunc = init_one_libfunc ("__eqsf2");
4995   nesf2_libfunc = init_one_libfunc ("__nesf2");
4996   gtsf2_libfunc = init_one_libfunc ("__gtsf2");
4997   gesf2_libfunc = init_one_libfunc ("__gesf2");
4998   ltsf2_libfunc = init_one_libfunc ("__ltsf2");
4999   lesf2_libfunc = init_one_libfunc ("__lesf2");
5000   unordsf2_libfunc = init_one_libfunc ("__unordsf2");
5001
5002   eqdf2_libfunc = init_one_libfunc ("__eqdf2");
5003   nedf2_libfunc = init_one_libfunc ("__nedf2");
5004   gtdf2_libfunc = init_one_libfunc ("__gtdf2");
5005   gedf2_libfunc = init_one_libfunc ("__gedf2");
5006   ltdf2_libfunc = init_one_libfunc ("__ltdf2");
5007   ledf2_libfunc = init_one_libfunc ("__ledf2");
5008   unorddf2_libfunc = init_one_libfunc ("__unorddf2");
5009
5010   eqxf2_libfunc = init_one_libfunc ("__eqxf2");
5011   nexf2_libfunc = init_one_libfunc ("__nexf2");
5012   gtxf2_libfunc = init_one_libfunc ("__gtxf2");
5013   gexf2_libfunc = init_one_libfunc ("__gexf2");
5014   ltxf2_libfunc = init_one_libfunc ("__ltxf2");
5015   lexf2_libfunc = init_one_libfunc ("__lexf2");
5016   unordxf2_libfunc = init_one_libfunc ("__unordxf2");
5017
5018   eqtf2_libfunc = init_one_libfunc ("__eqtf2");
5019   netf2_libfunc = init_one_libfunc ("__netf2");
5020   gttf2_libfunc = init_one_libfunc ("__gttf2");
5021   getf2_libfunc = init_one_libfunc ("__getf2");
5022   lttf2_libfunc = init_one_libfunc ("__lttf2");
5023   letf2_libfunc = init_one_libfunc ("__letf2");
5024   unordtf2_libfunc = init_one_libfunc ("__unordtf2");
5025
5026   floatsisf_libfunc = init_one_libfunc ("__floatsisf");
5027   floatdisf_libfunc = init_one_libfunc ("__floatdisf");
5028   floattisf_libfunc = init_one_libfunc ("__floattisf");
5029
5030   floatsidf_libfunc = init_one_libfunc ("__floatsidf");
5031   floatdidf_libfunc = init_one_libfunc ("__floatdidf");
5032   floattidf_libfunc = init_one_libfunc ("__floattidf");
5033
5034   floatsixf_libfunc = init_one_libfunc ("__floatsixf");
5035   floatdixf_libfunc = init_one_libfunc ("__floatdixf");
5036   floattixf_libfunc = init_one_libfunc ("__floattixf");
5037
5038   floatsitf_libfunc = init_one_libfunc ("__floatsitf");
5039   floatditf_libfunc = init_one_libfunc ("__floatditf");
5040   floattitf_libfunc = init_one_libfunc ("__floattitf");
5041
5042   fixsfsi_libfunc = init_one_libfunc ("__fixsfsi");
5043   fixsfdi_libfunc = init_one_libfunc ("__fixsfdi");
5044   fixsfti_libfunc = init_one_libfunc ("__fixsfti");
5045
5046   fixdfsi_libfunc = init_one_libfunc ("__fixdfsi");
5047   fixdfdi_libfunc = init_one_libfunc ("__fixdfdi");
5048   fixdfti_libfunc = init_one_libfunc ("__fixdfti");
5049
5050   fixxfsi_libfunc = init_one_libfunc ("__fixxfsi");
5051   fixxfdi_libfunc = init_one_libfunc ("__fixxfdi");
5052   fixxfti_libfunc = init_one_libfunc ("__fixxfti");
5053
5054   fixtfsi_libfunc = init_one_libfunc ("__fixtfsi");
5055   fixtfdi_libfunc = init_one_libfunc ("__fixtfdi");
5056   fixtfti_libfunc = init_one_libfunc ("__fixtfti");
5057
5058   fixunssfsi_libfunc = init_one_libfunc ("__fixunssfsi");
5059   fixunssfdi_libfunc = init_one_libfunc ("__fixunssfdi");
5060   fixunssfti_libfunc = init_one_libfunc ("__fixunssfti");
5061
5062   fixunsdfsi_libfunc = init_one_libfunc ("__fixunsdfsi");
5063   fixunsdfdi_libfunc = init_one_libfunc ("__fixunsdfdi");
5064   fixunsdfti_libfunc = init_one_libfunc ("__fixunsdfti");
5065
5066   fixunsxfsi_libfunc = init_one_libfunc ("__fixunsxfsi");
5067   fixunsxfdi_libfunc = init_one_libfunc ("__fixunsxfdi");
5068   fixunsxfti_libfunc = init_one_libfunc ("__fixunsxfti");
5069
5070   fixunstfsi_libfunc = init_one_libfunc ("__fixunstfsi");
5071   fixunstfdi_libfunc = init_one_libfunc ("__fixunstfdi");
5072   fixunstfti_libfunc = init_one_libfunc ("__fixunstfti");
5073
5074   /* For function entry/exit instrumentation.  */
5075   profile_function_entry_libfunc
5076     = init_one_libfunc ("__cyg_profile_func_enter");
5077   profile_function_exit_libfunc
5078     = init_one_libfunc ("__cyg_profile_func_exit");
5079
5080 #ifdef HAVE_conditional_trap
5081   init_traps ();
5082 #endif
5083
5084 #ifdef INIT_TARGET_OPTABS
5085   /* Allow the target to add more libcalls or rename some, etc.  */
5086   INIT_TARGET_OPTABS;
5087 #endif
5088
5089   /* Add these GC roots.  */
5090   ggc_add_root (optab_table, OTI_MAX, sizeof(optab), mark_optab);
5091   ggc_add_rtx_root (libfunc_table, LTI_MAX);
5092 }
5093 \f
5094 #ifdef HAVE_conditional_trap
5095 /* The insn generating function can not take an rtx_code argument.
5096    TRAP_RTX is used as an rtx argument.  Its code is replaced with
5097    the code to be used in the trap insn and all other fields are
5098    ignored.  */
5099 static rtx trap_rtx;
5100
5101 static void
5102 init_traps ()
5103 {
5104   if (HAVE_conditional_trap)
5105     {
5106       trap_rtx = gen_rtx_fmt_ee (EQ, VOIDmode, NULL_RTX, NULL_RTX);
5107       ggc_add_rtx_root (&trap_rtx, 1);
5108     }
5109 }
5110 #endif
5111
5112 /* Generate insns to trap with code TCODE if OP1 and OP2 satisfy condition
5113    CODE.  Return 0 on failure.  */
5114
5115 rtx
5116 gen_cond_trap (code, op1, op2, tcode)
5117   enum rtx_code code ATTRIBUTE_UNUSED;
5118   rtx op1, op2 ATTRIBUTE_UNUSED, tcode ATTRIBUTE_UNUSED;
5119 {
5120   enum machine_mode mode = GET_MODE (op1);
5121
5122   if (mode == VOIDmode)
5123     return 0;
5124
5125 #ifdef HAVE_conditional_trap
5126   if (HAVE_conditional_trap
5127       && cmp_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
5128     {
5129       rtx insn;
5130       start_sequence();
5131       emit_insn (GEN_FCN (cmp_optab->handlers[(int) mode].insn_code) (op1, op2));
5132       PUT_CODE (trap_rtx, code);
5133       insn = gen_conditional_trap (trap_rtx, tcode);
5134       if (insn)
5135         {
5136           emit_insn (insn);
5137           insn = gen_sequence ();
5138         }
5139       end_sequence();
5140       return insn;
5141     }
5142 #endif
5143
5144   return 0;
5145 }