OSDN Git Service

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