OSDN Git Service

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