OSDN Git Service

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