OSDN Git Service

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