OSDN Git Service

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