OSDN Git Service

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