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