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