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