OSDN Git Service

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