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