OSDN Git Service

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