OSDN Git Service

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