OSDN Git Service

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