OSDN Git Service

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