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