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