OSDN Git Service

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