OSDN Git Service

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