OSDN Git Service

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