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