BSD 4_4_Lite2 development
[unix-history] / usr / src / contrib / gcc-2.3.3 / optabs.c
CommitLineData
6222e40e
C
1/* Expand the basic unary and binary arithmetic operations, for GNU compiler.
2 Copyright (C) 1987, 1988, 1992 Free Software Foundation, Inc.
3
4This file is part of GNU CC.
5
6GNU CC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU CC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU CC; see the file COPYING. If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20
21#include "config.h"
22#include "rtl.h"
23#include "tree.h"
24#include "flags.h"
25#include "insn-flags.h"
26#include "insn-codes.h"
27#include "expr.h"
28#include "insn-config.h"
29#include "recog.h"
30#include <ctype.h>
31
32/* Each optab contains info on how this target machine
33 can perform a particular operation
34 for all sizes and kinds of operands.
35
36 The operation to be performed is often specified
37 by passing one of these optabs as an argument.
38
39 See expr.h for documentation of these optabs. */
40
41optab add_optab;
42optab sub_optab;
43optab smul_optab;
44optab smul_widen_optab;
45optab umul_widen_optab;
46optab sdiv_optab;
47optab sdivmod_optab;
48optab udiv_optab;
49optab udivmod_optab;
50optab smod_optab;
51optab umod_optab;
52optab flodiv_optab;
53optab ftrunc_optab;
54optab and_optab;
55optab ior_optab;
56optab xor_optab;
57optab ashl_optab;
58optab lshr_optab;
59optab lshl_optab;
60optab ashr_optab;
61optab rotl_optab;
62optab rotr_optab;
63optab smin_optab;
64optab smax_optab;
65optab umin_optab;
66optab umax_optab;
67
68optab mov_optab;
69optab movstrict_optab;
70
71optab neg_optab;
72optab abs_optab;
73optab one_cmpl_optab;
74optab ffs_optab;
75optab sqrt_optab;
76optab sin_optab;
77optab cos_optab;
78
79optab cmp_optab;
80optab ucmp_optab; /* Used only for libcalls for unsigned comparisons. */
81optab tst_optab;
82
83optab strlen_optab;
84
85/* SYMBOL_REF rtx's for the library functions that are called
86 implicitly and not via optabs. */
87
88rtx extendsfdf2_libfunc;
89rtx extendsfxf2_libfunc;
90rtx extendsftf2_libfunc;
91rtx extenddfxf2_libfunc;
92rtx extenddftf2_libfunc;
93
94rtx truncdfsf2_libfunc;
95rtx truncxfsf2_libfunc;
96rtx trunctfsf2_libfunc;
97rtx truncxfdf2_libfunc;
98rtx trunctfdf2_libfunc;
99
100rtx memcpy_libfunc;
101rtx bcopy_libfunc;
102rtx memcmp_libfunc;
103rtx bcmp_libfunc;
104rtx memset_libfunc;
105rtx bzero_libfunc;
106
107rtx eqsf2_libfunc;
108rtx nesf2_libfunc;
109rtx gtsf2_libfunc;
110rtx gesf2_libfunc;
111rtx ltsf2_libfunc;
112rtx lesf2_libfunc;
113
114rtx eqdf2_libfunc;
115rtx nedf2_libfunc;
116rtx gtdf2_libfunc;
117rtx gedf2_libfunc;
118rtx ltdf2_libfunc;
119rtx ledf2_libfunc;
120
121rtx eqxf2_libfunc;
122rtx nexf2_libfunc;
123rtx gtxf2_libfunc;
124rtx gexf2_libfunc;
125rtx ltxf2_libfunc;
126rtx lexf2_libfunc;
127
128rtx eqtf2_libfunc;
129rtx netf2_libfunc;
130rtx gttf2_libfunc;
131rtx getf2_libfunc;
132rtx lttf2_libfunc;
133rtx letf2_libfunc;
134
135rtx floatsisf_libfunc;
136rtx floatdisf_libfunc;
137rtx floattisf_libfunc;
138
139rtx floatsidf_libfunc;
140rtx floatdidf_libfunc;
141rtx floattidf_libfunc;
142
143rtx floatsixf_libfunc;
144rtx floatdixf_libfunc;
145rtx floattixf_libfunc;
146
147rtx floatsitf_libfunc;
148rtx floatditf_libfunc;
149rtx floattitf_libfunc;
150
151rtx fixsfsi_libfunc;
152rtx fixsfdi_libfunc;
153rtx fixsfti_libfunc;
154
155rtx fixdfsi_libfunc;
156rtx fixdfdi_libfunc;
157rtx fixdfti_libfunc;
158
159rtx fixxfsi_libfunc;
160rtx fixxfdi_libfunc;
161rtx fixxfti_libfunc;
162
163rtx fixtfsi_libfunc;
164rtx fixtfdi_libfunc;
165rtx fixtfti_libfunc;
166
167rtx fixunssfsi_libfunc;
168rtx fixunssfdi_libfunc;
169rtx fixunssfti_libfunc;
170
171rtx fixunsdfsi_libfunc;
172rtx fixunsdfdi_libfunc;
173rtx fixunsdfti_libfunc;
174
175rtx fixunsxfsi_libfunc;
176rtx fixunsxfdi_libfunc;
177rtx fixunsxfti_libfunc;
178
179rtx fixunstfsi_libfunc;
180rtx fixunstfdi_libfunc;
181rtx fixunstfti_libfunc;
182
183/* from emit-rtl.c */
184extern rtx gen_highpart ();
185
186/* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
187 gives the gen_function to make a branch to test that condition. */
188
189rtxfun bcc_gen_fctn[NUM_RTX_CODE];
190
191/* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
192 gives the insn code to make a store-condition insn
193 to test that condition. */
194
195enum insn_code setcc_gen_code[NUM_RTX_CODE];
196
197static void emit_float_lib_cmp ();
198\f
199/* Add a REG_EQUAL note to the last insn in SEQ. TARGET is being set to
200 the result of operation CODE applied to OP0 (and OP1 if it is a binary
201 operation).
202
203 If the last insn does not set TARGET, don't do anything, but return 1.
204
205 If a previous insn sets TARGET and TARGET is one of OP0 or OP1,
206 don't add the REG_EQUAL note but return 0. Our caller can then try
207 again, ensuring that TARGET is not one of the operands. */
208
209static int
210add_equal_note (seq, target, code, op0, op1)
211 rtx seq;
212 rtx target;
213 enum rtx_code code;
214 rtx op0, op1;
215{
216 rtx set;
217 int i;
218 rtx note;
219
220 if ((GET_RTX_CLASS (code) != '1' && GET_RTX_CLASS (code) != '2'
221 && GET_RTX_CLASS (code) != 'c' && GET_RTX_CLASS (code) != '<')
222 || GET_CODE (seq) != SEQUENCE
223 || (set = single_set (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1))) == 0
224 || GET_CODE (target) == ZERO_EXTRACT
225 || (! rtx_equal_p (SET_DEST (set), target)
226 /* For a STRICT_LOW_PART, the REG_NOTE applies to what is inside the
227 SUBREG. */
228 && (GET_CODE (SET_DEST (set)) != STRICT_LOW_PART
229 || ! rtx_equal_p (SUBREG_REG (XEXP (SET_DEST (set), 0)),
230 target))))
231 return 1;
232
233 /* If TARGET is in OP0 or OP1, check if anything in SEQ sets TARGET
234 besides the last insn. */
235 if (reg_overlap_mentioned_p (target, op0)
236 || (op1 && reg_overlap_mentioned_p (target, op1)))
237 for (i = XVECLEN (seq, 0) - 2; i >= 0; i--)
238 if (reg_set_p (target, XVECEXP (seq, 0, i)))
239 return 0;
240
241 if (GET_RTX_CLASS (code) == '1')
242 note = gen_rtx (code, GET_MODE (target), op0);
243 else
244 note = gen_rtx (code, GET_MODE (target), op0, op1);
245
246 REG_NOTES (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1))
247 = gen_rtx (EXPR_LIST, REG_EQUAL, note,
248 REG_NOTES (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1)));
249
250 return 1;
251}
252\f
253/* Generate code to perform an operation specified by BINOPTAB
254 on operands OP0 and OP1, with result having machine-mode MODE.
255
256 UNSIGNEDP is for the case where we have to widen the operands
257 to perform the operation. It says to use zero-extension.
258
259 If TARGET is nonzero, the value
260 is generated there, if it is convenient to do so.
261 In all cases an rtx is returned for the locus of the value;
262 this may or may not be TARGET. */
263
264rtx
265expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
266 enum machine_mode mode;
267 optab binoptab;
268 rtx op0, op1;
269 rtx target;
270 int unsignedp;
271 enum optab_methods methods;
272{
273 enum mode_class class;
274 enum machine_mode wider_mode;
275 register rtx temp;
276 int commutative_op = 0;
277 int shift_op = (binoptab->code == ASHIFT
278 || binoptab->code == ASHIFTRT
279 || binoptab->code == LSHIFT
280 || binoptab->code == LSHIFTRT
281 || binoptab->code == ROTATE
282 || binoptab->code == ROTATERT);
283 rtx entry_last = get_last_insn ();
284 rtx last;
285
286 class = GET_MODE_CLASS (mode);
287
288 op0 = protect_from_queue (op0, 0);
289 op1 = protect_from_queue (op1, 0);
290 if (target)
291 target = protect_from_queue (target, 1);
292
293 if (flag_force_mem)
294 {
295 op0 = force_not_mem (op0);
296 op1 = force_not_mem (op1);
297 }
298
299 /* If subtracting an integer constant, convert this into an addition of
300 the negated constant. */
301
302 if (binoptab == sub_optab && GET_CODE (op1) == CONST_INT)
303 {
304 op1 = negate_rtx (mode, op1);
305 binoptab = add_optab;
306 }
307
308 /* If we are inside an appropriately-short loop and one operand is an
309 expensive constant, force it into a register. */
310 if (CONSTANT_P (op0) && preserve_subexpressions_p ()
311 && rtx_cost (op0, binoptab->code) > 2)
312 op0 = force_reg (mode, op0);
313
314 if (CONSTANT_P (op1) && preserve_subexpressions_p ()
315 && rtx_cost (op1, binoptab->code) > 2)
316 op1 = force_reg (shift_op ? word_mode : mode, op1);
317
318 /* Record where to delete back to if we backtrack. */
319 last = get_last_insn ();
320
321 /* If operation is commutative,
322 try to make the first operand a register.
323 Even better, try to make it the same as the target.
324 Also try to make the last operand a constant. */
325 if (GET_RTX_CLASS (binoptab->code) == 'c'
326 || binoptab == smul_widen_optab
327 || binoptab == umul_widen_optab)
328 {
329 commutative_op = 1;
330
331 if (((target == 0 || GET_CODE (target) == REG)
332 ? ((GET_CODE (op1) == REG
333 && GET_CODE (op0) != REG)
334 || target == op1)
335 : rtx_equal_p (op1, target))
336 || GET_CODE (op0) == CONST_INT)
337 {
338 temp = op1;
339 op1 = op0;
340 op0 = temp;
341 }
342 }
343
344 /* If we can do it with a three-operand insn, do so. */
345
346 if (methods != OPTAB_MUST_WIDEN
347 && binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
348 {
349 int icode = (int) binoptab->handlers[(int) mode].insn_code;
350 enum machine_mode mode0 = insn_operand_mode[icode][1];
351 enum machine_mode mode1 = insn_operand_mode[icode][2];
352 rtx pat;
353 rtx xop0 = op0, xop1 = op1;
354
355 if (target)
356 temp = target;
357 else
358 temp = gen_reg_rtx (mode);
359
360 /* If it is a commutative operator and the modes would match
361 if we would swap the operands, we can save the conversions. */
362 if (commutative_op)
363 {
364 if (GET_MODE (op0) != mode0 && GET_MODE (op1) != mode1
365 && GET_MODE (op0) == mode1 && GET_MODE (op1) == mode0)
366 {
367 register rtx tmp;
368
369 tmp = op0; op0 = op1; op1 = tmp;
370 tmp = xop0; xop0 = xop1; xop1 = tmp;
371 }
372 }
373
374 /* In case the insn wants input operands in modes different from
375 the result, convert the operands. */
376
377 if (GET_MODE (op0) != VOIDmode
378 && GET_MODE (op0) != mode0)
379 xop0 = convert_to_mode (mode0, xop0, unsignedp);
380
381 if (GET_MODE (xop1) != VOIDmode
382 && GET_MODE (xop1) != mode1)
383 xop1 = convert_to_mode (mode1, xop1, unsignedp);
384
385 /* Now, if insn's predicates don't allow our operands, put them into
386 pseudo regs. */
387
388 if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))
389 xop0 = copy_to_mode_reg (mode0, xop0);
390
391 if (! (*insn_operand_predicate[icode][2]) (xop1, mode1))
392 xop1 = copy_to_mode_reg (mode1, xop1);
393
394 if (! (*insn_operand_predicate[icode][0]) (temp, mode))
395 temp = gen_reg_rtx (mode);
396
397 pat = GEN_FCN (icode) (temp, xop0, xop1);
398 if (pat)
399 {
400 /* If PAT is a multi-insn sequence, try to add an appropriate
401 REG_EQUAL note to it. If we can't because TEMP conflicts with an
402 operand, call ourselves again, this time without a target. */
403 if (GET_CODE (pat) == SEQUENCE
404 && ! add_equal_note (pat, temp, binoptab->code, xop0, xop1))
405 {
406 delete_insns_since (last);
407 return expand_binop (mode, binoptab, op0, op1, NULL_RTX,
408 unsignedp, methods);
409 }
410
411 emit_insn (pat);
412 return temp;
413 }
414 else
415 delete_insns_since (last);
416 }
417
418 /* If this is a multiply, see if we can do a widening operation that
419 takes operands of this mode and makes a wider mode. */
420
421 if (binoptab == smul_optab && GET_MODE_WIDER_MODE (mode) != VOIDmode
422 && (((unsignedp ? umul_widen_optab : smul_widen_optab)
423 ->handlers[(int) GET_MODE_WIDER_MODE (mode)].insn_code)
424 != CODE_FOR_nothing))
425 {
426 temp = expand_binop (GET_MODE_WIDER_MODE (mode),
427 unsignedp ? umul_widen_optab : smul_widen_optab,
428 op0, op1, 0, unsignedp, OPTAB_DIRECT);
429
430 if (GET_MODE_CLASS (mode) == MODE_INT)
431 return gen_lowpart (mode, temp);
432 else
433 return convert_to_mode (mode, temp, unsignedp);
434 }
435
436 /* Look for a wider mode of the same class for which we think we
437 can open-code the operation. Check for a widening multiply at the
438 wider mode as well. */
439
440 if ((class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
441 && methods != OPTAB_DIRECT && methods != OPTAB_LIB)
442 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
443 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
444 {
445 if (binoptab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing
446 || (binoptab == smul_optab
447 && GET_MODE_WIDER_MODE (wider_mode) != VOIDmode
448 && (((unsignedp ? umul_widen_optab : smul_widen_optab)
449 ->handlers[(int) GET_MODE_WIDER_MODE (wider_mode)].insn_code)
450 != CODE_FOR_nothing)))
451 {
452 rtx xop0 = op0, xop1 = op1;
453 int no_extend = 0;
454
455 /* For certain integer operations, we need not actually extend
456 the narrow operands, as long as we will truncate
457 the results to the same narrowness. Don't do this when
458 WIDER_MODE is wider than a word since a paradoxical SUBREG
459 isn't valid for such modes. */
460
461 if ((binoptab == ior_optab || binoptab == and_optab
462 || binoptab == xor_optab
463 || binoptab == add_optab || binoptab == sub_optab
464 || binoptab == smul_optab
465 || binoptab == ashl_optab || binoptab == lshl_optab)
466 && class == MODE_INT
467 && GET_MODE_SIZE (wider_mode) <= UNITS_PER_WORD)
468 no_extend = 1;
469
470 /* If an operand is a constant integer, we might as well
471 convert it since that is more efficient than using a SUBREG,
472 unlike the case for other operands. Similarly for
473 SUBREGs that were made due to promoted objects. */
474
475 if (no_extend && GET_MODE (xop0) != VOIDmode
476 && ! (GET_CODE (xop0) == SUBREG
477 && SUBREG_PROMOTED_VAR_P (xop0)))
478 xop0 = gen_rtx (SUBREG, wider_mode,
479 force_reg (GET_MODE (xop0), xop0), 0);
480 else
481 xop0 = convert_to_mode (wider_mode, xop0, unsignedp);
482
483 if (no_extend && GET_MODE (xop1) != VOIDmode
484 && ! (GET_CODE (xop1) == SUBREG
485 && SUBREG_PROMOTED_VAR_P (xop1)))
486 xop1 = gen_rtx (SUBREG, wider_mode,
487 force_reg (GET_MODE (xop1), xop1), 0);
488 else
489 xop1 = convert_to_mode (wider_mode, xop1, unsignedp);
490
491 temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX,
492 unsignedp, OPTAB_DIRECT);
493 if (temp)
494 {
495 if (class != MODE_INT)
496 {
497 if (target == 0)
498 target = gen_reg_rtx (mode);
499 convert_move (target, temp, 0);
500 return target;
501 }
502 else
503 return gen_lowpart (mode, temp);
504 }
505 else
506 delete_insns_since (last);
507 }
508 }
509
510 /* These can be done a word at a time. */
511 if ((binoptab == and_optab || binoptab == ior_optab || binoptab == xor_optab)
512 && class == MODE_INT
513 && GET_MODE_SIZE (mode) > UNITS_PER_WORD
514 && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
515 {
516 int i;
517 rtx insns;
518 rtx equiv_value;
519
520 /* If TARGET is the same as one of the operands, the REG_EQUAL note
521 won't be accurate, so use a new target. */
522 if (target == 0 || target == op0 || target == op1)
523 target = gen_reg_rtx (mode);
524
525 start_sequence ();
526
527 /* Do the actual arithmetic. */
528 for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)
529 {
530 rtx target_piece = operand_subword (target, i, 1, mode);
531 rtx x = expand_binop (word_mode, binoptab,
532 operand_subword_force (op0, i, mode),
533 operand_subword_force (op1, i, mode),
534 target_piece, unsignedp, methods);
535 if (target_piece != x)
536 emit_move_insn (target_piece, x);
537 }
538
539 insns = get_insns ();
540 end_sequence ();
541
542 if (binoptab->code != UNKNOWN)
543 equiv_value = gen_rtx (binoptab->code, mode, op0, op1);
544 else
545 equiv_value = 0;
546
547 emit_no_conflict_block (insns, target, op0, op1, equiv_value);
548 return target;
549 }
550
551 /* These can be done a word at a time by propagating carries. */
552 if ((binoptab == add_optab || binoptab == sub_optab)
553 && class == MODE_INT
554 && GET_MODE_SIZE (mode) >= 2 * UNITS_PER_WORD
555 && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
556 {
557 int i;
558 rtx carry_tmp = gen_reg_rtx (word_mode);
559 optab otheroptab = binoptab == add_optab ? sub_optab : add_optab;
560 int nwords = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
561 rtx carry_in, carry_out;
562 rtx xop0, xop1;
563
564 /* We can handle either a 1 or -1 value for the carry. If STORE_FLAG
565 value is one of those, use it. Otherwise, use 1 since it is the
566 one easiest to get. */
567#if STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1
568 int normalizep = STORE_FLAG_VALUE;
569#else
570 int normalizep = 1;
571#endif
572
573 /* Prepare the operands. */
574 xop0 = force_reg (mode, op0);
575 xop1 = force_reg (mode, op1);
576
577 if (target == 0 || GET_CODE (target) != REG
578 || target == xop0 || target == xop1)
579 target = gen_reg_rtx (mode);
580
581 /* Do the actual arithmetic. */
582 for (i = 0; i < nwords; i++)
583 {
584 int index = (WORDS_BIG_ENDIAN ? nwords - i - 1 : i);
585 rtx target_piece = operand_subword (target, index, 1, mode);
586 rtx op0_piece = operand_subword_force (xop0, index, mode);
587 rtx op1_piece = operand_subword_force (xop1, index, mode);
588 rtx x;
589
590 /* Main add/subtract of the input operands. */
591 x = expand_binop (word_mode, binoptab,
592 op0_piece, op1_piece,
593 target_piece, unsignedp, methods);
594 if (x == 0)
595 break;
596
597 if (i + 1 < nwords)
598 {
599 /* Store carry from main add/subtract. */
600 carry_out = gen_reg_rtx (word_mode);
601 carry_out = emit_store_flag (carry_out,
602 binoptab == add_optab ? LTU : GTU,
603 x, op0_piece,
604 word_mode, 1, normalizep);
605 if (!carry_out)
606 break;
607 }
608
609 if (i > 0)
610 {
611 /* Add/subtract previous carry to main result. */
612 x = expand_binop (word_mode,
613 normalizep == 1 ? binoptab : otheroptab,
614 x, carry_in,
615 target_piece, 1, methods);
616 if (target_piece != x)
617 emit_move_insn (target_piece, x);
618
619 if (i + 1 < nwords)
620 {
621 /* THIS CODE HAS NOT BEEN TESTED. */
622 /* Get out carry from adding/subtracting carry in. */
623 carry_tmp = emit_store_flag (carry_tmp,
624 binoptab == add_optab
625 ? LTU : GTU,
626 x, carry_in,
627 word_mode, 1, normalizep);
628 /* Logical-ior the two poss. carry together. */
629 carry_out = expand_binop (word_mode, ior_optab,
630 carry_out, carry_tmp,
631 carry_out, 0, methods);
632 if (!carry_out)
633 break;
634 }
635 }
636
637 carry_in = carry_out;
638 }
639
640 if (i == GET_MODE_BITSIZE (mode) / BITS_PER_WORD)
641 {
642 rtx temp;
643
644 temp = emit_move_insn (target, target);
645 REG_NOTES (temp) = gen_rtx (EXPR_LIST, REG_EQUAL,
646 gen_rtx (binoptab->code, mode, xop0, xop1),
647 REG_NOTES (temp));
648 return target;
649 }
650 else
651 delete_insns_since (last);
652 }
653
654 /* If we want to multiply two two-word values and have normal and widening
655 multiplies of single-word values, we can do this with three smaller
656 multiplications. Note that we do not make a REG_NO_CONFLICT block here
657 because we are not operating on one word at a time.
658
659 The multiplication proceeds as follows:
660 _______________________
661 [__op0_high_|__op0_low__]
662 _______________________
663 * [__op1_high_|__op1_low__]
664 _______________________________________________
665 _______________________
666 (1) [__op0_low__*__op1_low__]
667 _______________________
668 (2a) [__op0_low__*__op1_high_]
669 _______________________
670 (2b) [__op0_high_*__op1_low__]
671 _______________________
672 (3) [__op0_high_*__op1_high_]
673
674
675 This gives a 4-word result. Since we are only interested in the
676 lower 2 words, partial result (3) and the upper words of (2a) and
677 (2b) don't need to be calculated. Hence (2a) and (2b) can be
678 calculated using non-widening multiplication.
679
680 (1), however, needs to be calculated with an unsigned widening
681 multiplication. If this operation is not directly supported we
682 try using a signed widening multiplication and adjust the result.
683 This adjustment works as follows:
684
685 If both operands are positive then no adjustment is needed.
686
687 If the operands have different signs, for example op0_low < 0 and
688 op1_low >= 0, the instruction treats the most significant bit of
689 op0_low as a sign bit instead of a bit with significance
690 2**(BITS_PER_WORD-1), i.e. the instruction multiplies op1_low
691 with 2**BITS_PER_WORD - op0_low, and two's complements the
692 result. Conclusion: We need to add op1_low * 2**BITS_PER_WORD to
693 the result.
694
695 Similarly, if both operands are negative, we need to add
696 (op0_low + op1_low) * 2**BITS_PER_WORD.
697
698 We use a trick to adjust quickly. We logically shift op0_low right
699 (op1_low) BITS_PER_WORD-1 steps to get 0 or 1, and add this to
700 op0_high (op1_high) before it is used to calculate 2b (2a). If no
701 logical shift exists, we do an arithmetic right shift and subtract
702 the 0 or -1. */
703
704 if (binoptab == smul_optab
705 && class == MODE_INT
706 && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
707 && smul_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
708 && add_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
709 && ((umul_widen_optab->handlers[(int) mode].insn_code
710 != CODE_FOR_nothing)
711 || (smul_widen_optab->handlers[(int) mode].insn_code
712 != CODE_FOR_nothing)))
713 {
714 int low = (WORDS_BIG_ENDIAN ? 1 : 0);
715 int high = (WORDS_BIG_ENDIAN ? 0 : 1);
716 rtx op0_high = operand_subword_force (op0, high, mode);
717 rtx op0_low = operand_subword_force (op0, low, mode);
718 rtx op1_high = operand_subword_force (op1, high, mode);
719 rtx op1_low = operand_subword_force (op1, low, mode);
720 rtx product = 0;
721 rtx op0_xhigh;
722 rtx op1_xhigh;
723
724 /* If the target is the same as one of the inputs, don't use it. This
725 prevents problems with the REG_EQUAL note. */
726 if (target == op0 || target == op1)
727 target = 0;
728
729 /* Multiply the two lower words to get a double-word product.
730 If unsigned widening multiplication is available, use that;
731 otherwise use the signed form and compensate. */
732
733 if (umul_widen_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
734 {
735 product = expand_binop (mode, umul_widen_optab, op0_low, op1_low,
736 target, 1, OPTAB_DIRECT);
737
738 /* If we didn't succeed, delete everything we did so far. */
739 if (product == 0)
740 delete_insns_since (last);
741 else
742 op0_xhigh = op0_high, op1_xhigh = op1_high;
743 }
744
745 if (product == 0
746 && smul_widen_optab->handlers[(int) mode].insn_code
747 != CODE_FOR_nothing)
748 {
749 rtx wordm1 = GEN_INT (BITS_PER_WORD - 1);
750 product = expand_binop (mode, smul_widen_optab, op0_low, op1_low,
751 target, 1, OPTAB_DIRECT);
752 op0_xhigh = expand_binop (word_mode, lshr_optab, op0_low, wordm1,
753 NULL_RTX, 1, OPTAB_DIRECT);
754 if (op0_xhigh)
755 op0_xhigh = expand_binop (word_mode, add_optab, op0_high,
756 op0_xhigh, op0_xhigh, 0, OPTAB_DIRECT);
757 else
758 {
759 op0_xhigh = expand_binop (word_mode, ashr_optab, op0_low, wordm1,
760 NULL_RTX, 0, OPTAB_DIRECT);
761 if (op0_xhigh)
762 op0_xhigh = expand_binop (word_mode, sub_optab, op0_high,
763 op0_xhigh, op0_xhigh, 0,
764 OPTAB_DIRECT);
765 }
766
767 op1_xhigh = expand_binop (word_mode, lshr_optab, op1_low, wordm1,
768 NULL_RTX, 1, OPTAB_DIRECT);
769 if (op1_xhigh)
770 op1_xhigh = expand_binop (word_mode, add_optab, op1_high,
771 op1_xhigh, op1_xhigh, 0, OPTAB_DIRECT);
772 else
773 {
774 op1_xhigh = expand_binop (word_mode, ashr_optab, op1_low, wordm1,
775 NULL_RTX, 0, OPTAB_DIRECT);
776 if (op1_xhigh)
777 op1_xhigh = expand_binop (word_mode, sub_optab, op1_high,
778 op1_xhigh, op1_xhigh, 0,
779 OPTAB_DIRECT);
780 }
781 }
782
783 /* If we have been able to directly compute the product of the
784 low-order words of the operands and perform any required adjustments
785 of the operands, we proceed by trying two more multiplications
786 and then computing the appropriate sum.
787
788 We have checked above that the required addition is provided.
789 Full-word addition will normally always succeed, especially if
790 it is provided at all, so we don't worry about its failure. The
791 multiplication may well fail, however, so we do handle that. */
792
793 if (product && op0_xhigh && op1_xhigh)
794 {
795 rtx product_piece;
796 rtx product_high = operand_subword (product, high, 1, mode);
797 rtx temp = expand_binop (word_mode, binoptab, op0_low, op1_xhigh,
798 NULL_RTX, 0, OPTAB_DIRECT);
799
800 if (temp)
801 {
802 product_piece = expand_binop (word_mode, add_optab, temp,
803 product_high, product_high,
804 0, OPTAB_LIB_WIDEN);
805 if (product_piece != product_high)
806 emit_move_insn (product_high, product_piece);
807
808 temp = expand_binop (word_mode, binoptab, op1_low, op0_xhigh,
809 NULL_RTX, 0, OPTAB_DIRECT);
810
811 product_piece = expand_binop (word_mode, add_optab, temp,
812 product_high, product_high,
813 0, OPTAB_LIB_WIDEN);
814 if (product_piece != product_high)
815 emit_move_insn (product_high, product_piece);
816
817 temp = emit_move_insn (product, product);
818 REG_NOTES (temp) = gen_rtx (EXPR_LIST, REG_EQUAL,
819 gen_rtx (MULT, mode, op0, op1),
820 REG_NOTES (temp));
821
822 return product;
823 }
824 }
825
826 /* If we get here, we couldn't do it for some reason even though we
827 originally thought we could. Delete anything we've emitted in
828 trying to do it. */
829
830 delete_insns_since (last);
831 }
832
833 /* We need to open-code the complex type operations: '+, -, * and /' */
834
835 /* At this point we allow operations between two similar complex
836 numbers, and also if one of the operands is not a complex number
837 but rather of MODE_FLOAT or MODE_INT. However, the caller
838 must make sure that the MODE of the non-complex operand matches
839 the SUBMODE of the complex operand. */
840
841 if (class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT)
842 {
843 rtx real0 = (rtx) 0;
844 rtx imag0 = (rtx) 0;
845 rtx real1 = (rtx) 0;
846 rtx imag1 = (rtx) 0;
847 rtx realr;
848 rtx imagr;
849 rtx res;
850 rtx seq;
851 rtx equiv_value;
852
853 /* Find the correct mode for the real and imaginary parts */
854 enum machine_mode submode
855 = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT,
856 class == MODE_COMPLEX_INT ? MODE_INT : MODE_FLOAT,
857 0);
858
859 if (submode == BLKmode)
860 abort ();
861
862 if (! target)
863 target = gen_reg_rtx (mode);
864
865 start_sequence ();
866
867 realr = gen_realpart (submode, target);
868 imagr = gen_imagpart (submode, target);
869
870 if (GET_MODE (op0) == mode)
871 {
872 real0 = gen_realpart (submode, op0);
873 imag0 = gen_imagpart (submode, op0);
874 }
875 else
876 real0 = op0;
877
878 if (GET_MODE (op1) == mode)
879 {
880 real1 = gen_realpart (submode, op1);
881 imag1 = gen_imagpart (submode, op1);
882 }
883 else
884 real1 = op1;
885
886 if (! real0 || ! real1 || ! (imag0 || imag1))
887 abort ();
888
889 switch (binoptab->code)
890 {
891 case PLUS:
892 case MINUS:
893 res = expand_binop (submode, binoptab, real0, real1,
894 realr, unsignedp, methods);
895 if (res != realr)
896 emit_move_insn (realr, res);
897
898 if (imag0 && imag1)
899 res = expand_binop (submode, binoptab, imag0, imag1,
900 imagr, unsignedp, methods);
901 else if (imag0)
902 res = imag0;
903 else if (binoptab->code == MINUS)
904 res = expand_unop (submode, neg_optab, imag1, imagr, unsignedp);
905 else
906 res = imag1;
907
908 if (res != imagr)
909 emit_move_insn (imagr, res);
910 break;
911
912 case MULT:
913 /* (a+ib) * (c+id) = (ac-bd) + i(ad+cb) */
914
915 res = expand_binop (submode, binoptab, real0, real1,
916 realr, unsignedp, methods);
917
918 if (imag0 && imag1)
919 {
920 rtx temp =
921 expand_binop (submode, sub_optab, res,
922 expand_binop (submode, binoptab, imag0, imag1,
923 0, unsignedp, methods),
924 realr, unsignedp, methods);
925
926 if (temp != realr)
927 emit_move_insn (realr, temp);
928
929 res = expand_binop (submode, add_optab,
930 expand_binop (submode, binoptab,
931 real0, imag1,
932 0, unsignedp, methods),
933 expand_binop (submode, binoptab,
934 real1, imag0,
935 0, unsignedp, methods),
936 imagr, unsignedp, methods);
937 if (res != imagr)
938 emit_move_insn (imagr, res);
939 }
940 else
941 {
942 if (res != realr)
943 emit_move_insn (realr, res);
944
945 if (imag0)
946 res = expand_binop (submode, binoptab,
947 real1, imag0, imagr, unsignedp, methods);
948 else
949 res = expand_binop (submode, binoptab,
950 real0, imag1, imagr, unsignedp, methods);
951 if (res != imagr)
952 emit_move_insn (imagr, res);
953 }
954 break;
955
956 case DIV:
957 /* (c+id)/(a+ib) == ((c+id)*(a-ib))/(a*a+b*b) */
958
959 if (! imag1)
960 {
961 /* Simply divide the real and imaginary parts by `a' */
962 res = expand_binop (submode, binoptab, real0, real1,
963 realr, unsignedp, methods);
964 if (res != realr)
965 emit_move_insn (realr, res);
966
967 res = expand_binop (submode, binoptab, imag0, real1,
968 imagr, unsignedp, methods);
969 if (res != imagr)
970 emit_move_insn (imagr, res);
971 }
972 else /* Divisor is of complex type */
973 { /* X/(a+ib) */
974
975 rtx divisor;
976 rtx real_t;
977 rtx imag_t;
978
979 optab mulopt = unsignedp ? umul_widen_optab : smul_optab;
980
981 /* Divisor: c*c + d*d */
982 divisor = expand_binop (submode, add_optab,
983 expand_binop (submode, mulopt,
984 real1, real1,
985 0, unsignedp, methods),
986 expand_binop (submode, mulopt,
987 imag1, imag1,
988 0, unsignedp, methods),
989 0, unsignedp, methods);
990
991 if (! imag0) /* ((a)(c-id))/divisor */
992 { /* (a+i0) / (c+id) = (ac/(cc+dd)) + i(-ad/(cc+dd)) */
993 /* Calculate the dividend */
994 real_t = expand_binop (submode, mulopt, real0, real1,
995 0, unsignedp, methods);
996
997 imag_t
998 = expand_unop (submode, neg_optab,
999 expand_binop (submode, mulopt, real0, imag1,
1000 0, unsignedp, methods),
1001 0, unsignedp);
1002 }
1003 else /* ((a+ib)(c-id))/divider */
1004 {
1005 /* Calculate the dividend */
1006 real_t = expand_binop (submode, add_optab,
1007 expand_binop (submode, mulopt,
1008 real0, real1,
1009 0, unsignedp, methods),
1010 expand_binop (submode, mulopt,
1011 imag0, imag1,
1012 0, unsignedp, methods),
1013 0, unsignedp, methods);
1014
1015 imag_t = expand_binop (submode, sub_optab,
1016 expand_binop (submode, mulopt,
1017 imag0, real1,
1018 0, unsignedp, methods),
1019 expand_binop (submode, mulopt,
1020 real0, imag1,
1021 0, unsignedp, methods),
1022 0, unsignedp, methods);
1023
1024 }
1025
1026 res = expand_binop (submode, binoptab, real_t, divisor,
1027 realr, unsignedp, methods);
1028 if (res != realr)
1029 emit_move_insn (realr, res);
1030
1031 res = expand_binop (submode, binoptab, imag_t, divisor,
1032 imagr, unsignedp, methods);
1033 if (res != imagr)
1034 emit_move_insn (imagr, res);
1035 }
1036 break;
1037
1038 default:
1039 abort ();
1040 }
1041
1042 seq = get_insns ();
1043 end_sequence ();
1044
1045 if (binoptab->code != UNKNOWN)
1046 equiv_value = gen_rtx (binoptab->code, mode, op0, op1);
1047 else
1048 equiv_value = 0;
1049
1050 emit_no_conflict_block (seq, target, op0, op1, equiv_value);
1051
1052 return target;
1053 }
1054
1055 /* It can't be open-coded in this mode.
1056 Use a library call if one is available and caller says that's ok. */
1057
1058 if (binoptab->handlers[(int) mode].libfunc
1059 && (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN))
1060 {
1061 rtx insns;
1062 rtx funexp = binoptab->handlers[(int) mode].libfunc;
1063 rtx op1x = op1;
1064 enum machine_mode op1_mode = mode;
1065
1066 start_sequence ();
1067
1068 if (shift_op)
1069 {
1070 op1_mode = word_mode;
1071 /* Specify unsigned here,
1072 since negative shift counts are meaningless. */
1073 op1x = convert_to_mode (word_mode, op1, 1);
1074 }
1075
1076 /* Pass 1 for NO_QUEUE so we don't lose any increments
1077 if the libcall is cse'd or moved. */
1078 emit_library_call (binoptab->handlers[(int) mode].libfunc,
1079 1, mode, 2, op0, mode, op1x, op1_mode);
1080
1081 insns = get_insns ();
1082 end_sequence ();
1083
1084 target = gen_reg_rtx (mode);
1085 emit_libcall_block (insns, target, hard_libcall_value (mode),
1086 gen_rtx (binoptab->code, mode, op0, op1));
1087
1088 return target;
1089 }
1090
1091 delete_insns_since (last);
1092
1093 /* It can't be done in this mode. Can we do it in a wider mode? */
1094
1095 if (! (methods == OPTAB_WIDEN || methods == OPTAB_LIB_WIDEN
1096 || methods == OPTAB_MUST_WIDEN))
1097 {
1098 /* Caller says, don't even try. */
1099 delete_insns_since (entry_last);
1100 return 0;
1101 }
1102
1103 /* Compute the value of METHODS to pass to recursive calls.
1104 Don't allow widening to be tried recursively. */
1105
1106 methods = (methods == OPTAB_LIB_WIDEN ? OPTAB_LIB : OPTAB_DIRECT);
1107
1108 /* Look for a wider mode of the same class for which it appears we can do
1109 the operation. */
1110
1111 if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
1112 {
1113 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
1114 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
1115 {
1116 if ((binoptab->handlers[(int) wider_mode].insn_code
1117 != CODE_FOR_nothing)
1118 || (methods == OPTAB_LIB
1119 && binoptab->handlers[(int) wider_mode].libfunc))
1120 {
1121 rtx xop0 = op0, xop1 = op1;
1122 int no_extend = 0;
1123
1124 /* For certain integer operations, we need not actually extend
1125 the narrow operands, as long as we will truncate
1126 the results to the same narrowness. Don't do this when
1127 WIDER_MODE is wider than a word since a paradoxical SUBREG
1128 isn't valid for such modes. */
1129
1130 if ((binoptab == ior_optab || binoptab == and_optab
1131 || binoptab == xor_optab
1132 || binoptab == add_optab || binoptab == sub_optab
1133 || binoptab == smul_optab
1134 || binoptab == ashl_optab || binoptab == lshl_optab)
1135 && class == MODE_INT
1136 && GET_MODE_SIZE (wider_mode) <= UNITS_PER_WORD)
1137 no_extend = 1;
1138
1139 /* If an operand is a constant integer, we might as well
1140 convert it since that is more efficient than using a SUBREG,
1141 unlike the case for other operands. Similarly for
1142 SUBREGs that were made due to promoted objects.*/
1143
1144 if (no_extend && GET_MODE (xop0) != VOIDmode
1145 && ! (GET_CODE (xop0) == SUBREG
1146 && SUBREG_PROMOTED_VAR_P (xop0)))
1147 xop0 = gen_rtx (SUBREG, wider_mode,
1148 force_reg (GET_MODE (xop0), xop0), 0);
1149 else
1150 xop0 = convert_to_mode (wider_mode, xop0, unsignedp);
1151
1152 if (no_extend && GET_MODE (xop1) != VOIDmode
1153 && ! (GET_CODE (xop1) == SUBREG
1154 && SUBREG_PROMOTED_VAR_P (xop1)))
1155 xop1 = gen_rtx (SUBREG, wider_mode,
1156 force_reg (GET_MODE (xop1), xop1), 0);
1157 else
1158 xop1 = convert_to_mode (wider_mode, xop1, unsignedp);
1159
1160 temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX,
1161 unsignedp, methods);
1162 if (temp)
1163 {
1164 if (class != MODE_INT)
1165 {
1166 if (target == 0)
1167 target = gen_reg_rtx (mode);
1168 convert_move (target, temp, 0);
1169 return target;
1170 }
1171 else
1172 return gen_lowpart (mode, temp);
1173 }
1174 else
1175 delete_insns_since (last);
1176 }
1177 }
1178 }
1179
1180 delete_insns_since (entry_last);
1181 return 0;
1182}
1183\f
1184/* Expand a binary operator which has both signed and unsigned forms.
1185 UOPTAB is the optab for unsigned operations, and SOPTAB is for
1186 signed operations.
1187
1188 If we widen unsigned operands, we may use a signed wider operation instead
1189 of an unsigned wider operation, since the result would be the same. */
1190
1191rtx
1192sign_expand_binop (mode, uoptab, soptab, op0, op1, target, unsignedp, methods)
1193 enum machine_mode mode;
1194 optab uoptab, soptab;
1195 rtx op0, op1, target;
1196 int unsignedp;
1197 enum optab_methods methods;
1198{
1199 register rtx temp;
1200 optab direct_optab = unsignedp ? uoptab : soptab;
1201 struct optab wide_soptab;
1202
1203 /* Do it without widening, if possible. */
1204 temp = expand_binop (mode, direct_optab, op0, op1, target,
1205 unsignedp, OPTAB_DIRECT);
1206 if (temp || methods == OPTAB_DIRECT)
1207 return temp;
1208
1209 /* Try widening to a signed int. Make a fake signed optab that
1210 hides any signed insn for direct use. */
1211 wide_soptab = *soptab;
1212 wide_soptab.handlers[(int) mode].insn_code = CODE_FOR_nothing;
1213 wide_soptab.handlers[(int) mode].libfunc = 0;
1214
1215 temp = expand_binop (mode, &wide_soptab, op0, op1, target,
1216 unsignedp, OPTAB_WIDEN);
1217
1218 /* For unsigned operands, try widening to an unsigned int. */
1219 if (temp == 0 && unsignedp)
1220 temp = expand_binop (mode, uoptab, op0, op1, target,
1221 unsignedp, OPTAB_WIDEN);
1222 if (temp || methods == OPTAB_WIDEN)
1223 return temp;
1224
1225 /* Use the right width lib call if that exists. */
1226 temp = expand_binop (mode, direct_optab, op0, op1, target, unsignedp, OPTAB_LIB);
1227 if (temp || methods == OPTAB_LIB)
1228 return temp;
1229
1230 /* Must widen and use a lib call, use either signed or unsigned. */
1231 temp = expand_binop (mode, &wide_soptab, op0, op1, target,
1232 unsignedp, methods);
1233 if (temp != 0)
1234 return temp;
1235 if (unsignedp)
1236 return expand_binop (mode, uoptab, op0, op1, target,
1237 unsignedp, methods);
1238 return 0;
1239}
1240\f
1241/* Generate code to perform an operation specified by BINOPTAB
1242 on operands OP0 and OP1, with two results to TARG1 and TARG2.
1243 We assume that the order of the operands for the instruction
1244 is TARG0, OP0, OP1, TARG1, which would fit a pattern like
1245 [(set TARG0 (operate OP0 OP1)) (set TARG1 (operate ...))].
1246
1247 Either TARG0 or TARG1 may be zero, but what that means is that
1248 that result is not actually wanted. We will generate it into
1249 a dummy pseudo-reg and discard it. They may not both be zero.
1250
1251 Returns 1 if this operation can be performed; 0 if not. */
1252
1253int
1254expand_twoval_binop (binoptab, op0, op1, targ0, targ1, unsignedp)
1255 optab binoptab;
1256 rtx op0, op1;
1257 rtx targ0, targ1;
1258 int unsignedp;
1259{
1260 enum machine_mode mode = GET_MODE (targ0 ? targ0 : targ1);
1261 enum mode_class class;
1262 enum machine_mode wider_mode;
1263 rtx entry_last = get_last_insn ();
1264 rtx last;
1265
1266 class = GET_MODE_CLASS (mode);
1267
1268 op0 = protect_from_queue (op0, 0);
1269 op1 = protect_from_queue (op1, 0);
1270
1271 if (flag_force_mem)
1272 {
1273 op0 = force_not_mem (op0);
1274 op1 = force_not_mem (op1);
1275 }
1276
1277 /* If we are inside an appropriately-short loop and one operand is an
1278 expensive constant, force it into a register. */
1279 if (CONSTANT_P (op0) && preserve_subexpressions_p ()
1280 && rtx_cost (op0, binoptab->code) > 2)
1281 op0 = force_reg (mode, op0);
1282
1283 if (CONSTANT_P (op1) && preserve_subexpressions_p ()
1284 && rtx_cost (op1, binoptab->code) > 2)
1285 op1 = force_reg (mode, op1);
1286
1287 if (targ0)
1288 targ0 = protect_from_queue (targ0, 1);
1289 else
1290 targ0 = gen_reg_rtx (mode);
1291 if (targ1)
1292 targ1 = protect_from_queue (targ1, 1);
1293 else
1294 targ1 = gen_reg_rtx (mode);
1295
1296 /* Record where to go back to if we fail. */
1297 last = get_last_insn ();
1298
1299 if (binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1300 {
1301 int icode = (int) binoptab->handlers[(int) mode].insn_code;
1302 enum machine_mode mode0 = insn_operand_mode[icode][1];
1303 enum machine_mode mode1 = insn_operand_mode[icode][2];
1304 rtx pat;
1305 rtx xop0 = op0, xop1 = op1;
1306
1307 /* In case this insn wants input operands in modes different from the
1308 result, convert the operands. */
1309 if (GET_MODE (op0) != VOIDmode && GET_MODE (op0) != mode0)
1310 xop0 = convert_to_mode (mode0, xop0, unsignedp);
1311
1312 if (GET_MODE (op1) != VOIDmode && GET_MODE (op1) != mode1)
1313 xop1 = convert_to_mode (mode1, xop1, unsignedp);
1314
1315 /* Now, if insn doesn't accept these operands, put them into pseudos. */
1316 if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))
1317 xop0 = copy_to_mode_reg (mode0, xop0);
1318
1319 if (! (*insn_operand_predicate[icode][2]) (xop1, mode1))
1320 xop1 = copy_to_mode_reg (mode1, xop1);
1321
1322 /* We could handle this, but we should always be called with a pseudo
1323 for our targets and all insns should take them as outputs. */
1324 if (! (*insn_operand_predicate[icode][0]) (targ0, mode)
1325 || ! (*insn_operand_predicate[icode][3]) (targ1, mode))
1326 abort ();
1327
1328 pat = GEN_FCN (icode) (targ0, xop0, xop1, targ1);
1329 if (pat)
1330 {
1331 emit_insn (pat);
1332 return 1;
1333 }
1334 else
1335 delete_insns_since (last);
1336 }
1337
1338 /* It can't be done in this mode. Can we do it in a wider mode? */
1339
1340 if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
1341 {
1342 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
1343 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
1344 {
1345 if (binoptab->handlers[(int) wider_mode].insn_code
1346 != CODE_FOR_nothing)
1347 {
1348 register rtx t0 = gen_reg_rtx (wider_mode);
1349 register rtx t1 = gen_reg_rtx (wider_mode);
1350
1351 if (expand_twoval_binop (binoptab,
1352 convert_to_mode (wider_mode, op0,
1353 unsignedp),
1354 convert_to_mode (wider_mode, op1,
1355 unsignedp),
1356 t0, t1, unsignedp))
1357 {
1358 convert_move (targ0, t0, unsignedp);
1359 convert_move (targ1, t1, unsignedp);
1360 return 1;
1361 }
1362 else
1363 delete_insns_since (last);
1364 }
1365 }
1366 }
1367
1368 delete_insns_since (entry_last);
1369 return 0;
1370}
1371\f
1372/* Generate code to perform an operation specified by UNOPTAB
1373 on operand OP0, with result having machine-mode MODE.
1374
1375 UNSIGNEDP is for the case where we have to widen the operands
1376 to perform the operation. It says to use zero-extension.
1377
1378 If TARGET is nonzero, the value
1379 is generated there, if it is convenient to do so.
1380 In all cases an rtx is returned for the locus of the value;
1381 this may or may not be TARGET. */
1382
1383rtx
1384expand_unop (mode, unoptab, op0, target, unsignedp)
1385 enum machine_mode mode;
1386 optab unoptab;
1387 rtx op0;
1388 rtx target;
1389 int unsignedp;
1390{
1391 enum mode_class class;
1392 enum machine_mode wider_mode;
1393 register rtx temp;
1394 rtx last = get_last_insn ();
1395 rtx pat;
1396
1397 class = GET_MODE_CLASS (mode);
1398
1399 op0 = protect_from_queue (op0, 0);
1400
1401 if (flag_force_mem)
1402 {
1403 op0 = force_not_mem (op0);
1404 }
1405
1406 if (target)
1407 target = protect_from_queue (target, 1);
1408
1409 if (unoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1410 {
1411 int icode = (int) unoptab->handlers[(int) mode].insn_code;
1412 enum machine_mode mode0 = insn_operand_mode[icode][1];
1413 rtx xop0 = op0;
1414
1415 if (target)
1416 temp = target;
1417 else
1418 temp = gen_reg_rtx (mode);
1419
1420 if (GET_MODE (xop0) != VOIDmode
1421 && GET_MODE (xop0) != mode0)
1422 xop0 = convert_to_mode (mode0, xop0, unsignedp);
1423
1424 /* Now, if insn doesn't accept our operand, put it into a pseudo. */
1425
1426 if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))
1427 xop0 = copy_to_mode_reg (mode0, xop0);
1428
1429 if (! (*insn_operand_predicate[icode][0]) (temp, mode))
1430 temp = gen_reg_rtx (mode);
1431
1432 pat = GEN_FCN (icode) (temp, xop0);
1433 if (pat)
1434 {
1435 if (GET_CODE (pat) == SEQUENCE
1436 && ! add_equal_note (pat, temp, unoptab->code, xop0, NULL_RTX))
1437 {
1438 delete_insns_since (last);
1439 return expand_unop (mode, unoptab, op0, NULL_RTX, unsignedp);
1440 }
1441
1442 emit_insn (pat);
1443
1444 return temp;
1445 }
1446 else
1447 delete_insns_since (last);
1448 }
1449
1450 /* It can't be done in this mode. Can we open-code it in a wider mode? */
1451
1452 if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
1453 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
1454 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
1455 {
1456 if (unoptab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing)
1457 {
1458 rtx xop0 = op0;
1459
1460 /* For certain operations, we need not actually extend
1461 the narrow operand, as long as we will truncate the
1462 results to the same narrowness. But it is faster to
1463 convert a SUBREG due to mode promotion. */
1464
1465 if ((unoptab == neg_optab || unoptab == one_cmpl_optab)
1466 && GET_MODE_SIZE (wider_mode) <= UNITS_PER_WORD
1467 && class == MODE_INT
1468 && ! (GET_CODE (xop0) == SUBREG
1469 && SUBREG_PROMOTED_VAR_P (xop0)))
1470 xop0 = gen_rtx (SUBREG, wider_mode, force_reg (mode, xop0), 0);
1471 else
1472 xop0 = convert_to_mode (wider_mode, xop0, unsignedp);
1473
1474 temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
1475 unsignedp);
1476
1477 if (temp)
1478 {
1479 if (class != MODE_INT)
1480 {
1481 if (target == 0)
1482 target = gen_reg_rtx (mode);
1483 convert_move (target, temp, 0);
1484 return target;
1485 }
1486 else
1487 return gen_lowpart (mode, temp);
1488 }
1489 else
1490 delete_insns_since (last);
1491 }
1492 }
1493
1494 /* These can be done a word at a time. */
1495 if (unoptab == one_cmpl_optab
1496 && class == MODE_INT
1497 && GET_MODE_SIZE (mode) > UNITS_PER_WORD
1498 && unoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
1499 {
1500 int i;
1501 rtx insns;
1502
1503 if (target == 0 || target == op0)
1504 target = gen_reg_rtx (mode);
1505
1506 start_sequence ();
1507
1508 /* Do the actual arithmetic. */
1509 for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)
1510 {
1511 rtx target_piece = operand_subword (target, i, 1, mode);
1512 rtx x = expand_unop (word_mode, unoptab,
1513 operand_subword_force (op0, i, mode),
1514 target_piece, unsignedp);
1515 if (target_piece != x)
1516 emit_move_insn (target_piece, x);
1517 }
1518
1519 insns = get_insns ();
1520 end_sequence ();
1521
1522 emit_no_conflict_block (insns, target, op0, NULL_RTX,
1523 gen_rtx (unoptab->code, mode, op0));
1524 return target;
1525 }
1526
1527 /* Open-code the complex negation operation. */
1528 else if (unoptab == neg_optab
1529 && (class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT))
1530 {
1531 rtx target_piece;
1532 rtx x;
1533 rtx seq;
1534
1535 /* Find the correct mode for the real and imaginary parts */
1536 enum machine_mode submode
1537 = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT,
1538 class == MODE_COMPLEX_INT ? MODE_INT : MODE_FLOAT,
1539 0);
1540
1541 if (submode == BLKmode)
1542 abort ();
1543
1544 if (target == 0)
1545 target = gen_reg_rtx (mode);
1546
1547 start_sequence ();
1548
1549 target_piece = gen_imagpart (submode, target);
1550 x = expand_unop (submode, unoptab,
1551 gen_imagpart (submode, op0),
1552 target_piece, unsignedp);
1553 if (target_piece != x)
1554 emit_move_insn (target_piece, x);
1555
1556 target_piece = gen_realpart (submode, target);
1557 x = expand_unop (submode, unoptab,
1558 gen_realpart (submode, op0),
1559 target_piece, unsignedp);
1560 if (target_piece != x)
1561 emit_move_insn (target_piece, x);
1562
1563 seq = get_insns ();
1564 end_sequence ();
1565
1566 emit_no_conflict_block (seq, target, op0, 0,
1567 gen_rtx (unoptab->code, mode, op0));
1568 return target;
1569 }
1570
1571 /* Now try a library call in this mode. */
1572 if (unoptab->handlers[(int) mode].libfunc)
1573 {
1574 rtx insns;
1575 rtx funexp = unoptab->handlers[(int) mode].libfunc;
1576
1577 start_sequence ();
1578
1579 /* Pass 1 for NO_QUEUE so we don't lose any increments
1580 if the libcall is cse'd or moved. */
1581 emit_library_call (unoptab->handlers[(int) mode].libfunc,
1582 1, mode, 1, op0, mode);
1583 insns = get_insns ();
1584 end_sequence ();
1585
1586 target = gen_reg_rtx (mode);
1587 emit_libcall_block (insns, target, hard_libcall_value (mode),
1588 gen_rtx (unoptab->code, mode, op0));
1589
1590 return target;
1591 }
1592
1593 /* It can't be done in this mode. Can we do it in a wider mode? */
1594
1595 if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
1596 {
1597 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
1598 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
1599 {
1600 if ((unoptab->handlers[(int) wider_mode].insn_code
1601 != CODE_FOR_nothing)
1602 || unoptab->handlers[(int) wider_mode].libfunc)
1603 {
1604 rtx xop0 = op0;
1605
1606 /* For certain operations, we need not actually extend
1607 the narrow operand, as long as we will truncate the
1608 results to the same narrowness. */
1609
1610 if ((unoptab == neg_optab || unoptab == one_cmpl_optab)
1611 && GET_MODE_SIZE (wider_mode) <= UNITS_PER_WORD
1612 && class == MODE_INT
1613 && ! (GET_CODE (xop0) == SUBREG
1614 && SUBREG_PROMOTED_VAR_P (xop0)))
1615 xop0 = gen_rtx (SUBREG, wider_mode, force_reg (mode, xop0), 0);
1616 else
1617 xop0 = convert_to_mode (wider_mode, xop0, unsignedp);
1618
1619 temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
1620 unsignedp);
1621
1622 if (temp)
1623 {
1624 if (class != MODE_INT)
1625 {
1626 if (target == 0)
1627 target = gen_reg_rtx (mode);
1628 convert_move (target, temp, 0);
1629 return target;
1630 }
1631 else
1632 return gen_lowpart (mode, temp);
1633 }
1634 else
1635 delete_insns_since (last);
1636 }
1637 }
1638 }
1639
1640 return 0;
1641}
1642\f
1643/* Emit code to compute the absolute value of OP0, with result to
1644 TARGET if convenient. (TARGET may be 0.) The return value says
1645 where the result actually is to be found.
1646
1647 MODE is the mode of the operand; the mode of the result is
1648 different but can be deduced from MODE.
1649
1650 UNSIGNEDP is relevant for complex integer modes. */
1651
1652rtx
1653expand_complex_abs (mode, op0, target, unsignedp)
1654 enum machine_mode mode;
1655 rtx op0;
1656 rtx target;
1657 int unsignedp;
1658{
1659 enum mode_class class = GET_MODE_CLASS (mode);
1660 enum machine_mode wider_mode;
1661 register rtx temp;
1662 rtx entry_last = get_last_insn ();
1663 rtx last;
1664 rtx pat;
1665
1666 /* Find the correct mode for the real and imaginary parts. */
1667 enum machine_mode submode
1668 = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT,
1669 class == MODE_COMPLEX_INT ? MODE_INT : MODE_FLOAT,
1670 0);
1671
1672 if (submode == BLKmode)
1673 abort ();
1674
1675 op0 = protect_from_queue (op0, 0);
1676
1677 if (flag_force_mem)
1678 {
1679 op0 = force_not_mem (op0);
1680 }
1681
1682 last = get_last_insn ();
1683
1684 if (target)
1685 target = protect_from_queue (target, 1);
1686
1687 if (abs_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1688 {
1689 int icode = (int) abs_optab->handlers[(int) mode].insn_code;
1690 enum machine_mode mode0 = insn_operand_mode[icode][1];
1691 rtx xop0 = op0;
1692
1693 if (target)
1694 temp = target;
1695 else
1696 temp = gen_reg_rtx (submode);
1697
1698 if (GET_MODE (xop0) != VOIDmode
1699 && GET_MODE (xop0) != mode0)
1700 xop0 = convert_to_mode (mode0, xop0, unsignedp);
1701
1702 /* Now, if insn doesn't accept our operand, put it into a pseudo. */
1703
1704 if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))
1705 xop0 = copy_to_mode_reg (mode0, xop0);
1706
1707 if (! (*insn_operand_predicate[icode][0]) (temp, submode))
1708 temp = gen_reg_rtx (submode);
1709
1710 pat = GEN_FCN (icode) (temp, xop0);
1711 if (pat)
1712 {
1713 if (GET_CODE (pat) == SEQUENCE
1714 && ! add_equal_note (pat, temp, abs_optab->code, xop0, NULL_RTX))
1715 {
1716 delete_insns_since (last);
1717 return expand_unop (mode, abs_optab, op0, NULL_RTX, unsignedp);
1718 }
1719
1720 emit_insn (pat);
1721
1722 return temp;
1723 }
1724 else
1725 delete_insns_since (last);
1726 }
1727
1728 /* It can't be done in this mode. Can we open-code it in a wider mode? */
1729
1730 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
1731 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
1732 {
1733 if (abs_optab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing)
1734 {
1735 rtx xop0 = op0;
1736
1737 xop0 = convert_to_mode (wider_mode, xop0, unsignedp);
1738 temp = expand_complex_abs (wider_mode, xop0, NULL_RTX, unsignedp);
1739
1740 if (temp)
1741 {
1742 if (class != MODE_COMPLEX_INT)
1743 {
1744 if (target == 0)
1745 target = gen_reg_rtx (submode);
1746 convert_move (target, temp, 0);
1747 return target;
1748 }
1749 else
1750 return gen_lowpart (submode, temp);
1751 }
1752 else
1753 delete_insns_since (last);
1754 }
1755 }
1756
1757 /* Open-code the complex absolute-value operation
1758 if we can open-code sqrt. Otherwise it's not worth while. */
1759 if (sqrt_optab->handlers[(int) submode].insn_code != CODE_FOR_nothing)
1760 {
1761 rtx real, imag, total;
1762
1763 real = gen_realpart (submode, op0);
1764 imag = gen_imagpart (submode, op0);
1765 /* Square both parts. */
1766 real = expand_mult (mode, real, real, NULL_RTX, 0);
1767 imag = expand_mult (mode, imag, imag, NULL_RTX, 0);
1768 /* Sum the parts. */
1769 total = expand_binop (submode, add_optab, real, imag, 0,
1770 0, OPTAB_LIB_WIDEN);
1771 /* Get sqrt in TARGET. Set TARGET to where the result is. */
1772 target = expand_unop (submode, sqrt_optab, total, target, 0);
1773 if (target == 0)
1774 delete_insns_since (last);
1775 else
1776 return target;
1777 }
1778
1779 /* Now try a library call in this mode. */
1780 if (abs_optab->handlers[(int) mode].libfunc)
1781 {
1782 rtx insns;
1783 rtx funexp = abs_optab->handlers[(int) mode].libfunc;
1784
1785 start_sequence ();
1786
1787 /* Pass 1 for NO_QUEUE so we don't lose any increments
1788 if the libcall is cse'd or moved. */
1789 emit_library_call (abs_optab->handlers[(int) mode].libfunc,
1790 1, mode, 1, op0, mode);
1791 insns = get_insns ();
1792 end_sequence ();
1793
1794 target = gen_reg_rtx (submode);
1795 emit_libcall_block (insns, target, hard_libcall_value (submode),
1796 gen_rtx (abs_optab->code, mode, op0));
1797
1798 return target;
1799 }
1800
1801 /* It can't be done in this mode. Can we do it in a wider mode? */
1802
1803 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
1804 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
1805 {
1806 if ((abs_optab->handlers[(int) wider_mode].insn_code
1807 != CODE_FOR_nothing)
1808 || abs_optab->handlers[(int) wider_mode].libfunc)
1809 {
1810 rtx xop0 = op0;
1811
1812 xop0 = convert_to_mode (wider_mode, xop0, unsignedp);
1813
1814 temp = expand_complex_abs (wider_mode, xop0, NULL_RTX, unsignedp);
1815
1816 if (temp)
1817 {
1818 if (class != MODE_COMPLEX_INT)
1819 {
1820 if (target == 0)
1821 target = gen_reg_rtx (submode);
1822 convert_move (target, temp, 0);
1823 return target;
1824 }
1825 else
1826 return gen_lowpart (submode, temp);
1827 }
1828 else
1829 delete_insns_since (last);
1830 }
1831 }
1832
1833 delete_insns_since (entry_last);
1834 return 0;
1835}
1836\f
1837/* Generate an instruction whose insn-code is INSN_CODE,
1838 with two operands: an output TARGET and an input OP0.
1839 TARGET *must* be nonzero, and the output is always stored there.
1840 CODE is an rtx code such that (CODE OP0) is an rtx that describes
1841 the value that is stored into TARGET. */
1842
1843void
1844emit_unop_insn (icode, target, op0, code)
1845 int icode;
1846 rtx target;
1847 rtx op0;
1848 enum rtx_code code;
1849{
1850 register rtx temp;
1851 enum machine_mode mode0 = insn_operand_mode[icode][1];
1852 rtx pat;
1853
1854 temp = target = protect_from_queue (target, 1);
1855
1856 op0 = protect_from_queue (op0, 0);
1857
1858 if (flag_force_mem)
1859 op0 = force_not_mem (op0);
1860
1861 /* Now, if insn does not accept our operands, put them into pseudos. */
1862
1863 if (! (*insn_operand_predicate[icode][1]) (op0, mode0))
1864 op0 = copy_to_mode_reg (mode0, op0);
1865
1866 if (! (*insn_operand_predicate[icode][0]) (temp, GET_MODE (temp))
1867 || (flag_force_mem && GET_CODE (temp) == MEM))
1868 temp = gen_reg_rtx (GET_MODE (temp));
1869
1870 pat = GEN_FCN (icode) (temp, op0);
1871
1872 if (GET_CODE (pat) == SEQUENCE && code != UNKNOWN)
1873 add_equal_note (pat, temp, code, op0, NULL_RTX);
1874
1875 emit_insn (pat);
1876
1877 if (temp != target)
1878 emit_move_insn (target, temp);
1879}
1880\f
1881/* Emit code to perform a series of operations on a multi-word quantity, one
1882 word at a time.
1883
1884 Such a block is preceded by a CLOBBER of the output, consists of multiple
1885 insns, each setting one word of the output, and followed by a SET copying
1886 the output to itself.
1887
1888 Each of the insns setting words of the output receives a REG_NO_CONFLICT
1889 note indicating that it doesn't conflict with the (also multi-word)
1890 inputs. The entire block is surrounded by REG_LIBCALL and REG_RETVAL
1891 notes.
1892
1893 INSNS is a block of code generated to perform the operation, not including
1894 the CLOBBER and final copy. All insns that compute intermediate values
1895 are first emitted, followed by the block as described above. Only
1896 INSNs are allowed in the block; no library calls or jumps may be
1897 present.
1898
1899 TARGET, OP0, and OP1 are the output and inputs of the operations,
1900 respectively. OP1 may be zero for a unary operation.
1901
1902 EQUIV, if non-zero, is an expression to be placed into a REG_EQUAL note
1903 on the last insn.
1904
1905 If TARGET is not a register, INSNS is simply emitted with no special
1906 processing.
1907
1908 The final insn emitted is returned. */
1909
1910rtx
1911emit_no_conflict_block (insns, target, op0, op1, equiv)
1912 rtx insns;
1913 rtx target;
1914 rtx op0, op1;
1915 rtx equiv;
1916{
1917 rtx prev, next, first, last, insn;
1918
1919 if (GET_CODE (target) != REG || reload_in_progress)
1920 return emit_insns (insns);
1921
1922 /* First emit all insns that do not store into words of the output and remove
1923 these from the list. */
1924 for (insn = insns; insn; insn = next)
1925 {
1926 rtx set = 0;
1927 int i;
1928
1929 next = NEXT_INSN (insn);
1930
1931 if (GET_CODE (insn) != INSN)
1932 abort ();
1933
1934 if (GET_CODE (PATTERN (insn)) == SET)
1935 set = PATTERN (insn);
1936 else if (GET_CODE (PATTERN (insn)) == PARALLEL)
1937 {
1938 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
1939 if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET)
1940 {
1941 set = XVECEXP (PATTERN (insn), 0, i);
1942 break;
1943 }
1944 }
1945
1946 if (set == 0)
1947 abort ();
1948
1949 if (! reg_overlap_mentioned_p (target, SET_DEST (set)))
1950 {
1951 if (PREV_INSN (insn))
1952 NEXT_INSN (PREV_INSN (insn)) = next;
1953 else
1954 insns = next;
1955
1956 if (next)
1957 PREV_INSN (next) = PREV_INSN (insn);
1958
1959 add_insn (insn);
1960 }
1961 }
1962
1963 prev = get_last_insn ();
1964
1965 /* Now write the CLOBBER of the output, followed by the setting of each
1966 of the words, followed by the final copy. */
1967 if (target != op0 && target != op1)
1968 emit_insn (gen_rtx (CLOBBER, VOIDmode, target));
1969
1970 for (insn = insns; insn; insn = next)
1971 {
1972 next = NEXT_INSN (insn);
1973 add_insn (insn);
1974
1975 if (op1 && GET_CODE (op1) == REG)
1976 REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_NO_CONFLICT, op1,
1977 REG_NOTES (insn));
1978
1979 if (op0 && GET_CODE (op0) == REG)
1980 REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_NO_CONFLICT, op0,
1981 REG_NOTES (insn));
1982 }
1983
1984 last = emit_move_insn (target, target);
1985 if (equiv)
1986 REG_NOTES (last) = gen_rtx (EXPR_LIST, REG_EQUAL, equiv, REG_NOTES (last));
1987
1988 if (prev == 0)
1989 first = get_insns ();
1990 else
1991 first = NEXT_INSN (prev);
1992
1993 /* Encapsulate the block so it gets manipulated as a unit. */
1994 REG_NOTES (first) = gen_rtx (INSN_LIST, REG_LIBCALL, last,
1995 REG_NOTES (first));
1996 REG_NOTES (last) = gen_rtx (INSN_LIST, REG_RETVAL, first, REG_NOTES (last));
1997
1998 return last;
1999}
2000\f
2001/* Emit code to make a call to a constant function or a library call.
2002
2003 INSNS is a list containing all insns emitted in the call.
2004 These insns leave the result in RESULT. Our block is to copy RESULT
2005 to TARGET, which is logically equivalent to EQUIV.
2006
2007 We first emit any insns that set a pseudo on the assumption that these are
2008 loading constants into registers; doing so allows them to be safely cse'ed
2009 between blocks. Then we emit all the other insns in the block, followed by
2010 an insn to move RESULT to TARGET. This last insn will have a REQ_EQUAL
2011 note with an operand of EQUIV.
2012
2013 Moving assignments to pseudos outside of the block is done to improve
2014 the generated code, but is not required to generate correct code,
2015 hence being unable to move an assignment is not grounds for not making
2016 a libcall block. There are two reasons why it is safe to leave these
2017 insns inside the block: First, we know that these pseudos cannot be
2018 used in generated RTL outside the block since they are created for
2019 temporary purposes within the block. Second, CSE will not record the
2020 values of anything set inside a libcall block, so we know they must
2021 be dead at the end of the block.
2022
2023 Except for the first group of insns (the ones setting pseudos), the
2024 block is delimited by REG_RETVAL and REG_LIBCALL notes. */
2025
2026void
2027emit_libcall_block (insns, target, result, equiv)
2028 rtx insns;
2029 rtx target;
2030 rtx result;
2031 rtx equiv;
2032{
2033 rtx prev, next, first, last, insn;
2034
2035 /* First emit all insns that set pseudos. Remove them from the list as
2036 we go. Avoid insns that set pseudo which were referenced in previous
2037 insns. These can be generated by move_by_pieces, for example,
2038 to update an address. */
2039
2040 for (insn = insns; insn; insn = next)
2041 {
2042 rtx set = single_set (insn);
2043
2044 next = NEXT_INSN (insn);
2045
2046 if (set != 0 && GET_CODE (SET_DEST (set)) == REG
2047 && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER
2048 && (insn == insns
2049 || (! reg_mentioned_p (SET_DEST (set), PATTERN (insns))
2050 && ! reg_used_between_p (SET_DEST (set), insns, insn))))
2051 {
2052 if (PREV_INSN (insn))
2053 NEXT_INSN (PREV_INSN (insn)) = next;
2054 else
2055 insns = next;
2056
2057 if (next)
2058 PREV_INSN (next) = PREV_INSN (insn);
2059
2060 add_insn (insn);
2061 }
2062 }
2063
2064 prev = get_last_insn ();
2065
2066 /* Write the remaining insns followed by the final copy. */
2067
2068 for (insn = insns; insn; insn = next)
2069 {
2070 next = NEXT_INSN (insn);
2071
2072 add_insn (insn);
2073 }
2074
2075 last = emit_move_insn (target, result);
2076 REG_NOTES (last) = gen_rtx (EXPR_LIST, REG_EQUAL, equiv, REG_NOTES (last));
2077
2078 if (prev == 0)
2079 first = get_insns ();
2080 else
2081 first = NEXT_INSN (prev);
2082
2083 /* Encapsulate the block so it gets manipulated as a unit. */
2084 REG_NOTES (first) = gen_rtx (INSN_LIST, REG_LIBCALL, last,
2085 REG_NOTES (first));
2086 REG_NOTES (last) = gen_rtx (INSN_LIST, REG_RETVAL, first, REG_NOTES (last));
2087}
2088\f
2089/* Generate code to store zero in X. */
2090
2091void
2092emit_clr_insn (x)
2093 rtx x;
2094{
2095 emit_move_insn (x, const0_rtx);
2096}
2097
2098/* Generate code to store 1 in X
2099 assuming it contains zero beforehand. */
2100
2101void
2102emit_0_to_1_insn (x)
2103 rtx x;
2104{
2105 emit_move_insn (x, const1_rtx);
2106}
2107
2108/* Generate code to compare X with Y
2109 so that the condition codes are set.
2110
2111 MODE is the mode of the inputs (in case they are const_int).
2112 UNSIGNEDP nonzero says that X and Y are unsigned;
2113 this matters if they need to be widened.
2114
2115 If they have mode BLKmode, then SIZE specifies the size of both X and Y,
2116 and ALIGN specifies the known shared alignment of X and Y.
2117
2118 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).
2119 It is ignored for fixed-point and block comparisons;
2120 it is used only for floating-point comparisons. */
2121
2122void
2123emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align)
2124 rtx x, y;
2125 enum rtx_code comparison;
2126 rtx size;
2127 enum machine_mode mode;
2128 int unsignedp;
2129 int align;
2130{
2131 enum mode_class class;
2132 enum machine_mode wider_mode;
2133
2134 class = GET_MODE_CLASS (mode);
2135
2136 /* They could both be VOIDmode if both args are immediate constants,
2137 but we should fold that at an earlier stage.
2138 With no special code here, this will call abort,
2139 reminding the programmer to implement such folding. */
2140
2141 if (mode != BLKmode && flag_force_mem)
2142 {
2143 x = force_not_mem (x);
2144 y = force_not_mem (y);
2145 }
2146
2147 /* If we are inside an appropriately-short loop and one operand is an
2148 expensive constant, force it into a register. */
2149 if (CONSTANT_P (x) && preserve_subexpressions_p () && rtx_cost (x, COMPARE) > 2)
2150 x = force_reg (mode, x);
2151
2152 if (CONSTANT_P (y) && preserve_subexpressions_p () && rtx_cost (y, COMPARE) > 2)
2153 y = force_reg (mode, y);
2154
2155 /* Don't let both operands fail to indicate the mode. */
2156 if (GET_MODE (x) == VOIDmode && GET_MODE (y) == VOIDmode)
2157 x = force_reg (mode, x);
2158
2159 /* Handle all BLKmode compares. */
2160
2161 if (mode == BLKmode)
2162 {
2163 emit_queue ();
2164 x = protect_from_queue (x, 0);
2165 y = protect_from_queue (y, 0);
2166
2167 if (size == 0)
2168 abort ();
2169#ifdef HAVE_cmpstrqi
2170 if (HAVE_cmpstrqi
2171 && GET_CODE (size) == CONST_INT
2172 && INTVAL (size) < (1 << GET_MODE_BITSIZE (QImode)))
2173 {
2174 enum machine_mode result_mode
2175 = insn_operand_mode[(int) CODE_FOR_cmpstrqi][0];
2176 rtx result = gen_reg_rtx (result_mode);
2177 emit_insn (gen_cmpstrqi (result, x, y, size, GEN_INT (align)));
2178 emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX,
2179 result_mode, 0, 0);
2180 }
2181 else
2182#endif
2183#ifdef HAVE_cmpstrhi
2184 if (HAVE_cmpstrhi
2185 && GET_CODE (size) == CONST_INT
2186 && INTVAL (size) < (1 << GET_MODE_BITSIZE (HImode)))
2187 {
2188 enum machine_mode result_mode
2189 = insn_operand_mode[(int) CODE_FOR_cmpstrhi][0];
2190 rtx result = gen_reg_rtx (result_mode);
2191 emit_insn (gen_cmpstrhi (result, x, y, size, GEN_INT (align)));
2192 emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX,
2193 result_mode, 0, 0);
2194 }
2195 else
2196#endif
2197#ifdef HAVE_cmpstrsi
2198 if (HAVE_cmpstrsi)
2199 {
2200 enum machine_mode result_mode
2201 = insn_operand_mode[(int) CODE_FOR_cmpstrsi][0];
2202 rtx result = gen_reg_rtx (result_mode);
2203 size = protect_from_queue (size, 0);
2204 emit_insn (gen_cmpstrsi (result, x, y,
2205 convert_to_mode (SImode, size, 1),
2206 GEN_INT (align)));
2207 emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX,
2208 result_mode, 0, 0);
2209 }
2210 else
2211#endif
2212 {
2213#ifdef TARGET_MEM_FUNCTIONS
2214 emit_library_call (memcmp_libfunc, 0,
2215 TYPE_MODE (integer_type_node), 3,
2216 XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
2217 size, Pmode);
2218#else
2219 emit_library_call (bcmp_libfunc, 0,
2220 TYPE_MODE (integer_type_node), 3,
2221 XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
2222 size, Pmode);
2223#endif
2224 emit_cmp_insn (hard_libcall_value (TYPE_MODE (integer_type_node)),
2225 const0_rtx, comparison, NULL_RTX,
2226 TYPE_MODE (integer_type_node), 0, 0);
2227 }
2228 return;
2229 }
2230
2231 /* Handle some compares against zero. */
2232
2233 if (y == CONST0_RTX (mode)
2234 && tst_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
2235 {
2236 int icode = (int) tst_optab->handlers[(int) mode].insn_code;
2237
2238 emit_queue ();
2239 x = protect_from_queue (x, 0);
2240 y = protect_from_queue (y, 0);
2241
2242 /* Now, if insn does accept these operands, put them into pseudos. */
2243 if (! (*insn_operand_predicate[icode][0])
2244 (x, insn_operand_mode[icode][0]))
2245 x = copy_to_mode_reg (insn_operand_mode[icode][0], x);
2246
2247 emit_insn (GEN_FCN (icode) (x));
2248 return;
2249 }
2250
2251 /* Handle compares for which there is a directly suitable insn. */
2252
2253 if (cmp_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
2254 {
2255 int icode = (int) cmp_optab->handlers[(int) mode].insn_code;
2256
2257 emit_queue ();
2258 x = protect_from_queue (x, 0);
2259 y = protect_from_queue (y, 0);
2260
2261 /* Now, if insn doesn't accept these operands, put them into pseudos. */
2262 if (! (*insn_operand_predicate[icode][0])
2263 (x, insn_operand_mode[icode][0]))
2264 x = copy_to_mode_reg (insn_operand_mode[icode][0], x);
2265
2266 if (! (*insn_operand_predicate[icode][1])
2267 (y, insn_operand_mode[icode][1]))
2268 y = copy_to_mode_reg (insn_operand_mode[icode][1], y);
2269
2270 emit_insn (GEN_FCN (icode) (x, y));
2271 return;
2272 }
2273
2274 /* Try widening if we can find a direct insn that way. */
2275
2276 if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
2277 {
2278 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
2279 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2280 {
2281 if (cmp_optab->handlers[(int) wider_mode].insn_code
2282 != CODE_FOR_nothing)
2283 {
2284 x = protect_from_queue (x, 0);
2285 y = protect_from_queue (y, 0);
2286 x = convert_to_mode (wider_mode, x, unsignedp);
2287 y = convert_to_mode (wider_mode, y, unsignedp);
2288 emit_cmp_insn (x, y, comparison, NULL_RTX,
2289 wider_mode, unsignedp, align);
2290 return;
2291 }
2292 }
2293 }
2294
2295 /* Handle a lib call just for the mode we are using. */
2296
2297 if (cmp_optab->handlers[(int) mode].libfunc
2298 && class != MODE_FLOAT)
2299 {
2300 rtx libfunc = cmp_optab->handlers[(int) mode].libfunc;
2301 /* If we want unsigned, and this mode has a distinct unsigned
2302 comparison routine, use that. */
2303 if (unsignedp && ucmp_optab->handlers[(int) mode].libfunc)
2304 libfunc = ucmp_optab->handlers[(int) mode].libfunc;
2305
2306 emit_library_call (libfunc, 1,
2307 SImode, 2, x, mode, y, mode);
2308
2309 /* Integer comparison returns a result that must be compared against 1,
2310 so that even if we do an unsigned compare afterward,
2311 there is still a value that can represent the result "less than". */
2312
2313 emit_cmp_insn (hard_libcall_value (SImode), const1_rtx,
2314 comparison, NULL_RTX, SImode, unsignedp, 0);
2315 return;
2316 }
2317
2318 if (class == MODE_FLOAT)
2319 emit_float_lib_cmp (x, y, comparison);
2320
2321 else
2322 abort ();
2323}
2324
2325/* Nonzero if a compare of mode MODE can be done straightforwardly
2326 (without splitting it into pieces). */
2327
2328int
2329can_compare_p (mode)
2330 enum machine_mode mode;
2331{
2332 do
2333 {
2334 if (cmp_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)
2335 return 1;
2336 mode = GET_MODE_WIDER_MODE (mode);
2337 } while (mode != VOIDmode);
2338
2339 return 0;
2340}
2341\f
2342/* Emit a library call comparison between floating point X and Y.
2343 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). */
2344
2345static void
2346emit_float_lib_cmp (x, y, comparison)
2347 rtx x, y;
2348 enum rtx_code comparison;
2349{
2350 enum machine_mode mode = GET_MODE (x);
2351 rtx libfunc;
2352
2353 if (mode == SFmode)
2354 switch (comparison)
2355 {
2356 case EQ:
2357 libfunc = eqsf2_libfunc;
2358 break;
2359
2360 case NE:
2361 libfunc = nesf2_libfunc;
2362 break;
2363
2364 case GT:
2365 libfunc = gtsf2_libfunc;
2366 break;
2367
2368 case GE:
2369 libfunc = gesf2_libfunc;
2370 break;
2371
2372 case LT:
2373 libfunc = ltsf2_libfunc;
2374 break;
2375
2376 case LE:
2377 libfunc = lesf2_libfunc;
2378 break;
2379 }
2380 else if (mode == DFmode)
2381 switch (comparison)
2382 {
2383 case EQ:
2384 libfunc = eqdf2_libfunc;
2385 break;
2386
2387 case NE:
2388 libfunc = nedf2_libfunc;
2389 break;
2390
2391 case GT:
2392 libfunc = gtdf2_libfunc;
2393 break;
2394
2395 case GE:
2396 libfunc = gedf2_libfunc;
2397 break;
2398
2399 case LT:
2400 libfunc = ltdf2_libfunc;
2401 break;
2402
2403 case LE:
2404 libfunc = ledf2_libfunc;
2405 break;
2406 }
2407 else if (mode == XFmode)
2408 switch (comparison)
2409 {
2410 case EQ:
2411 libfunc = eqxf2_libfunc;
2412 break;
2413
2414 case NE:
2415 libfunc = nexf2_libfunc;
2416 break;
2417
2418 case GT:
2419 libfunc = gtxf2_libfunc;
2420 break;
2421
2422 case GE:
2423 libfunc = gexf2_libfunc;
2424 break;
2425
2426 case LT:
2427 libfunc = ltxf2_libfunc;
2428 break;
2429
2430 case LE:
2431 libfunc = lexf2_libfunc;
2432 break;
2433 }
2434 else if (mode == TFmode)
2435 switch (comparison)
2436 {
2437 case EQ:
2438 libfunc = eqtf2_libfunc;
2439 break;
2440
2441 case NE:
2442 libfunc = netf2_libfunc;
2443 break;
2444
2445 case GT:
2446 libfunc = gttf2_libfunc;
2447 break;
2448
2449 case GE:
2450 libfunc = getf2_libfunc;
2451 break;
2452
2453 case LT:
2454 libfunc = lttf2_libfunc;
2455 break;
2456
2457 case LE:
2458 libfunc = letf2_libfunc;
2459 break;
2460 }
2461 else
2462 {
2463 enum machine_mode wider_mode;
2464
2465 for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
2466 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2467 {
2468 if ((cmp_optab->handlers[(int) wider_mode].insn_code
2469 != CODE_FOR_nothing)
2470 || (cmp_optab->handlers[(int) wider_mode].libfunc != 0))
2471 {
2472 x = protect_from_queue (x, 0);
2473 y = protect_from_queue (y, 0);
2474 x = convert_to_mode (wider_mode, x, 0);
2475 y = convert_to_mode (wider_mode, y, 0);
2476 emit_float_lib_cmp (x, y, comparison);
2477 return;
2478 }
2479 }
2480 abort ();
2481 }
2482
2483 emit_library_call (libfunc, 1,
2484 SImode, 2, x, mode, y, mode);
2485
2486 emit_cmp_insn (hard_libcall_value (SImode), const0_rtx, comparison,
2487 NULL_RTX, SImode, 0, 0);
2488}
2489\f
2490/* Generate code to indirectly jump to a location given in the rtx LOC. */
2491
2492void
2493emit_indirect_jump (loc)
2494 rtx loc;
2495{
2496 if (! ((*insn_operand_predicate[(int)CODE_FOR_indirect_jump][0])
2497 (loc, VOIDmode)))
2498 loc = copy_to_mode_reg (insn_operand_mode[(int)CODE_FOR_indirect_jump][0],
2499 loc);
2500
2501 emit_jump_insn (gen_indirect_jump (loc));
2502 emit_barrier ();
2503}
2504\f
2505/* These three functions generate an insn body and return it
2506 rather than emitting the insn.
2507
2508 They do not protect from queued increments,
2509 because they may be used 1) in protect_from_queue itself
2510 and 2) in other passes where there is no queue. */
2511
2512/* Generate and return an insn body to add Y to X. */
2513
2514rtx
2515gen_add2_insn (x, y)
2516 rtx x, y;
2517{
2518 int icode = (int) add_optab->handlers[(int) GET_MODE (x)].insn_code;
2519
2520 if (! (*insn_operand_predicate[icode][0]) (x, insn_operand_mode[icode][0])
2521 || ! (*insn_operand_predicate[icode][1]) (x, insn_operand_mode[icode][1])
2522 || ! (*insn_operand_predicate[icode][2]) (y, insn_operand_mode[icode][2]))
2523 abort ();
2524
2525 return (GEN_FCN (icode) (x, x, y));
2526}
2527
2528int
2529have_add2_insn (mode)
2530 enum machine_mode mode;
2531{
2532 return add_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing;
2533}
2534
2535/* Generate and return an insn body to subtract Y from X. */
2536
2537rtx
2538gen_sub2_insn (x, y)
2539 rtx x, y;
2540{
2541 int icode = (int) sub_optab->handlers[(int) GET_MODE (x)].insn_code;
2542
2543 if (! (*insn_operand_predicate[icode][0]) (x, insn_operand_mode[icode][0])
2544 || ! (*insn_operand_predicate[icode][1]) (x, insn_operand_mode[icode][1])
2545 || ! (*insn_operand_predicate[icode][2]) (y, insn_operand_mode[icode][2]))
2546 abort ();
2547
2548 return (GEN_FCN (icode) (x, x, y));
2549}
2550
2551int
2552have_sub2_insn (mode)
2553 enum machine_mode mode;
2554{
2555 return sub_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing;
2556}
2557
2558/* Generate the body of an instruction to copy Y into X. */
2559
2560rtx
2561gen_move_insn (x, y)
2562 rtx x, y;
2563{
2564 register enum machine_mode mode = GET_MODE (x);
2565 enum insn_code insn_code;
2566
2567 if (mode == VOIDmode)
2568 mode = GET_MODE (y);
2569
2570 insn_code = mov_optab->handlers[(int) mode].insn_code;
2571
2572 /* Handle MODE_CC modes: If we don't have a special move insn for this mode,
2573 find a mode to do it in. If we have a movcc, use it. Otherwise,
2574 find the MODE_INT mode of the same width. */
2575
2576 if (insn_code == CODE_FOR_nothing)
2577 {
2578 enum machine_mode tmode = VOIDmode;
2579 rtx x1 = x, y1 = y;
2580
2581 if (GET_MODE_CLASS (mode) == MODE_CC && mode != CCmode
2582 && mov_optab->handlers[(int) CCmode].insn_code != CODE_FOR_nothing)
2583 tmode = CCmode;
2584 else if (GET_MODE_CLASS (mode) == MODE_CC)
2585 for (tmode = QImode; tmode != VOIDmode;
2586 tmode = GET_MODE_WIDER_MODE (tmode))
2587 if (GET_MODE_SIZE (tmode) == GET_MODE_SIZE (mode))
2588 break;
2589
2590 if (tmode == VOIDmode)
2591 abort ();
2592
2593 /* Get X and Y in TMODE. We can't use gen_lowpart here because it
2594 may call change_address which is not appropriate if we were
2595 called when a reload was in progress. We don't have to worry
2596 about changing the address since the size in bytes is supposed to
2597 be the same. Copy the MEM to change the mode and move any
2598 substitutions from the old MEM to the new one. */
2599
2600 if (reload_in_progress)
2601 {
2602 x = gen_lowpart_common (tmode, x1);
2603 if (x == 0 && GET_CODE (x1) == MEM)
2604 {
2605 x = gen_rtx (MEM, tmode, XEXP (x1, 0));
2606 RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (x1);
2607 MEM_IN_STRUCT_P (x) = MEM_IN_STRUCT_P (x1);
2608 MEM_VOLATILE_P (x) = MEM_VOLATILE_P (x1);
2609 copy_replacements (x1, x);
2610 }
2611
2612 y = gen_lowpart_common (tmode, y1);
2613 if (y == 0 && GET_CODE (y1) == MEM)
2614 {
2615 y = gen_rtx (MEM, tmode, XEXP (y1, 0));
2616 RTX_UNCHANGING_P (y) = RTX_UNCHANGING_P (y1);
2617 MEM_IN_STRUCT_P (y) = MEM_IN_STRUCT_P (y1);
2618 MEM_VOLATILE_P (y) = MEM_VOLATILE_P (y1);
2619 copy_replacements (y1, y);
2620 }
2621 }
2622 else
2623 {
2624 x = gen_lowpart (tmode, x);
2625 y = gen_lowpart (tmode, y);
2626 }
2627
2628 insn_code = mov_optab->handlers[(int) tmode].insn_code;
2629 }
2630
2631 return (GEN_FCN (insn_code) (x, y));
2632}
2633\f
2634/* Tables of patterns for extending one integer mode to another. */
2635static enum insn_code extendtab[MAX_MACHINE_MODE][MAX_MACHINE_MODE][2];
2636
2637/* Return the insn code used to extend FROM_MODE to TO_MODE.
2638 UNSIGNEDP specifies zero-extension instead of sign-extension. If
2639 no such operation exists, CODE_FOR_nothing will be returned. */
2640
2641enum insn_code
2642can_extend_p (to_mode, from_mode, unsignedp)
2643 enum machine_mode to_mode, from_mode;
2644 int unsignedp;
2645{
2646 return extendtab[(int) to_mode][(int) from_mode][unsignedp];
2647}
2648
2649/* Generate the body of an insn to extend Y (with mode MFROM)
2650 into X (with mode MTO). Do zero-extension if UNSIGNEDP is nonzero. */
2651
2652rtx
2653gen_extend_insn (x, y, mto, mfrom, unsignedp)
2654 rtx x, y;
2655 enum machine_mode mto, mfrom;
2656 int unsignedp;
2657{
2658 return (GEN_FCN (extendtab[(int) mto][(int) mfrom][unsignedp]) (x, y));
2659}
2660
2661static void
2662init_extends ()
2663{
2664 enum insn_code *p;
2665
2666 for (p = extendtab[0][0];
2667 p < extendtab[0][0] + sizeof extendtab / sizeof extendtab[0][0][0];
2668 p++)
2669 *p = CODE_FOR_nothing;
2670
2671#ifdef HAVE_extendditi2
2672 if (HAVE_extendditi2)
2673 extendtab[(int) TImode][(int) DImode][0] = CODE_FOR_extendditi2;
2674#endif
2675#ifdef HAVE_extendsiti2
2676 if (HAVE_extendsiti2)
2677 extendtab[(int) TImode][(int) SImode][0] = CODE_FOR_extendsiti2;
2678#endif
2679#ifdef HAVE_extendhiti2
2680 if (HAVE_extendhiti2)
2681 extendtab[(int) TImode][(int) HImode][0] = CODE_FOR_extendhiti2;
2682#endif
2683#ifdef HAVE_extendqiti2
2684 if (HAVE_extendqiti2)
2685 extendtab[(int) TImode][(int) QImode][0] = CODE_FOR_extendqiti2;
2686#endif
2687#ifdef HAVE_extendsidi2
2688 if (HAVE_extendsidi2)
2689 extendtab[(int) DImode][(int) SImode][0] = CODE_FOR_extendsidi2;
2690#endif
2691#ifdef HAVE_extendhidi2
2692 if (HAVE_extendhidi2)
2693 extendtab[(int) DImode][(int) HImode][0] = CODE_FOR_extendhidi2;
2694#endif
2695#ifdef HAVE_extendqidi2
2696 if (HAVE_extendqidi2)
2697 extendtab[(int) DImode][(int) QImode][0] = CODE_FOR_extendqidi2;
2698#endif
2699#ifdef HAVE_extendhisi2
2700 if (HAVE_extendhisi2)
2701 extendtab[(int) SImode][(int) HImode][0] = CODE_FOR_extendhisi2;
2702#endif
2703#ifdef HAVE_extendqisi2
2704 if (HAVE_extendqisi2)
2705 extendtab[(int) SImode][(int) QImode][0] = CODE_FOR_extendqisi2;
2706#endif
2707#ifdef HAVE_extendqihi2
2708 if (HAVE_extendqihi2)
2709 extendtab[(int) HImode][(int) QImode][0] = CODE_FOR_extendqihi2;
2710#endif
2711
2712#ifdef HAVE_zero_extendditi2
2713 if (HAVE_zero_extendsiti2)
2714 extendtab[(int) TImode][(int) DImode][1] = CODE_FOR_zero_extendditi2;
2715#endif
2716#ifdef HAVE_zero_extendsiti2
2717 if (HAVE_zero_extendsiti2)
2718 extendtab[(int) TImode][(int) SImode][1] = CODE_FOR_zero_extendsiti2;
2719#endif
2720#ifdef HAVE_zero_extendhiti2
2721 if (HAVE_zero_extendhiti2)
2722 extendtab[(int) TImode][(int) HImode][1] = CODE_FOR_zero_extendhiti2;
2723#endif
2724#ifdef HAVE_zero_extendqiti2
2725 if (HAVE_zero_extendqiti2)
2726 extendtab[(int) TImode][(int) QImode][1] = CODE_FOR_zero_extendqiti2;
2727#endif
2728#ifdef HAVE_zero_extendsidi2
2729 if (HAVE_zero_extendsidi2)
2730 extendtab[(int) DImode][(int) SImode][1] = CODE_FOR_zero_extendsidi2;
2731#endif
2732#ifdef HAVE_zero_extendhidi2
2733 if (HAVE_zero_extendhidi2)
2734 extendtab[(int) DImode][(int) HImode][1] = CODE_FOR_zero_extendhidi2;
2735#endif
2736#ifdef HAVE_zero_extendqidi2
2737 if (HAVE_zero_extendqidi2)
2738 extendtab[(int) DImode][(int) QImode][1] = CODE_FOR_zero_extendqidi2;
2739#endif
2740#ifdef HAVE_zero_extendhisi2
2741 if (HAVE_zero_extendhisi2)
2742 extendtab[(int) SImode][(int) HImode][1] = CODE_FOR_zero_extendhisi2;
2743#endif
2744#ifdef HAVE_zero_extendqisi2
2745 if (HAVE_zero_extendqisi2)
2746 extendtab[(int) SImode][(int) QImode][1] = CODE_FOR_zero_extendqisi2;
2747#endif
2748#ifdef HAVE_zero_extendqihi2
2749 if (HAVE_zero_extendqihi2)
2750 extendtab[(int) HImode][(int) QImode][1] = CODE_FOR_zero_extendqihi2;
2751#endif
2752}
2753\f
2754/* can_fix_p and can_float_p say whether the target machine
2755 can directly convert a given fixed point type to
2756 a given floating point type, or vice versa.
2757 The returned value is the CODE_FOR_... value to use,
2758 or CODE_FOR_nothing if these modes cannot be directly converted. */
2759
2760static enum insn_code fixtab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
2761static enum insn_code fixtrunctab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
2762static enum insn_code floattab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
2763
2764/* *TRUNCP_PTR is set to 1 if it is necessary to output
2765 an explicit FTRUNC insn before the fix insn; otherwise 0. */
2766
2767static enum insn_code
2768can_fix_p (fixmode, fltmode, unsignedp, truncp_ptr)
2769 enum machine_mode fltmode, fixmode;
2770 int unsignedp;
2771 int *truncp_ptr;
2772{
2773 *truncp_ptr = 0;
2774 if (fixtrunctab[(int) fltmode][(int) fixmode][unsignedp] != CODE_FOR_nothing)
2775 return fixtrunctab[(int) fltmode][(int) fixmode][unsignedp];
2776
2777 if (ftrunc_optab->handlers[(int) fltmode].insn_code != CODE_FOR_nothing)
2778 {
2779 *truncp_ptr = 1;
2780 return fixtab[(int) fltmode][(int) fixmode][unsignedp];
2781 }
2782 return CODE_FOR_nothing;
2783}
2784
2785static enum insn_code
2786can_float_p (fltmode, fixmode, unsignedp)
2787 enum machine_mode fixmode, fltmode;
2788 int unsignedp;
2789{
2790 return floattab[(int) fltmode][(int) fixmode][unsignedp];
2791}
2792
2793void
2794init_fixtab ()
2795{
2796 enum insn_code *p;
2797 for (p = fixtab[0][0];
2798 p < fixtab[0][0] + sizeof fixtab / sizeof (fixtab[0][0][0]);
2799 p++)
2800 *p = CODE_FOR_nothing;
2801 for (p = fixtrunctab[0][0];
2802 p < fixtrunctab[0][0] + sizeof fixtrunctab / sizeof (fixtrunctab[0][0][0]);
2803 p++)
2804 *p = CODE_FOR_nothing;
2805
2806#ifdef HAVE_fixsfqi2
2807 if (HAVE_fixsfqi2)
2808 fixtab[(int) SFmode][(int) QImode][0] = CODE_FOR_fixsfqi2;
2809#endif
2810#ifdef HAVE_fixsfhi2
2811 if (HAVE_fixsfhi2)
2812 fixtab[(int) SFmode][(int) HImode][0] = CODE_FOR_fixsfhi2;
2813#endif
2814#ifdef HAVE_fixsfsi2
2815 if (HAVE_fixsfsi2)
2816 fixtab[(int) SFmode][(int) SImode][0] = CODE_FOR_fixsfsi2;
2817#endif
2818#ifdef HAVE_fixsfdi2
2819 if (HAVE_fixsfdi2)
2820 fixtab[(int) SFmode][(int) DImode][0] = CODE_FOR_fixsfdi2;
2821#endif
2822
2823#ifdef HAVE_fixdfqi2
2824 if (HAVE_fixdfqi2)
2825 fixtab[(int) DFmode][(int) QImode][0] = CODE_FOR_fixdfqi2;
2826#endif
2827#ifdef HAVE_fixdfhi2
2828 if (HAVE_fixdfhi2)
2829 fixtab[(int) DFmode][(int) HImode][0] = CODE_FOR_fixdfhi2;
2830#endif
2831#ifdef HAVE_fixdfsi2
2832 if (HAVE_fixdfsi2)
2833 fixtab[(int) DFmode][(int) SImode][0] = CODE_FOR_fixdfsi2;
2834#endif
2835#ifdef HAVE_fixdfdi2
2836 if (HAVE_fixdfdi2)
2837 fixtab[(int) DFmode][(int) DImode][0] = CODE_FOR_fixdfdi2;
2838#endif
2839#ifdef HAVE_fixdfti2
2840 if (HAVE_fixdfti2)
2841 fixtab[(int) DFmode][(int) TImode][0] = CODE_FOR_fixdfti2;
2842#endif
2843
2844#ifdef HAVE_fixxfqi2
2845 if (HAVE_fixxfqi2)
2846 fixtab[(int) XFmode][(int) QImode][0] = CODE_FOR_fixxfqi2;
2847#endif
2848#ifdef HAVE_fixxfhi2
2849 if (HAVE_fixxfhi2)
2850 fixtab[(int) XFmode][(int) HImode][0] = CODE_FOR_fixxfhi2;
2851#endif
2852#ifdef HAVE_fixxfsi2
2853 if (HAVE_fixxfsi2)
2854 fixtab[(int) XFmode][(int) SImode][0] = CODE_FOR_fixxfsi2;
2855#endif
2856#ifdef HAVE_fixxfdi2
2857 if (HAVE_fixxfdi2)
2858 fixtab[(int) XFmode][(int) DImode][0] = CODE_FOR_fixxfdi2;
2859#endif
2860#ifdef HAVE_fixxfti2
2861 if (HAVE_fixxfti2)
2862 fixtab[(int) XFmode][(int) TImode][0] = CODE_FOR_fixxfti2;
2863#endif
2864
2865#ifdef HAVE_fixtfqi2
2866 if (HAVE_fixtfqi2)
2867 fixtab[(int) TFmode][(int) QImode][0] = CODE_FOR_fixtfqi2;
2868#endif
2869#ifdef HAVE_fixtfhi2
2870 if (HAVE_fixtfhi2)
2871 fixtab[(int) TFmode][(int) HImode][0] = CODE_FOR_fixtfhi2;
2872#endif
2873#ifdef HAVE_fixtfsi2
2874 if (HAVE_fixtfsi2)
2875 fixtab[(int) TFmode][(int) SImode][0] = CODE_FOR_fixtfsi2;
2876#endif
2877#ifdef HAVE_fixtfdi2
2878 if (HAVE_fixtfdi2)
2879 fixtab[(int) TFmode][(int) DImode][0] = CODE_FOR_fixtfdi2;
2880#endif
2881#ifdef HAVE_fixtfti2
2882 if (HAVE_fixtfti2)
2883 fixtab[(int) TFmode][(int) TImode][0] = CODE_FOR_fixtfti2;
2884#endif
2885
2886#ifdef HAVE_fixunssfqi2
2887 if (HAVE_fixunssfqi2)
2888 fixtab[(int) SFmode][(int) QImode][1] = CODE_FOR_fixunssfqi2;
2889#endif
2890#ifdef HAVE_fixunssfhi2
2891 if (HAVE_fixunssfhi2)
2892 fixtab[(int) SFmode][(int) HImode][1] = CODE_FOR_fixunssfhi2;
2893#endif
2894#ifdef HAVE_fixunssfsi2
2895 if (HAVE_fixunssfsi2)
2896 fixtab[(int) SFmode][(int) SImode][1] = CODE_FOR_fixunssfsi2;
2897#endif
2898#ifdef HAVE_fixunssfdi2
2899 if (HAVE_fixunssfdi2)
2900 fixtab[(int) SFmode][(int) DImode][1] = CODE_FOR_fixunssfdi2;
2901#endif
2902
2903#ifdef HAVE_fixunsdfqi2
2904 if (HAVE_fixunsdfqi2)
2905 fixtab[(int) DFmode][(int) QImode][1] = CODE_FOR_fixunsdfqi2;
2906#endif
2907#ifdef HAVE_fixunsdfhi2
2908 if (HAVE_fixunsdfhi2)
2909 fixtab[(int) DFmode][(int) HImode][1] = CODE_FOR_fixunsdfhi2;
2910#endif
2911#ifdef HAVE_fixunsdfsi2
2912 if (HAVE_fixunsdfsi2)
2913 fixtab[(int) DFmode][(int) SImode][1] = CODE_FOR_fixunsdfsi2;
2914#endif
2915#ifdef HAVE_fixunsdfdi2
2916 if (HAVE_fixunsdfdi2)
2917 fixtab[(int) DFmode][(int) DImode][1] = CODE_FOR_fixunsdfdi2;
2918#endif
2919#ifdef HAVE_fixunsdfti2
2920 if (HAVE_fixunsdfti2)
2921 fixtab[(int) DFmode][(int) TImode][1] = CODE_FOR_fixunsdfti2;
2922#endif
2923
2924#ifdef HAVE_fixunsxfqi2
2925 if (HAVE_fixunsxfqi2)
2926 fixtab[(int) XFmode][(int) QImode][1] = CODE_FOR_fixunsxfqi2;
2927#endif
2928#ifdef HAVE_fixunsxfhi2
2929 if (HAVE_fixunsxfhi2)
2930 fixtab[(int) XFmode][(int) HImode][1] = CODE_FOR_fixunsxfhi2;
2931#endif
2932#ifdef HAVE_fixunsxfsi2
2933 if (HAVE_fixunsxfsi2)
2934 fixtab[(int) XFmode][(int) SImode][1] = CODE_FOR_fixunsxfsi2;
2935#endif
2936#ifdef HAVE_fixunsxfdi2
2937 if (HAVE_fixunsxfdi2)
2938 fixtab[(int) XFmode][(int) DImode][1] = CODE_FOR_fixunsxfdi2;
2939#endif
2940#ifdef HAVE_fixunsxfti2
2941 if (HAVE_fixunsxfti2)
2942 fixtab[(int) XFmode][(int) TImode][1] = CODE_FOR_fixunsxfti2;
2943#endif
2944
2945#ifdef HAVE_fixunstfqi2
2946 if (HAVE_fixunstfqi2)
2947 fixtab[(int) TFmode][(int) QImode][1] = CODE_FOR_fixunstfqi2;
2948#endif
2949#ifdef HAVE_fixunstfhi2
2950 if (HAVE_fixunstfhi2)
2951 fixtab[(int) TFmode][(int) HImode][1] = CODE_FOR_fixunstfhi2;
2952#endif
2953#ifdef HAVE_fixunstfsi2
2954 if (HAVE_fixunstfsi2)
2955 fixtab[(int) TFmode][(int) SImode][1] = CODE_FOR_fixunstfsi2;
2956#endif
2957#ifdef HAVE_fixunstfdi2
2958 if (HAVE_fixunstfdi2)
2959 fixtab[(int) TFmode][(int) DImode][1] = CODE_FOR_fixunstfdi2;
2960#endif
2961#ifdef HAVE_fixunstfti2
2962 if (HAVE_fixunstfti2)
2963 fixtab[(int) TFmode][(int) TImode][1] = CODE_FOR_fixunstfti2;
2964#endif
2965
2966#ifdef HAVE_fix_truncsfqi2
2967 if (HAVE_fix_truncsfqi2)
2968 fixtrunctab[(int) SFmode][(int) QImode][0] = CODE_FOR_fix_truncsfqi2;
2969#endif
2970#ifdef HAVE_fix_truncsfhi2
2971 if (HAVE_fix_truncsfhi2)
2972 fixtrunctab[(int) SFmode][(int) HImode][0] = CODE_FOR_fix_truncsfhi2;
2973#endif
2974#ifdef HAVE_fix_truncsfsi2
2975 if (HAVE_fix_truncsfsi2)
2976 fixtrunctab[(int) SFmode][(int) SImode][0] = CODE_FOR_fix_truncsfsi2;
2977#endif
2978#ifdef HAVE_fix_truncsfdi2
2979 if (HAVE_fix_truncsfdi2)
2980 fixtrunctab[(int) SFmode][(int) DImode][0] = CODE_FOR_fix_truncsfdi2;
2981#endif
2982
2983#ifdef HAVE_fix_truncdfqi2
2984 if (HAVE_fix_truncdfqi2)
2985 fixtrunctab[(int) DFmode][(int) QImode][0] = CODE_FOR_fix_truncdfqi2;
2986#endif
2987#ifdef HAVE_fix_truncdfhi2
2988 if (HAVE_fix_truncdfhi2)
2989 fixtrunctab[(int) DFmode][(int) HImode][0] = CODE_FOR_fix_truncdfhi2;
2990#endif
2991#ifdef HAVE_fix_truncdfsi2
2992 if (HAVE_fix_truncdfsi2)
2993 fixtrunctab[(int) DFmode][(int) SImode][0] = CODE_FOR_fix_truncdfsi2;
2994#endif
2995#ifdef HAVE_fix_truncdfdi2
2996 if (HAVE_fix_truncdfdi2)
2997 fixtrunctab[(int) DFmode][(int) DImode][0] = CODE_FOR_fix_truncdfdi2;
2998#endif
2999#ifdef HAVE_fix_truncdfti2
3000 if (HAVE_fix_truncdfti2)
3001 fixtrunctab[(int) DFmode][(int) TImode][0] = CODE_FOR_fix_truncdfti2;
3002#endif
3003
3004#ifdef HAVE_fix_truncxfqi2
3005 if (HAVE_fix_truncxfqi2)
3006 fixtrunctab[(int) XFmode][(int) QImode][0] = CODE_FOR_fix_truncxfqi2;
3007#endif
3008#ifdef HAVE_fix_truncxfhi2
3009 if (HAVE_fix_truncxfhi2)
3010 fixtrunctab[(int) XFmode][(int) HImode][0] = CODE_FOR_fix_truncxfhi2;
3011#endif
3012#ifdef HAVE_fix_truncxfsi2
3013 if (HAVE_fix_truncxfsi2)
3014 fixtrunctab[(int) XFmode][(int) SImode][0] = CODE_FOR_fix_truncxfsi2;
3015#endif
3016#ifdef HAVE_fix_truncxfdi2
3017 if (HAVE_fix_truncxfdi2)
3018 fixtrunctab[(int) XFmode][(int) DImode][0] = CODE_FOR_fix_truncxfdi2;
3019#endif
3020#ifdef HAVE_fix_truncxfti2
3021 if (HAVE_fix_truncxfti2)
3022 fixtrunctab[(int) XFmode][(int) TImode][0] = CODE_FOR_fix_truncxfti2;
3023#endif
3024
3025#ifdef HAVE_fix_trunctfqi2
3026 if (HAVE_fix_trunctfqi2)
3027 fixtrunctab[(int) TFmode][(int) QImode][0] = CODE_FOR_fix_trunctfqi2;
3028#endif
3029#ifdef HAVE_fix_trunctfhi2
3030 if (HAVE_fix_trunctfhi2)
3031 fixtrunctab[(int) TFmode][(int) HImode][0] = CODE_FOR_fix_trunctfhi2;
3032#endif
3033#ifdef HAVE_fix_trunctfsi2
3034 if (HAVE_fix_trunctfsi2)
3035 fixtrunctab[(int) TFmode][(int) SImode][0] = CODE_FOR_fix_trunctfsi2;
3036#endif
3037#ifdef HAVE_fix_trunctfdi2
3038 if (HAVE_fix_trunctfdi2)
3039 fixtrunctab[(int) TFmode][(int) DImode][0] = CODE_FOR_fix_trunctfdi2;
3040#endif
3041#ifdef HAVE_fix_trunctfti2
3042 if (HAVE_fix_trunctfti2)
3043 fixtrunctab[(int) TFmode][(int) TImode][0] = CODE_FOR_fix_trunctfti2;
3044#endif
3045
3046#ifdef HAVE_fixuns_truncsfqi2
3047 if (HAVE_fixuns_truncsfqi2)
3048 fixtrunctab[(int) SFmode][(int) QImode][1] = CODE_FOR_fixuns_truncsfqi2;
3049#endif
3050#ifdef HAVE_fixuns_truncsfhi2
3051 if (HAVE_fixuns_truncsfhi2)
3052 fixtrunctab[(int) SFmode][(int) HImode][1] = CODE_FOR_fixuns_truncsfhi2;
3053#endif
3054#ifdef HAVE_fixuns_truncsfsi2
3055 if (HAVE_fixuns_truncsfsi2)
3056 fixtrunctab[(int) SFmode][(int) SImode][1] = CODE_FOR_fixuns_truncsfsi2;
3057#endif
3058#ifdef HAVE_fixuns_truncsfdi2
3059 if (HAVE_fixuns_truncsfdi2)
3060 fixtrunctab[(int) SFmode][(int) DImode][1] = CODE_FOR_fixuns_truncsfdi2;
3061#endif
3062
3063#ifdef HAVE_fixuns_truncdfqi2
3064 if (HAVE_fixuns_truncdfqi2)
3065 fixtrunctab[(int) DFmode][(int) QImode][1] = CODE_FOR_fixuns_truncdfqi2;
3066#endif
3067#ifdef HAVE_fixuns_truncdfhi2
3068 if (HAVE_fixuns_truncdfhi2)
3069 fixtrunctab[(int) DFmode][(int) HImode][1] = CODE_FOR_fixuns_truncdfhi2;
3070#endif
3071#ifdef HAVE_fixuns_truncdfsi2
3072 if (HAVE_fixuns_truncdfsi2)
3073 fixtrunctab[(int) DFmode][(int) SImode][1] = CODE_FOR_fixuns_truncdfsi2;
3074#endif
3075#ifdef HAVE_fixuns_truncdfdi2
3076 if (HAVE_fixuns_truncdfdi2)
3077 fixtrunctab[(int) DFmode][(int) DImode][1] = CODE_FOR_fixuns_truncdfdi2;
3078#endif
3079#ifdef HAVE_fixuns_truncdfti2
3080 if (HAVE_fixuns_truncdfti2)
3081 fixtrunctab[(int) DFmode][(int) TImode][1] = CODE_FOR_fixuns_truncdfti2;
3082#endif
3083
3084#ifdef HAVE_fixuns_truncxfqi2
3085 if (HAVE_fixuns_truncxfqi2)
3086 fixtrunctab[(int) XFmode][(int) QImode][1] = CODE_FOR_fixuns_truncxfqi2;
3087#endif
3088#ifdef HAVE_fixuns_truncxfhi2
3089 if (HAVE_fixuns_truncxfhi2)
3090 fixtrunctab[(int) XFmode][(int) HImode][1] = CODE_FOR_fixuns_truncxfhi2;
3091#endif
3092#ifdef HAVE_fixuns_truncxfsi2
3093 if (HAVE_fixuns_truncxfsi2)
3094 fixtrunctab[(int) XFmode][(int) SImode][1] = CODE_FOR_fixuns_truncxfsi2;
3095#endif
3096#ifdef HAVE_fixuns_truncxfdi2
3097 if (HAVE_fixuns_truncxfdi2)
3098 fixtrunctab[(int) XFmode][(int) DImode][1] = CODE_FOR_fixuns_truncxfdi2;
3099#endif
3100#ifdef HAVE_fixuns_truncxfti2
3101 if (HAVE_fixuns_truncxfti2)
3102 fixtrunctab[(int) XFmode][(int) TImode][1] = CODE_FOR_fixuns_truncxfti2;
3103#endif
3104
3105#ifdef HAVE_fixuns_trunctfqi2
3106 if (HAVE_fixuns_trunctfqi2)
3107 fixtrunctab[(int) TFmode][(int) QImode][1] = CODE_FOR_fixuns_trunctfqi2;
3108#endif
3109#ifdef HAVE_fixuns_trunctfhi2
3110 if (HAVE_fixuns_trunctfhi2)
3111 fixtrunctab[(int) TFmode][(int) HImode][1] = CODE_FOR_fixuns_trunctfhi2;
3112#endif
3113#ifdef HAVE_fixuns_trunctfsi2
3114 if (HAVE_fixuns_trunctfsi2)
3115 fixtrunctab[(int) TFmode][(int) SImode][1] = CODE_FOR_fixuns_trunctfsi2;
3116#endif
3117#ifdef HAVE_fixuns_trunctfdi2
3118 if (HAVE_fixuns_trunctfdi2)
3119 fixtrunctab[(int) TFmode][(int) DImode][1] = CODE_FOR_fixuns_trunctfdi2;
3120#endif
3121#ifdef HAVE_fixuns_trunctfti2
3122 if (HAVE_fixuns_trunctfti2)
3123 fixtrunctab[(int) TFmode][(int) TImode][1] = CODE_FOR_fixuns_trunctfti2;
3124#endif
3125
3126#ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC
3127 /* This flag says the same insns that convert to a signed fixnum
3128 also convert validly to an unsigned one. */
3129 {
3130 int i;
3131 int j;
3132 for (i = 0; i < NUM_MACHINE_MODES; i++)
3133 for (j = 0; j < NUM_MACHINE_MODES; j++)
3134 fixtrunctab[i][j][1] = fixtrunctab[i][j][0];
3135 }
3136#endif
3137}
3138
3139void
3140init_floattab ()
3141{
3142 enum insn_code *p;
3143 for (p = floattab[0][0];
3144 p < floattab[0][0] + sizeof floattab / sizeof (floattab[0][0][0]);
3145 p++)
3146 *p = CODE_FOR_nothing;
3147
3148#ifdef HAVE_floatqisf2
3149 if (HAVE_floatqisf2)
3150 floattab[(int) SFmode][(int) QImode][0] = CODE_FOR_floatqisf2;
3151#endif
3152#ifdef HAVE_floathisf2
3153 if (HAVE_floathisf2)
3154 floattab[(int) SFmode][(int) HImode][0] = CODE_FOR_floathisf2;
3155#endif
3156#ifdef HAVE_floatsisf2
3157 if (HAVE_floatsisf2)
3158 floattab[(int) SFmode][(int) SImode][0] = CODE_FOR_floatsisf2;
3159#endif
3160#ifdef HAVE_floatdisf2
3161 if (HAVE_floatdisf2)
3162 floattab[(int) SFmode][(int) DImode][0] = CODE_FOR_floatdisf2;
3163#endif
3164#ifdef HAVE_floattisf2
3165 if (HAVE_floattisf2)
3166 floattab[(int) SFmode][(int) TImode][0] = CODE_FOR_floattisf2;
3167#endif
3168
3169#ifdef HAVE_floatqidf2
3170 if (HAVE_floatqidf2)
3171 floattab[(int) DFmode][(int) QImode][0] = CODE_FOR_floatqidf2;
3172#endif
3173#ifdef HAVE_floathidf2
3174 if (HAVE_floathidf2)
3175 floattab[(int) DFmode][(int) HImode][0] = CODE_FOR_floathidf2;
3176#endif
3177#ifdef HAVE_floatsidf2
3178 if (HAVE_floatsidf2)
3179 floattab[(int) DFmode][(int) SImode][0] = CODE_FOR_floatsidf2;
3180#endif
3181#ifdef HAVE_floatdidf2
3182 if (HAVE_floatdidf2)
3183 floattab[(int) DFmode][(int) DImode][0] = CODE_FOR_floatdidf2;
3184#endif
3185#ifdef HAVE_floattidf2
3186 if (HAVE_floattidf2)
3187 floattab[(int) DFmode][(int) TImode][0] = CODE_FOR_floattidf2;
3188#endif
3189
3190#ifdef HAVE_floatqixf2
3191 if (HAVE_floatqixf2)
3192 floattab[(int) XFmode][(int) QImode][0] = CODE_FOR_floatqixf2;
3193#endif
3194#ifdef HAVE_floathixf2
3195 if (HAVE_floathixf2)
3196 floattab[(int) XFmode][(int) HImode][0] = CODE_FOR_floathixf2;
3197#endif
3198#ifdef HAVE_floatsixf2
3199 if (HAVE_floatsixf2)
3200 floattab[(int) XFmode][(int) SImode][0] = CODE_FOR_floatsixf2;
3201#endif
3202#ifdef HAVE_floatdixf2
3203 if (HAVE_floatdixf2)
3204 floattab[(int) XFmode][(int) DImode][0] = CODE_FOR_floatdixf2;
3205#endif
3206#ifdef HAVE_floattixf2
3207 if (HAVE_floattixf2)
3208 floattab[(int) XFmode][(int) TImode][0] = CODE_FOR_floattixf2;
3209#endif
3210
3211#ifdef HAVE_floatqitf2
3212 if (HAVE_floatqitf2)
3213 floattab[(int) TFmode][(int) QImode][0] = CODE_FOR_floatqitf2;
3214#endif
3215#ifdef HAVE_floathitf2
3216 if (HAVE_floathitf2)
3217 floattab[(int) TFmode][(int) HImode][0] = CODE_FOR_floathitf2;
3218#endif
3219#ifdef HAVE_floatsitf2
3220 if (HAVE_floatsitf2)
3221 floattab[(int) TFmode][(int) SImode][0] = CODE_FOR_floatsitf2;
3222#endif
3223#ifdef HAVE_floatditf2
3224 if (HAVE_floatditf2)
3225 floattab[(int) TFmode][(int) DImode][0] = CODE_FOR_floatditf2;
3226#endif
3227#ifdef HAVE_floattitf2
3228 if (HAVE_floattitf2)
3229 floattab[(int) TFmode][(int) TImode][0] = CODE_FOR_floattitf2;
3230#endif
3231
3232#ifdef HAVE_floatunsqisf2
3233 if (HAVE_floatunsqisf2)
3234 floattab[(int) SFmode][(int) QImode][1] = CODE_FOR_floatunsqisf2;
3235#endif
3236#ifdef HAVE_floatunshisf2
3237 if (HAVE_floatunshisf2)
3238 floattab[(int) SFmode][(int) HImode][1] = CODE_FOR_floatunshisf2;
3239#endif
3240#ifdef HAVE_floatunssisf2
3241 if (HAVE_floatunssisf2)
3242 floattab[(int) SFmode][(int) SImode][1] = CODE_FOR_floatunssisf2;
3243#endif
3244#ifdef HAVE_floatunsdisf2
3245 if (HAVE_floatunsdisf2)
3246 floattab[(int) SFmode][(int) DImode][1] = CODE_FOR_floatunsdisf2;
3247#endif
3248#ifdef HAVE_floatunstisf2
3249 if (HAVE_floatunstisf2)
3250 floattab[(int) SFmode][(int) TImode][1] = CODE_FOR_floatunstisf2;
3251#endif
3252
3253#ifdef HAVE_floatunsqidf2
3254 if (HAVE_floatunsqidf2)
3255 floattab[(int) DFmode][(int) QImode][1] = CODE_FOR_floatunsqidf2;
3256#endif
3257#ifdef HAVE_floatunshidf2
3258 if (HAVE_floatunshidf2)
3259 floattab[(int) DFmode][(int) HImode][1] = CODE_FOR_floatunshidf2;
3260#endif
3261#ifdef HAVE_floatunssidf2
3262 if (HAVE_floatunssidf2)
3263 floattab[(int) DFmode][(int) SImode][1] = CODE_FOR_floatunssidf2;
3264#endif
3265#ifdef HAVE_floatunsdidf2
3266 if (HAVE_floatunsdidf2)
3267 floattab[(int) DFmode][(int) DImode][1] = CODE_FOR_floatunsdidf2;
3268#endif
3269#ifdef HAVE_floatunstidf2
3270 if (HAVE_floatunstidf2)
3271 floattab[(int) DFmode][(int) TImode][1] = CODE_FOR_floatunstidf2;
3272#endif
3273
3274#ifdef HAVE_floatunsqixf2
3275 if (HAVE_floatunsqixf2)
3276 floattab[(int) XFmode][(int) QImode][1] = CODE_FOR_floatunsqixf2;
3277#endif
3278#ifdef HAVE_floatunshixf2
3279 if (HAVE_floatunshixf2)
3280 floattab[(int) XFmode][(int) HImode][1] = CODE_FOR_floatunshixf2;
3281#endif
3282#ifdef HAVE_floatunssixf2
3283 if (HAVE_floatunssixf2)
3284 floattab[(int) XFmode][(int) SImode][1] = CODE_FOR_floatunssixf2;
3285#endif
3286#ifdef HAVE_floatunsdixf2
3287 if (HAVE_floatunsdixf2)
3288 floattab[(int) XFmode][(int) DImode][1] = CODE_FOR_floatunsdixf2;
3289#endif
3290#ifdef HAVE_floatunstixf2
3291 if (HAVE_floatunstixf2)
3292 floattab[(int) XFmode][(int) TImode][1] = CODE_FOR_floatunstixf2;
3293#endif
3294
3295#ifdef HAVE_floatunsqitf2
3296 if (HAVE_floatunsqitf2)
3297 floattab[(int) TFmode][(int) QImode][1] = CODE_FOR_floatunsqitf2;
3298#endif
3299#ifdef HAVE_floatunshitf2
3300 if (HAVE_floatunshitf2)
3301 floattab[(int) TFmode][(int) HImode][1] = CODE_FOR_floatunshitf2;
3302#endif
3303#ifdef HAVE_floatunssitf2
3304 if (HAVE_floatunssitf2)
3305 floattab[(int) TFmode][(int) SImode][1] = CODE_FOR_floatunssitf2;
3306#endif
3307#ifdef HAVE_floatunsditf2
3308 if (HAVE_floatunsditf2)
3309 floattab[(int) TFmode][(int) DImode][1] = CODE_FOR_floatunsditf2;
3310#endif
3311#ifdef HAVE_floatunstitf2
3312 if (HAVE_floatunstitf2)
3313 floattab[(int) TFmode][(int) TImode][1] = CODE_FOR_floatunstitf2;
3314#endif
3315}
3316\f
3317/* Generate code to convert FROM to floating point
3318 and store in TO. FROM must be fixed point and not VOIDmode.
3319 UNSIGNEDP nonzero means regard FROM as unsigned.
3320 Normally this is done by correcting the final value
3321 if it is negative. */
3322
3323void
3324expand_float (to, from, unsignedp)
3325 rtx to, from;
3326 int unsignedp;
3327{
3328 enum insn_code icode;
3329 register rtx target = to;
3330 enum machine_mode fmode, imode;
3331
3332 /* Crash now, because we won't be able to decide which mode to use. */
3333 if (GET_MODE (from) == VOIDmode)
3334 abort ();
3335
3336 /* Look for an insn to do the conversion. Do it in the specified
3337 modes if possible; otherwise convert either input, output or both to
3338 wider mode. If the integer mode is wider than the mode of FROM,
3339 we can do the conversion signed even if the input is unsigned. */
3340
3341 for (imode = GET_MODE (from); imode != VOIDmode;
3342 imode = GET_MODE_WIDER_MODE (imode))
3343 for (fmode = GET_MODE (to); fmode != VOIDmode;
3344 fmode = GET_MODE_WIDER_MODE (fmode))
3345 {
3346 int doing_unsigned = unsignedp;
3347
3348 icode = can_float_p (fmode, imode, unsignedp);
3349 if (icode == CODE_FOR_nothing && imode != GET_MODE (from) && unsignedp)
3350 icode = can_float_p (fmode, imode, 0), doing_unsigned = 0;
3351
3352 if (icode != CODE_FOR_nothing)
3353 {
3354 to = protect_from_queue (to, 1);
3355 from = protect_from_queue (from, 0);
3356
3357 if (imode != GET_MODE (from))
3358 from = convert_to_mode (imode, from, unsignedp);
3359
3360 if (fmode != GET_MODE (to))
3361 target = gen_reg_rtx (fmode);
3362
3363 emit_unop_insn (icode, target, from,
3364 doing_unsigned ? UNSIGNED_FLOAT : FLOAT);
3365
3366 if (target != to)
3367 convert_move (to, target, 0);
3368 return;
3369 }
3370 }
3371
3372#if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
3373
3374 /* Unsigned integer, and no way to convert directly.
3375 Convert as signed, then conditionally adjust the result. */
3376 if (unsignedp)
3377 {
3378 rtx label = gen_label_rtx ();
3379 rtx temp;
3380 REAL_VALUE_TYPE offset;
3381
3382 emit_queue ();
3383
3384 to = protect_from_queue (to, 1);
3385 from = protect_from_queue (from, 0);
3386
3387 if (flag_force_mem)
3388 from = force_not_mem (from);
3389
3390 /* If we are about to do some arithmetic to correct for an
3391 unsigned operand, do it in a pseudo-register. */
3392
3393 if (GET_CODE (to) != REG || REGNO (to) <= LAST_VIRTUAL_REGISTER)
3394 target = gen_reg_rtx (GET_MODE (to));
3395
3396 /* Convert as signed integer to floating. */
3397 expand_float (target, from, 0);
3398
3399 /* If FROM is negative (and therefore TO is negative),
3400 correct its value by 2**bitwidth. */
3401
3402 do_pending_stack_adjust ();
3403 emit_cmp_insn (from, const0_rtx, GE, NULL_RTX, GET_MODE (from), 0, 0);
3404 emit_jump_insn (gen_bge (label));
3405 /* On SCO 3.2.1, ldexp rejects values outside [0.5, 1).
3406 Rather than setting up a dconst_dot_5, let's hope SCO
3407 fixes the bug. */
3408 offset = REAL_VALUE_LDEXP (dconst1, GET_MODE_BITSIZE (GET_MODE (from)));
3409 temp = expand_binop (GET_MODE (to), add_optab, target,
3410 immed_real_const_1 (offset, GET_MODE (to)),
3411 target, 0, OPTAB_LIB_WIDEN);
3412 if (temp != target)
3413 emit_move_insn (target, temp);
3414 do_pending_stack_adjust ();
3415 emit_label (label);
3416 }
3417 else
3418#endif
3419
3420 /* No hardware instruction available; call a library rotine to convert from
3421 SImode, DImode, or TImode into SFmode, DFmode, XFmode, or TFmode. */
3422 {
3423 rtx libfcn;
3424 rtx insns;
3425
3426 to = protect_from_queue (to, 1);
3427 from = protect_from_queue (from, 0);
3428
3429 if (GET_MODE_SIZE (GET_MODE (from)) < GET_MODE_SIZE (SImode))
3430 from = convert_to_mode (SImode, from, unsignedp);
3431
3432 if (flag_force_mem)
3433 from = force_not_mem (from);
3434
3435 if (GET_MODE (to) == SFmode)
3436 {
3437 if (GET_MODE (from) == SImode)
3438 libfcn = floatsisf_libfunc;
3439 else if (GET_MODE (from) == DImode)
3440 libfcn = floatdisf_libfunc;
3441 else if (GET_MODE (from) == TImode)
3442 libfcn = floattisf_libfunc;
3443 else
3444 abort ();
3445 }
3446 else if (GET_MODE (to) == DFmode)
3447 {
3448 if (GET_MODE (from) == SImode)
3449 libfcn = floatsidf_libfunc;
3450 else if (GET_MODE (from) == DImode)
3451 libfcn = floatdidf_libfunc;
3452 else if (GET_MODE (from) == TImode)
3453 libfcn = floattidf_libfunc;
3454 else
3455 abort ();
3456 }
3457 else if (GET_MODE (to) == XFmode)
3458 {
3459 if (GET_MODE (from) == SImode)
3460 libfcn = floatsixf_libfunc;
3461 else if (GET_MODE (from) == DImode)
3462 libfcn = floatdixf_libfunc;
3463 else if (GET_MODE (from) == TImode)
3464 libfcn = floattixf_libfunc;
3465 else
3466 abort ();
3467 }
3468 else if (GET_MODE (to) == TFmode)
3469 {
3470 if (GET_MODE (from) == SImode)
3471 libfcn = floatsitf_libfunc;
3472 else if (GET_MODE (from) == DImode)
3473 libfcn = floatditf_libfunc;
3474 else if (GET_MODE (from) == TImode)
3475 libfcn = floattitf_libfunc;
3476 else
3477 abort ();
3478 }
3479 else
3480 abort ();
3481
3482 start_sequence ();
3483
3484 emit_library_call (libfcn, 1, GET_MODE (to), 1, from, GET_MODE (from));
3485 insns = get_insns ();
3486 end_sequence ();
3487
3488 emit_libcall_block (insns, target, hard_libcall_value (GET_MODE (to)),
3489 gen_rtx (FLOAT, GET_MODE (to), from));
3490 }
3491
3492 /* Copy result to requested destination
3493 if we have been computing in a temp location. */
3494
3495 if (target != to)
3496 {
3497 if (GET_MODE (target) == GET_MODE (to))
3498 emit_move_insn (to, target);
3499 else
3500 convert_move (to, target, 0);
3501 }
3502}
3503\f
3504/* expand_fix: generate code to convert FROM to fixed point
3505 and store in TO. FROM must be floating point. */
3506
3507static rtx
3508ftruncify (x)
3509 rtx x;
3510{
3511 rtx temp = gen_reg_rtx (GET_MODE (x));
3512 return expand_unop (GET_MODE (x), ftrunc_optab, x, temp, 0);
3513}
3514
3515void
3516expand_fix (to, from, unsignedp)
3517 register rtx to, from;
3518 int unsignedp;
3519{
3520 enum insn_code icode;
3521 register rtx target = to;
3522 enum machine_mode fmode, imode;
3523 int must_trunc = 0;
3524 rtx libfcn = 0;
3525
3526 /* We first try to find a pair of modes, one real and one integer, at
3527 least as wide as FROM and TO, respectively, in which we can open-code
3528 this conversion. If the integer mode is wider than the mode of TO,
3529 we can do the conversion either signed or unsigned. */
3530
3531 for (imode = GET_MODE (to); imode != VOIDmode;
3532 imode = GET_MODE_WIDER_MODE (imode))
3533 for (fmode = GET_MODE (from); fmode != VOIDmode;
3534 fmode = GET_MODE_WIDER_MODE (fmode))
3535 {
3536 int doing_unsigned = unsignedp;
3537
3538 icode = can_fix_p (imode, fmode, unsignedp, &must_trunc);
3539 if (icode == CODE_FOR_nothing && imode != GET_MODE (to) && unsignedp)
3540 icode = can_fix_p (imode, fmode, 0, &must_trunc), doing_unsigned = 0;
3541
3542 if (icode != CODE_FOR_nothing)
3543 {
3544 to = protect_from_queue (to, 1);
3545 from = protect_from_queue (from, 0);
3546
3547 if (fmode != GET_MODE (from))
3548 from = convert_to_mode (fmode, from, 0);
3549
3550 if (must_trunc)
3551 from = ftruncify (from);
3552
3553 if (imode != GET_MODE (to))
3554 target = gen_reg_rtx (imode);
3555
3556 emit_unop_insn (icode, target, from,
3557 doing_unsigned ? UNSIGNED_FIX : FIX);
3558 if (target != to)
3559 convert_move (to, target, unsignedp);
3560 return;
3561 }
3562 }
3563
3564#if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
3565 /* For an unsigned conversion, there is one more way to do it.
3566 If we have a signed conversion, we generate code that compares
3567 the real value to the largest representable positive number. If if
3568 is smaller, the conversion is done normally. Otherwise, subtract
3569 one plus the highest signed number, convert, and add it back.
3570
3571 We only need to check all real modes, since we know we didn't find
3572 anything with a wider integer mode. */
3573
3574 if (unsignedp && GET_MODE_BITSIZE (GET_MODE (to)) <= HOST_BITS_PER_WIDE_INT)
3575 for (fmode = GET_MODE (from); fmode != VOIDmode;
3576 fmode = GET_MODE_WIDER_MODE (fmode))
3577 /* Make sure we won't lose significant bits doing this. */
3578 if (GET_MODE_BITSIZE (fmode) > GET_MODE_BITSIZE (GET_MODE (to))
3579 && CODE_FOR_nothing != can_fix_p (GET_MODE (to), fmode, 0,
3580 &must_trunc))
3581 {
3582 int bitsize = GET_MODE_BITSIZE (GET_MODE (to));
3583 REAL_VALUE_TYPE offset = REAL_VALUE_LDEXP (dconst1, bitsize - 1);
3584 rtx limit = immed_real_const_1 (offset, fmode);
3585 rtx lab1 = gen_label_rtx ();
3586 rtx lab2 = gen_label_rtx ();
3587 rtx insn;
3588
3589 emit_queue ();
3590 to = protect_from_queue (to, 1);
3591 from = protect_from_queue (from, 0);
3592
3593 if (flag_force_mem)
3594 from = force_not_mem (from);
3595
3596 if (fmode != GET_MODE (from))
3597 from = convert_to_mode (fmode, from, 0);
3598
3599 /* See if we need to do the subtraction. */
3600 do_pending_stack_adjust ();
3601 emit_cmp_insn (from, limit, GE, NULL_RTX, GET_MODE (from), 0, 0);
3602 emit_jump_insn (gen_bge (lab1));
3603
3604 /* If not, do the signed "fix" and branch around fixup code. */
3605 expand_fix (to, from, 0);
3606 emit_jump_insn (gen_jump (lab2));
3607 emit_barrier ();
3608
3609 /* Otherwise, subtract 2**(N-1), convert to signed number,
3610 then add 2**(N-1). Do the addition using XOR since this
3611 will often generate better code. */
3612 emit_label (lab1);
3613 target = expand_binop (GET_MODE (from), sub_optab, from, limit,
3614 NULL_RTX, 0, OPTAB_LIB_WIDEN);
3615 expand_fix (to, target, 0);
3616 target = expand_binop (GET_MODE (to), xor_optab, to,
3617 GEN_INT ((HOST_WIDE_INT) 1 << (bitsize - 1)),
3618 to, 1, OPTAB_LIB_WIDEN);
3619
3620 if (target != to)
3621 emit_move_insn (to, target);
3622
3623 emit_label (lab2);
3624
3625 /* Make a place for a REG_NOTE and add it. */
3626 insn = emit_move_insn (to, to);
3627 REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL,
3628 gen_rtx (UNSIGNED_FIX, GET_MODE (to),
3629 from), REG_NOTES (insn));
3630
3631 return;
3632 }
3633#endif
3634
3635 /* We can't do it with an insn, so use a library call. But first ensure
3636 that the mode of TO is at least as wide as SImode, since those are the
3637 only library calls we know about. */
3638
3639 if (GET_MODE_SIZE (GET_MODE (to)) < GET_MODE_SIZE (SImode))
3640 {
3641 target = gen_reg_rtx (SImode);
3642
3643 expand_fix (target, from, unsignedp);
3644 }
3645 else if (GET_MODE (from) == SFmode)
3646 {
3647 if (GET_MODE (to) == SImode)
3648 libfcn = unsignedp ? fixunssfsi_libfunc : fixsfsi_libfunc;
3649 else if (GET_MODE (to) == DImode)
3650 libfcn = unsignedp ? fixunssfdi_libfunc : fixsfdi_libfunc;
3651 else if (GET_MODE (to) == TImode)
3652 libfcn = unsignedp ? fixunssfti_libfunc : fixsfti_libfunc;
3653 else
3654 abort ();
3655 }
3656 else if (GET_MODE (from) == DFmode)
3657 {
3658 if (GET_MODE (to) == SImode)
3659 libfcn = unsignedp ? fixunsdfsi_libfunc : fixdfsi_libfunc;
3660 else if (GET_MODE (to) == DImode)
3661 libfcn = unsignedp ? fixunsdfdi_libfunc : fixdfdi_libfunc;
3662 else if (GET_MODE (to) == TImode)
3663 libfcn = unsignedp ? fixunsdfti_libfunc : fixdfti_libfunc;
3664 else
3665 abort ();
3666 }
3667 else if (GET_MODE (from) == XFmode)
3668 {
3669 if (GET_MODE (to) == SImode)
3670 libfcn = unsignedp ? fixunsxfsi_libfunc : fixxfsi_libfunc;
3671 else if (GET_MODE (to) == DImode)
3672 libfcn = unsignedp ? fixunsxfdi_libfunc : fixxfdi_libfunc;
3673 else if (GET_MODE (to) == TImode)
3674 libfcn = unsignedp ? fixunsxfti_libfunc : fixxfti_libfunc;
3675 else
3676 abort ();
3677 }
3678 else if (GET_MODE (from) == TFmode)
3679 {
3680 if (GET_MODE (to) == SImode)
3681 libfcn = unsignedp ? fixunstfsi_libfunc : fixtfsi_libfunc;
3682 else if (GET_MODE (to) == DImode)
3683 libfcn = unsignedp ? fixunstfdi_libfunc : fixtfdi_libfunc;
3684 else if (GET_MODE (to) == TImode)
3685 libfcn = unsignedp ? fixunstfti_libfunc : fixtfti_libfunc;
3686 else
3687 abort ();
3688 }
3689 else
3690 abort ();
3691
3692 if (libfcn)
3693 {
3694 rtx insns;
3695
3696 to = protect_from_queue (to, 1);
3697 from = protect_from_queue (from, 0);
3698
3699 if (flag_force_mem)
3700 from = force_not_mem (from);
3701
3702 start_sequence ();
3703
3704 emit_library_call (libfcn, 1, GET_MODE (to), 1, from, GET_MODE (from));
3705 insns = get_insns ();
3706 end_sequence ();
3707
3708 emit_libcall_block (insns, target, hard_libcall_value (GET_MODE (to)),
3709 gen_rtx (unsignedp ? FIX : UNSIGNED_FIX,
3710 GET_MODE (to), from));
3711 }
3712
3713 if (GET_MODE (to) == GET_MODE (target))
3714 emit_move_insn (to, target);
3715 else
3716 convert_move (to, target, 0);
3717}
3718\f
3719static optab
3720init_optab (code)
3721 enum rtx_code code;
3722{
3723 int i;
3724 optab op = (optab) xmalloc (sizeof (struct optab));
3725 op->code = code;
3726 for (i = 0; i < NUM_MACHINE_MODES; i++)
3727 {
3728 op->handlers[i].insn_code = CODE_FOR_nothing;
3729 op->handlers[i].libfunc = 0;
3730 }
3731 return op;
3732}
3733
3734/* Initialize the libfunc fields of an entire group of entries in some
3735 optab. Each entry is set equal to a string consisting of a leading
3736 pair of underscores followed by a generic operation name followed by
3737 a mode name (downshifted to lower case) followed by a single character
3738 representing the number of operands for the given operation (which is
3739 usually one of the characters '2', '3', or '4').
3740
3741 OPTABLE is the table in which libfunc fields are to be initialized.
3742 FIRST_MODE is the first machine mode index in the given optab to
3743 initialize.
3744 LAST_MODE is the last machine mode index in the given optab to
3745 initialize.
3746 OPNAME is the generic (string) name of the operation.
3747 SUFFIX is the character which specifies the number of operands for
3748 the given generic operation.
3749*/
3750
3751static void
3752init_libfuncs (optable, first_mode, last_mode, opname, suffix)
3753 register optab optable;
3754 register char *opname;
3755 register enum machine_mode first_mode;
3756 register enum machine_mode last_mode;
3757 register char suffix;
3758{
3759 register enum machine_mode mode;
3760 register unsigned opname_len = strlen (opname);
3761
3762 for (mode = first_mode; (int) mode <= (int) last_mode;
3763 mode = (enum machine_mode) ((int) mode + 1))
3764 {
3765 register char *mname = mode_name[(int) mode];
3766 register unsigned mname_len = strlen (mname);
3767 register char *libfunc_name
3768 = (char *) xmalloc (2 + opname_len + mname_len + 1 + 1);
3769 register char *p;
3770 register char *q;
3771
3772 p = libfunc_name;
3773 *p++ = '_';
3774 *p++ = '_';
3775 for (q = opname; *q; )
3776 *p++ = *q++;
3777 for (q = mname; *q; q++)
3778 *p++ = tolower (*q);
3779 *p++ = suffix;
3780 *p++ = '\0';
3781 optable->handlers[(int) mode].libfunc
3782 = gen_rtx (SYMBOL_REF, Pmode, libfunc_name);
3783 }
3784}
3785
3786/* Initialize the libfunc fields of an entire group of entries in some
3787 optab which correspond to all integer mode operations. The parameters
3788 have the same meaning as similarly named ones for the `init_libfuncs'
3789 routine. (See above). */
3790
3791static void
3792init_integral_libfuncs (optable, opname, suffix)
3793 register optab optable;
3794 register char *opname;
3795 register char suffix;
3796{
3797 init_libfuncs (optable, SImode, TImode, opname, suffix);
3798}
3799
3800/* Initialize the libfunc fields of an entire group of entries in some
3801 optab which correspond to all real mode operations. The parameters
3802 have the same meaning as similarly named ones for the `init_libfuncs'
3803 routine. (See above). */
3804
3805static void
3806init_floating_libfuncs (optable, opname, suffix)
3807 register optab optable;
3808 register char *opname;
3809 register char suffix;
3810{
3811 init_libfuncs (optable, SFmode, TFmode, opname, suffix);
3812}
3813
3814/* Initialize the libfunc fields of an entire group of entries in some
3815 optab which correspond to all complex floating modes. The parameters
3816 have the same meaning as similarly named ones for the `init_libfuncs'
3817 routine. (See above). */
3818
3819static void
3820init_complex_libfuncs (optable, opname, suffix)
3821 register optab optable;
3822 register char *opname;
3823 register char suffix;
3824{
3825 init_libfuncs (optable, SCmode, TCmode, opname, suffix);
3826}
3827
3828/* Call this once to initialize the contents of the optabs
3829 appropriately for the current target machine. */
3830
3831void
3832init_optabs ()
3833{
3834 int i;
3835
3836 init_fixtab ();
3837 init_floattab ();
3838 init_extends ();
3839
3840 add_optab = init_optab (PLUS);
3841 sub_optab = init_optab (MINUS);
3842 smul_optab = init_optab (MULT);
3843 smul_widen_optab = init_optab (UNKNOWN);
3844 umul_widen_optab = init_optab (UNKNOWN);
3845 sdiv_optab = init_optab (DIV);
3846 sdivmod_optab = init_optab (UNKNOWN);
3847 udiv_optab = init_optab (UDIV);
3848 udivmod_optab = init_optab (UNKNOWN);
3849 smod_optab = init_optab (MOD);
3850 umod_optab = init_optab (UMOD);
3851 flodiv_optab = init_optab (DIV);
3852 ftrunc_optab = init_optab (UNKNOWN);
3853 and_optab = init_optab (AND);
3854 ior_optab = init_optab (IOR);
3855 xor_optab = init_optab (XOR);
3856 ashl_optab = init_optab (ASHIFT);
3857 ashr_optab = init_optab (ASHIFTRT);
3858 lshl_optab = init_optab (LSHIFT);
3859 lshr_optab = init_optab (LSHIFTRT);
3860 rotl_optab = init_optab (ROTATE);
3861 rotr_optab = init_optab (ROTATERT);
3862 smin_optab = init_optab (SMIN);
3863 smax_optab = init_optab (SMAX);
3864 umin_optab = init_optab (UMIN);
3865 umax_optab = init_optab (UMAX);
3866 mov_optab = init_optab (UNKNOWN);
3867 movstrict_optab = init_optab (UNKNOWN);
3868 cmp_optab = init_optab (UNKNOWN);
3869 ucmp_optab = init_optab (UNKNOWN);
3870 tst_optab = init_optab (UNKNOWN);
3871 neg_optab = init_optab (NEG);
3872 abs_optab = init_optab (ABS);
3873 one_cmpl_optab = init_optab (NOT);
3874 ffs_optab = init_optab (FFS);
3875 sqrt_optab = init_optab (SQRT);
3876 sin_optab = init_optab (UNKNOWN);
3877 cos_optab = init_optab (UNKNOWN);
3878 strlen_optab = init_optab (UNKNOWN);
3879
3880#ifdef HAVE_addqi3
3881 if (HAVE_addqi3)
3882 add_optab->handlers[(int) QImode].insn_code = CODE_FOR_addqi3;
3883#endif
3884#ifdef HAVE_addhi3
3885 if (HAVE_addhi3)
3886 add_optab->handlers[(int) HImode].insn_code = CODE_FOR_addhi3;
3887#endif
3888#ifdef HAVE_addpsi3
3889 if (HAVE_addpsi3)
3890 add_optab->handlers[(int) PSImode].insn_code = CODE_FOR_addpsi3;
3891#endif
3892#ifdef HAVE_addsi3
3893 if (HAVE_addsi3)
3894 add_optab->handlers[(int) SImode].insn_code = CODE_FOR_addsi3;
3895#endif
3896#ifdef HAVE_adddi3
3897 if (HAVE_adddi3)
3898 add_optab->handlers[(int) DImode].insn_code = CODE_FOR_adddi3;
3899#endif
3900#ifdef HAVE_addti3
3901 if (HAVE_addti3)
3902 add_optab->handlers[(int) TImode].insn_code = CODE_FOR_addti3;
3903#endif
3904#ifdef HAVE_addsf3
3905 if (HAVE_addsf3)
3906 add_optab->handlers[(int) SFmode].insn_code = CODE_FOR_addsf3;
3907#endif
3908#ifdef HAVE_adddf3
3909 if (HAVE_adddf3)
3910 add_optab->handlers[(int) DFmode].insn_code = CODE_FOR_adddf3;
3911#endif
3912#ifdef HAVE_addxf3
3913 if (HAVE_addxf3)
3914 add_optab->handlers[(int) XFmode].insn_code = CODE_FOR_addxf3;
3915#endif
3916#ifdef HAVE_addtf3
3917 if (HAVE_addtf3)
3918 add_optab->handlers[(int) TFmode].insn_code = CODE_FOR_addtf3;
3919#endif
3920 init_integral_libfuncs (add_optab, "add", '3');
3921 init_floating_libfuncs (add_optab, "add", '3');
3922
3923#ifdef HAVE_subqi3
3924 if (HAVE_subqi3)
3925 sub_optab->handlers[(int) QImode].insn_code = CODE_FOR_subqi3;
3926#endif
3927#ifdef HAVE_subhi3
3928 if (HAVE_subhi3)
3929 sub_optab->handlers[(int) HImode].insn_code = CODE_FOR_subhi3;
3930#endif
3931#ifdef HAVE_subpsi3
3932 if (HAVE_subpsi3)
3933 sub_optab->handlers[(int) PSImode].insn_code = CODE_FOR_subpsi3;
3934#endif
3935#ifdef HAVE_subsi3
3936 if (HAVE_subsi3)
3937 sub_optab->handlers[(int) SImode].insn_code = CODE_FOR_subsi3;
3938#endif
3939#ifdef HAVE_subdi3
3940 if (HAVE_subdi3)
3941 sub_optab->handlers[(int) DImode].insn_code = CODE_FOR_subdi3;
3942#endif
3943#ifdef HAVE_subti3
3944 if (HAVE_subti3)
3945 sub_optab->handlers[(int) TImode].insn_code = CODE_FOR_subti3;
3946#endif
3947#ifdef HAVE_subsf3
3948 if (HAVE_subsf3)
3949 sub_optab->handlers[(int) SFmode].insn_code = CODE_FOR_subsf3;
3950#endif
3951#ifdef HAVE_subdf3
3952 if (HAVE_subdf3)
3953 sub_optab->handlers[(int) DFmode].insn_code = CODE_FOR_subdf3;
3954#endif
3955#ifdef HAVE_subxf3
3956 if (HAVE_subxf3)
3957 sub_optab->handlers[(int) XFmode].insn_code = CODE_FOR_subxf3;
3958#endif
3959#ifdef HAVE_subtf3
3960 if (HAVE_subtf3)
3961 sub_optab->handlers[(int) TFmode].insn_code = CODE_FOR_subtf3;
3962#endif
3963 init_integral_libfuncs (sub_optab, "sub", '3');
3964 init_floating_libfuncs (sub_optab, "sub", '3');
3965
3966#ifdef HAVE_mulqi3
3967 if (HAVE_mulqi3)
3968 smul_optab->handlers[(int) QImode].insn_code = CODE_FOR_mulqi3;
3969#endif
3970#ifdef HAVE_mulhi3
3971 if (HAVE_mulhi3)
3972 smul_optab->handlers[(int) HImode].insn_code = CODE_FOR_mulhi3;
3973#endif
3974#ifdef HAVE_mulpsi3
3975 if (HAVE_mulpsi3)
3976 smul_optab->handlers[(int) PSImode].insn_code = CODE_FOR_mulpsi3;
3977#endif
3978#ifdef HAVE_mulsi3
3979 if (HAVE_mulsi3)
3980 smul_optab->handlers[(int) SImode].insn_code = CODE_FOR_mulsi3;
3981#endif
3982#ifdef HAVE_muldi3
3983 if (HAVE_muldi3)
3984 smul_optab->handlers[(int) DImode].insn_code = CODE_FOR_muldi3;
3985#endif
3986#ifdef HAVE_multi3
3987 if (HAVE_multi3)
3988 smul_optab->handlers[(int) TImode].insn_code = CODE_FOR_multi3;
3989#endif
3990#ifdef HAVE_mulsf3
3991 if (HAVE_mulsf3)
3992 smul_optab->handlers[(int) SFmode].insn_code = CODE_FOR_mulsf3;
3993#endif
3994#ifdef HAVE_muldf3
3995 if (HAVE_muldf3)
3996 smul_optab->handlers[(int) DFmode].insn_code = CODE_FOR_muldf3;
3997#endif
3998#ifdef HAVE_mulxf3
3999 if (HAVE_mulxf3)
4000 smul_optab->handlers[(int) XFmode].insn_code = CODE_FOR_mulxf3;
4001#endif
4002#ifdef HAVE_multf3
4003 if (HAVE_multf3)
4004 smul_optab->handlers[(int) TFmode].insn_code = CODE_FOR_multf3;
4005#endif
4006 init_integral_libfuncs (smul_optab, "mul", '3');
4007 init_floating_libfuncs (smul_optab, "mul", '3');
4008
4009#ifdef MULSI3_LIBCALL
4010 smul_optab->handlers[(int) SImode].libfunc
4011 = gen_rtx (SYMBOL_REF, Pmode, MULSI3_LIBCALL);
4012#endif
4013#ifdef MULDI3_LIBCALL
4014 smul_optab->handlers[(int) DImode].libfunc
4015 = gen_rtx (SYMBOL_REF, Pmode, MULDI3_LIBCALL);
4016#endif
4017#ifdef MULTI3_LIBCALL
4018 smul_optab->handlers[(int) TImode].libfunc
4019 = gen_rtx (SYMBOL_REF, Pmode, MULTI3_LIBCALL);
4020#endif
4021
4022#ifdef HAVE_mulqihi3
4023 if (HAVE_mulqihi3)
4024 smul_widen_optab->handlers[(int) HImode].insn_code = CODE_FOR_mulqihi3;
4025#endif
4026#ifdef HAVE_mulhisi3
4027 if (HAVE_mulhisi3)
4028 smul_widen_optab->handlers[(int) SImode].insn_code = CODE_FOR_mulhisi3;
4029#endif
4030#ifdef HAVE_mulsidi3
4031 if (HAVE_mulsidi3)
4032 smul_widen_optab->handlers[(int) DImode].insn_code = CODE_FOR_mulsidi3;
4033#endif
4034#ifdef HAVE_mulditi3
4035 if (HAVE_mulditi3)
4036 smul_widen_optab->handlers[(int) TImode].insn_code = CODE_FOR_mulditi3;
4037#endif
4038
4039#ifdef HAVE_umulqihi3
4040 if (HAVE_umulqihi3)
4041 umul_widen_optab->handlers[(int) HImode].insn_code = CODE_FOR_umulqihi3;
4042#endif
4043#ifdef HAVE_umulhisi3
4044 if (HAVE_umulhisi3)
4045 umul_widen_optab->handlers[(int) SImode].insn_code = CODE_FOR_umulhisi3;
4046#endif
4047#ifdef HAVE_umulsidi3
4048 if (HAVE_umulsidi3)
4049 umul_widen_optab->handlers[(int) DImode].insn_code = CODE_FOR_umulsidi3;
4050#endif
4051#ifdef HAVE_umulditi3
4052 if (HAVE_umulditi3)
4053 umul_widen_optab->handlers[(int) TImode].insn_code = CODE_FOR_umulditi3;
4054#endif
4055
4056#ifdef HAVE_divqi3
4057 if (HAVE_divqi3)
4058 sdiv_optab->handlers[(int) QImode].insn_code = CODE_FOR_divqi3;
4059#endif
4060#ifdef HAVE_divhi3
4061 if (HAVE_divhi3)
4062 sdiv_optab->handlers[(int) HImode].insn_code = CODE_FOR_divhi3;
4063#endif
4064#ifdef HAVE_divpsi3
4065 if (HAVE_divpsi3)
4066 sdiv_optab->handlers[(int) PSImode].insn_code = CODE_FOR_divpsi3;
4067#endif
4068#ifdef HAVE_divsi3
4069 if (HAVE_divsi3)
4070 sdiv_optab->handlers[(int) SImode].insn_code = CODE_FOR_divsi3;
4071#endif
4072#ifdef HAVE_divdi3
4073 if (HAVE_divdi3)
4074 sdiv_optab->handlers[(int) DImode].insn_code = CODE_FOR_divdi3;
4075#endif
4076#ifdef HAVE_divti3
4077 if (HAVE_divti3)
4078 sdiv_optab->handlers[(int) TImode].insn_code = CODE_FOR_divti3;
4079#endif
4080 init_integral_libfuncs (sdiv_optab, "div", '3');
4081
4082#ifdef DIVSI3_LIBCALL
4083 sdiv_optab->handlers[(int) SImode].libfunc
4084 = gen_rtx (SYMBOL_REF, Pmode, DIVSI3_LIBCALL);
4085#endif
4086#ifdef DIVDI3_LIBCALL
4087 sdiv_optab->handlers[(int) DImode].libfunc
4088 = gen_rtx (SYMBOL_REF, Pmode, DIVDI3_LIBCALL);
4089#endif
4090#ifdef DIVTI3_LIBCALL
4091 sdiv_optab->handlers[(int) TImode].libfunc
4092 = gen_rtx (SYMBOL_REF, Pmode, DIVTI3_LIBCALL);
4093#endif
4094
4095#ifdef HAVE_udivqi3
4096 if (HAVE_udivqi3)
4097 udiv_optab->handlers[(int) QImode].insn_code = CODE_FOR_udivqi3;
4098#endif
4099#ifdef HAVE_udivhi3
4100 if (HAVE_udivhi3)
4101 udiv_optab->handlers[(int) HImode].insn_code = CODE_FOR_udivhi3;
4102#endif
4103#ifdef HAVE_udivpsi3
4104 if (HAVE_udivpsi3)
4105 udiv_optab->handlers[(int) PSImode].insn_code = CODE_FOR_udivpsi3;
4106#endif
4107#ifdef HAVE_udivsi3
4108 if (HAVE_udivsi3)
4109 udiv_optab->handlers[(int) SImode].insn_code = CODE_FOR_udivsi3;
4110#endif
4111#ifdef HAVE_udivdi3
4112 if (HAVE_udivdi3)
4113 udiv_optab->handlers[(int) DImode].insn_code = CODE_FOR_udivdi3;
4114#endif
4115#ifdef HAVE_udivti3
4116 if (HAVE_udivti3)
4117 udiv_optab->handlers[(int) TImode].insn_code = CODE_FOR_udivti3;
4118#endif
4119 init_integral_libfuncs (udiv_optab, "udiv", '3');
4120
4121#ifdef UDIVSI3_LIBCALL
4122 udiv_optab->handlers[(int) SImode].libfunc
4123 = gen_rtx (SYMBOL_REF, Pmode, UDIVSI3_LIBCALL);
4124#endif
4125#ifdef UDIVDI3_LIBCALL
4126 udiv_optab->handlers[(int) DImode].libfunc
4127 = gen_rtx (SYMBOL_REF, Pmode, UDIVDI3_LIBCALL);
4128#endif
4129#ifdef UDIVTI3_LIBCALL
4130 udiv_optab->handlers[(int) TImode].libfunc
4131 = gen_rtx (SYMBOL_REF, Pmode, UDIVTI3_LIBCALL);
4132#endif
4133
4134#ifdef HAVE_divmodqi4
4135 if (HAVE_divmodqi4)
4136 sdivmod_optab->handlers[(int) QImode].insn_code = CODE_FOR_divmodqi4;
4137#endif
4138#ifdef HAVE_divmodhi4
4139 if (HAVE_divmodhi4)
4140 sdivmod_optab->handlers[(int) HImode].insn_code = CODE_FOR_divmodhi4;
4141#endif
4142#ifdef HAVE_divmodsi4
4143 if (HAVE_divmodsi4)
4144 sdivmod_optab->handlers[(int) SImode].insn_code = CODE_FOR_divmodsi4;
4145#endif
4146#ifdef HAVE_divmoddi4
4147 if (HAVE_divmoddi4)
4148 sdivmod_optab->handlers[(int) DImode].insn_code = CODE_FOR_divmoddi4;
4149#endif
4150#ifdef HAVE_divmodti4
4151 if (HAVE_divmodti4)
4152 sdivmod_optab->handlers[(int) TImode].insn_code = CODE_FOR_divmodti4;
4153#endif
4154 init_integral_libfuncs (sdivmod_optab, "divmod", '4');
4155
4156#ifdef HAVE_udivmodqi4
4157 if (HAVE_udivmodqi4)
4158 udivmod_optab->handlers[(int) QImode].insn_code = CODE_FOR_udivmodqi4;
4159#endif
4160#ifdef HAVE_udivmodhi4
4161 if (HAVE_udivmodhi4)
4162 udivmod_optab->handlers[(int) HImode].insn_code = CODE_FOR_udivmodhi4;
4163#endif
4164#ifdef HAVE_udivmodsi4
4165 if (HAVE_udivmodsi4)
4166 udivmod_optab->handlers[(int) SImode].insn_code = CODE_FOR_udivmodsi4;
4167#endif
4168#ifdef HAVE_udivmoddi4
4169 if (HAVE_udivmoddi4)
4170 udivmod_optab->handlers[(int) DImode].insn_code = CODE_FOR_udivmoddi4;
4171#endif
4172#ifdef HAVE_udivmodti4
4173 if (HAVE_udivmodti4)
4174 udivmod_optab->handlers[(int) TImode].insn_code = CODE_FOR_udivmodti4;
4175#endif
4176 init_integral_libfuncs (udivmod_optab, "udivmod", '4');
4177
4178#ifdef HAVE_modqi3
4179 if (HAVE_modqi3)
4180 smod_optab->handlers[(int) QImode].insn_code = CODE_FOR_modqi3;
4181#endif
4182#ifdef HAVE_modhi3
4183 if (HAVE_modhi3)
4184 smod_optab->handlers[(int) HImode].insn_code = CODE_FOR_modhi3;
4185#endif
4186#ifdef HAVE_modpsi3
4187 if (HAVE_modpsi3)
4188 smod_optab->handlers[(int) PSImode].insn_code = CODE_FOR_modpsi3;
4189#endif
4190#ifdef HAVE_modsi3
4191 if (HAVE_modsi3)
4192 smod_optab->handlers[(int) SImode].insn_code = CODE_FOR_modsi3;
4193#endif
4194#ifdef HAVE_moddi3
4195 if (HAVE_moddi3)
4196 smod_optab->handlers[(int) DImode].insn_code = CODE_FOR_moddi3;
4197#endif
4198#ifdef HAVE_modti3
4199 if (HAVE_modti3)
4200 smod_optab->handlers[(int) TImode].insn_code = CODE_FOR_modti3;
4201#endif
4202 init_integral_libfuncs (smod_optab, "mod", '3');
4203
4204#ifdef MODSI3_LIBCALL
4205 smod_optab->handlers[(int) SImode].libfunc
4206 = gen_rtx (SYMBOL_REF, Pmode, MODSI3_LIBCALL);
4207#endif
4208#ifdef MODDI3_LIBCALL
4209 smod_optab->handlers[(int) DImode].libfunc
4210 = gen_rtx (SYMBOL_REF, Pmode, MODDI3_LIBCALL);
4211#endif
4212#ifdef MODTI3_LIBCALL
4213 smod_optab->handlers[(int) TImode].libfunc
4214 = gen_rtx (SYMBOL_REF, Pmode, MODTI3_LIBCALL);
4215#endif
4216
4217#ifdef HAVE_umodqi3
4218 if (HAVE_umodqi3)
4219 umod_optab->handlers[(int) QImode].insn_code = CODE_FOR_umodqi3;
4220#endif
4221#ifdef HAVE_umodhi3
4222 if (HAVE_umodhi3)
4223 umod_optab->handlers[(int) HImode].insn_code = CODE_FOR_umodhi3;
4224#endif
4225#ifdef HAVE_umodpsi3
4226 if (HAVE_umodpsi3)
4227 umod_optab->handlers[(int) PSImode].insn_code = CODE_FOR_umodpsi3;
4228#endif
4229#ifdef HAVE_umodsi3
4230 if (HAVE_umodsi3)
4231 umod_optab->handlers[(int) SImode].insn_code = CODE_FOR_umodsi3;
4232#endif
4233#ifdef HAVE_umoddi3
4234 if (HAVE_umoddi3)
4235 umod_optab->handlers[(int) DImode].insn_code = CODE_FOR_umoddi3;
4236#endif
4237#ifdef HAVE_umodti3
4238 if (HAVE_umodti3)
4239 umod_optab->handlers[(int) TImode].insn_code = CODE_FOR_umodti3;
4240#endif
4241 init_integral_libfuncs (umod_optab, "umod", '3');
4242
4243#ifdef UMODSI3_LIBCALL
4244 umod_optab->handlers[(int) SImode].libfunc
4245 = gen_rtx (SYMBOL_REF, Pmode, UMODSI3_LIBCALL);
4246#endif
4247#ifdef UMODDI3_LIBCALL
4248 umod_optab->handlers[(int) DImode].libfunc
4249 = gen_rtx (SYMBOL_REF, Pmode, UMODDI3_LIBCALL);
4250#endif
4251#ifdef UMODTI3_LIBCALL
4252 umod_optab->handlers[(int) TImode].libfunc
4253 = gen_rtx (SYMBOL_REF, Pmode, UMODTI3_LIBCALL);
4254#endif
4255
4256#ifdef HAVE_divsf3
4257 if (HAVE_divsf3)
4258 flodiv_optab->handlers[(int) SFmode].insn_code = CODE_FOR_divsf3;
4259#endif
4260#ifdef HAVE_divdf3
4261 if (HAVE_divdf3)
4262 flodiv_optab->handlers[(int) DFmode].insn_code = CODE_FOR_divdf3;
4263#endif
4264#ifdef HAVE_divxf3
4265 if (HAVE_divxf3)
4266 flodiv_optab->handlers[(int) XFmode].insn_code = CODE_FOR_divxf3;
4267#endif
4268#ifdef HAVE_divtf3
4269 if (HAVE_divtf3)
4270 flodiv_optab->handlers[(int) TFmode].insn_code = CODE_FOR_divtf3;
4271#endif
4272 init_floating_libfuncs (flodiv_optab, "div", '3');
4273
4274#ifdef HAVE_ftruncsf2
4275 if (HAVE_ftruncsf2)
4276 ftrunc_optab->handlers[(int) SFmode].insn_code = CODE_FOR_ftruncsf2;
4277#endif
4278#ifdef HAVE_ftruncdf2
4279 if (HAVE_ftruncdf2)
4280 ftrunc_optab->handlers[(int) DFmode].insn_code = CODE_FOR_ftruncdf2;
4281#endif
4282#ifdef HAVE_ftruncxf2
4283 if (HAVE_ftruncxf2)
4284 ftrunc_optab->handlers[(int) XFmode].insn_code = CODE_FOR_ftruncxf2;
4285#endif
4286#ifdef HAVE_ftrunctf2
4287 if (HAVE_ftrunctf2)
4288 ftrunc_optab->handlers[(int) TFmode].insn_code = CODE_FOR_ftrunctf2;
4289#endif
4290 init_floating_libfuncs (ftrunc_optab, "ftrunc", '2');
4291
4292#ifdef HAVE_andqi3
4293 if (HAVE_andqi3)
4294 and_optab->handlers[(int) QImode].insn_code = CODE_FOR_andqi3;
4295#endif
4296#ifdef HAVE_andhi3
4297 if (HAVE_andhi3)
4298 and_optab->handlers[(int) HImode].insn_code = CODE_FOR_andhi3;
4299#endif
4300#ifdef HAVE_andpsi3
4301 if (HAVE_andpsi3)
4302 and_optab->handlers[(int) PSImode].insn_code = CODE_FOR_andpsi3;
4303#endif
4304#ifdef HAVE_andsi3
4305 if (HAVE_andsi3)
4306 and_optab->handlers[(int) SImode].insn_code = CODE_FOR_andsi3;
4307#endif
4308#ifdef HAVE_anddi3
4309 if (HAVE_anddi3)
4310 and_optab->handlers[(int) DImode].insn_code = CODE_FOR_anddi3;
4311#endif
4312#ifdef HAVE_andti3
4313 if (HAVE_andti3)
4314 and_optab->handlers[(int) TImode].insn_code = CODE_FOR_andti3;
4315#endif
4316 init_integral_libfuncs (and_optab, "and", '3');
4317
4318#ifdef HAVE_iorqi3
4319 if (HAVE_iorqi3)
4320 ior_optab->handlers[(int) QImode].insn_code = CODE_FOR_iorqi3;
4321#endif
4322#ifdef HAVE_iorhi3
4323 if (HAVE_iorhi3)
4324 ior_optab->handlers[(int) HImode].insn_code = CODE_FOR_iorhi3;
4325#endif
4326#ifdef HAVE_iorpsi3
4327 if (HAVE_iorpsi3)
4328 ior_optab->handlers[(int) PSImode].insn_code = CODE_FOR_iorpsi3;
4329#endif
4330#ifdef HAVE_iorsi3
4331 if (HAVE_iorsi3)
4332 ior_optab->handlers[(int) SImode].insn_code = CODE_FOR_iorsi3;
4333#endif
4334#ifdef HAVE_iordi3
4335 if (HAVE_iordi3)
4336 ior_optab->handlers[(int) DImode].insn_code = CODE_FOR_iordi3;
4337#endif
4338#ifdef HAVE_iorti3
4339 if (HAVE_iorti3)
4340 ior_optab->handlers[(int) TImode].insn_code = CODE_FOR_iorti3;
4341#endif
4342 init_integral_libfuncs (ior_optab, "ior", '3');
4343
4344#ifdef HAVE_xorqi3
4345 if (HAVE_xorqi3)
4346 xor_optab->handlers[(int) QImode].insn_code = CODE_FOR_xorqi3;
4347#endif
4348#ifdef HAVE_xorhi3
4349 if (HAVE_xorhi3)
4350 xor_optab->handlers[(int) HImode].insn_code = CODE_FOR_xorhi3;
4351#endif
4352#ifdef HAVE_xorpsi3
4353 if (HAVE_xorpsi3)
4354 xor_optab->handlers[(int) PSImode].insn_code = CODE_FOR_xorpsi3;
4355#endif
4356#ifdef HAVE_xorsi3
4357 if (HAVE_xorsi3)
4358 xor_optab->handlers[(int) SImode].insn_code = CODE_FOR_xorsi3;
4359#endif
4360#ifdef HAVE_xordi3
4361 if (HAVE_xordi3)
4362 xor_optab->handlers[(int) DImode].insn_code = CODE_FOR_xordi3;
4363#endif
4364#ifdef HAVE_xorti3
4365 if (HAVE_xorti3)
4366 xor_optab->handlers[(int) TImode].insn_code = CODE_FOR_xorti3;
4367#endif
4368 init_integral_libfuncs (xor_optab, "xor", '3');
4369
4370#ifdef HAVE_ashlqi3
4371 if (HAVE_ashlqi3)
4372 ashl_optab->handlers[(int) QImode].insn_code = CODE_FOR_ashlqi3;
4373#endif
4374#ifdef HAVE_ashlhi3
4375 if (HAVE_ashlhi3)
4376 ashl_optab->handlers[(int) HImode].insn_code = CODE_FOR_ashlhi3;
4377#endif
4378#ifdef HAVE_ashlpsi3
4379 if (HAVE_ashlpsi3)
4380 ashl_optab->handlers[(int) PSImode].insn_code = CODE_FOR_ashlpsi3;
4381#endif
4382#ifdef HAVE_ashlsi3
4383 if (HAVE_ashlsi3)
4384 ashl_optab->handlers[(int) SImode].insn_code = CODE_FOR_ashlsi3;
4385#endif
4386#ifdef HAVE_ashldi3
4387 if (HAVE_ashldi3)
4388 ashl_optab->handlers[(int) DImode].insn_code = CODE_FOR_ashldi3;
4389#endif
4390#ifdef HAVE_ashlti3
4391 if (HAVE_ashlti3)
4392 ashl_optab->handlers[(int) TImode].insn_code = CODE_FOR_ashlti3;
4393#endif
4394 init_integral_libfuncs (ashl_optab, "ashl", '3');
4395
4396#ifdef HAVE_ashrqi3
4397 if (HAVE_ashrqi3)
4398 ashr_optab->handlers[(int) QImode].insn_code = CODE_FOR_ashrqi3;
4399#endif
4400#ifdef HAVE_ashrhi3
4401 if (HAVE_ashrhi3)
4402 ashr_optab->handlers[(int) HImode].insn_code = CODE_FOR_ashrhi3;
4403#endif
4404#ifdef HAVE_ashrpsi3
4405 if (HAVE_ashrpsi3)
4406 ashr_optab->handlers[(int) PSImode].insn_code = CODE_FOR_ashrpsi3;
4407#endif
4408#ifdef HAVE_ashrsi3
4409 if (HAVE_ashrsi3)
4410 ashr_optab->handlers[(int) SImode].insn_code = CODE_FOR_ashrsi3;
4411#endif
4412#ifdef HAVE_ashrdi3
4413 if (HAVE_ashrdi3)
4414 ashr_optab->handlers[(int) DImode].insn_code = CODE_FOR_ashrdi3;
4415#endif
4416#ifdef HAVE_ashrti3
4417 if (HAVE_ashrti3)
4418 ashr_optab->handlers[(int) TImode].insn_code = CODE_FOR_ashrti3;
4419#endif
4420 init_integral_libfuncs (ashr_optab, "ashr", '3');
4421
4422#ifdef HAVE_lshlqi3
4423 if (HAVE_lshlqi3)
4424 lshl_optab->handlers[(int) QImode].insn_code = CODE_FOR_lshlqi3;
4425#endif
4426#ifdef HAVE_lshlhi3
4427 if (HAVE_lshlhi3)
4428 lshl_optab->handlers[(int) HImode].insn_code = CODE_FOR_lshlhi3;
4429#endif
4430#ifdef HAVE_lshlpsi3
4431 if (HAVE_lshlpsi3)
4432 lshl_optab->handlers[(int) PSImode].insn_code = CODE_FOR_lshlpsi3;
4433#endif
4434#ifdef HAVE_lshlsi3
4435 if (HAVE_lshlsi3)
4436 lshl_optab->handlers[(int) SImode].insn_code = CODE_FOR_lshlsi3;
4437#endif
4438#ifdef HAVE_lshldi3
4439 if (HAVE_lshldi3)
4440 lshl_optab->handlers[(int) DImode].insn_code = CODE_FOR_lshldi3;
4441#endif
4442#ifdef HAVE_lshlti3
4443 if (HAVE_lshlti3)
4444 lshl_optab->handlers[(int) TImode].insn_code = CODE_FOR_lshlti3;
4445#endif
4446 init_integral_libfuncs (lshl_optab, "lshl", '3');
4447
4448#ifdef HAVE_lshrqi3
4449 if (HAVE_lshrqi3)
4450 lshr_optab->handlers[(int) QImode].insn_code = CODE_FOR_lshrqi3;
4451#endif
4452#ifdef HAVE_lshrhi3
4453 if (HAVE_lshrhi3)
4454 lshr_optab->handlers[(int) HImode].insn_code = CODE_FOR_lshrhi3;
4455#endif
4456#ifdef HAVE_lshrpsi3
4457 if (HAVE_lshrpsi3)
4458 lshr_optab->handlers[(int) PSImode].insn_code = CODE_FOR_lshrpsi3;
4459#endif
4460#ifdef HAVE_lshrsi3
4461 if (HAVE_lshrsi3)
4462 lshr_optab->handlers[(int) SImode].insn_code = CODE_FOR_lshrsi3;
4463#endif
4464#ifdef HAVE_lshrdi3
4465 if (HAVE_lshrdi3)
4466 lshr_optab->handlers[(int) DImode].insn_code = CODE_FOR_lshrdi3;
4467#endif
4468#ifdef HAVE_lshrti3
4469 if (HAVE_lshrti3)
4470 lshr_optab->handlers[(int) TImode].insn_code = CODE_FOR_lshrti3;
4471#endif
4472 init_integral_libfuncs (lshr_optab, "lshr", '3');
4473
4474#ifdef HAVE_rotlqi3
4475 if (HAVE_rotlqi3)
4476 rotl_optab->handlers[(int) QImode].insn_code = CODE_FOR_rotlqi3;
4477#endif
4478#ifdef HAVE_rotlhi3
4479 if (HAVE_rotlhi3)
4480 rotl_optab->handlers[(int) HImode].insn_code = CODE_FOR_rotlhi3;
4481#endif
4482#ifdef HAVE_rotlpsi3
4483 if (HAVE_rotlpsi3)
4484 rotl_optab->handlers[(int) PSImode].insn_code = CODE_FOR_rotlpsi3;
4485#endif
4486#ifdef HAVE_rotlsi3
4487 if (HAVE_rotlsi3)
4488 rotl_optab->handlers[(int) SImode].insn_code = CODE_FOR_rotlsi3;
4489#endif
4490#ifdef HAVE_rotldi3
4491 if (HAVE_rotldi3)
4492 rotl_optab->handlers[(int) DImode].insn_code = CODE_FOR_rotldi3;
4493#endif
4494#ifdef HAVE_rotlti3
4495 if (HAVE_rotlti3)
4496 rotl_optab->handlers[(int) TImode].insn_code = CODE_FOR_rotlti3;
4497#endif
4498 init_integral_libfuncs (rotl_optab, "rotl", '3');
4499
4500#ifdef HAVE_rotrqi3
4501 if (HAVE_rotrqi3)
4502 rotr_optab->handlers[(int) QImode].insn_code = CODE_FOR_rotrqi3;
4503#endif
4504#ifdef HAVE_rotrhi3
4505 if (HAVE_rotrhi3)
4506 rotr_optab->handlers[(int) HImode].insn_code = CODE_FOR_rotrhi3;
4507#endif
4508#ifdef HAVE_rotrpsi3
4509 if (HAVE_rotrpsi3)
4510 rotr_optab->handlers[(int) PSImode].insn_code = CODE_FOR_rotrpsi3;
4511#endif
4512#ifdef HAVE_rotrsi3
4513 if (HAVE_rotrsi3)
4514 rotr_optab->handlers[(int) SImode].insn_code = CODE_FOR_rotrsi3;
4515#endif
4516#ifdef HAVE_rotrdi3
4517 if (HAVE_rotrdi3)
4518 rotr_optab->handlers[(int) DImode].insn_code = CODE_FOR_rotrdi3;
4519#endif
4520#ifdef HAVE_rotrti3
4521 if (HAVE_rotrti3)
4522 rotr_optab->handlers[(int) TImode].insn_code = CODE_FOR_rotrti3;
4523#endif
4524 init_integral_libfuncs (rotr_optab, "rotr", '3');
4525
4526#ifdef HAVE_sminqi3
4527 if (HAVE_sminqi3)
4528 smin_optab->handlers[(int) QImode].insn_code = CODE_FOR_sminqi3;
4529#endif
4530#ifdef HAVE_sminhi3
4531 if (HAVE_sminhi3)
4532 smin_optab->handlers[(int) HImode].insn_code = CODE_FOR_sminhi3;
4533#endif
4534#ifdef HAVE_sminsi3
4535 if (HAVE_sminsi3)
4536 smin_optab->handlers[(int) SImode].insn_code = CODE_FOR_sminsi3;
4537#endif
4538#ifdef HAVE_smindi3
4539 if (HAVE_smindi3)
4540 smin_optab->handlers[(int) DImode].insn_code = CODE_FOR_smindi3;
4541#endif
4542#ifdef HAVE_sminti3
4543 if (HAVE_sminti3)
4544 smin_optab->handlers[(int) TImode].insn_code = CODE_FOR_sminti3;
4545#endif
4546#ifdef HAVE_minsf3
4547 if (HAVE_minsf3)
4548 smin_optab->handlers[(int) SFmode].insn_code = CODE_FOR_minsf3;
4549#endif
4550#ifdef HAVE_mindf3
4551 if (HAVE_mindf3)
4552 smin_optab->handlers[(int) DFmode].insn_code = CODE_FOR_mindf3;
4553#endif
4554#ifdef HAVE_minxf3
4555 if (HAVE_minxf3)
4556 smin_optab->handlers[(int) XFmode].insn_code = CODE_FOR_minxf3;
4557#endif
4558#ifdef HAVE_mintf3
4559 if (HAVE_mintf3)
4560 smin_optab->handlers[(int) TFmode].insn_code = CODE_FOR_mintf3;
4561#endif
4562 init_integral_libfuncs (smin_optab, "min", '3');
4563 init_floating_libfuncs (smin_optab, "min", '3');
4564
4565#ifdef HAVE_smaxqi3
4566 if (HAVE_smaxqi3)
4567 smax_optab->handlers[(int) QImode].insn_code = CODE_FOR_smaxqi3;
4568#endif
4569#ifdef HAVE_smaxhi3
4570 if (HAVE_smaxhi3)
4571 smax_optab->handlers[(int) HImode].insn_code = CODE_FOR_smaxhi3;
4572#endif
4573#ifdef HAVE_smaxsi3
4574 if (HAVE_smaxsi3)
4575 smax_optab->handlers[(int) SImode].insn_code = CODE_FOR_smaxsi3;
4576#endif
4577#ifdef HAVE_smaxdi3
4578 if (HAVE_smaxdi3)
4579 smax_optab->handlers[(int) DImode].insn_code = CODE_FOR_smaxdi3;
4580#endif
4581#ifdef HAVE_smaxti3
4582 if (HAVE_smaxti3)
4583 smax_optab->handlers[(int) TImode].insn_code = CODE_FOR_smaxti3;
4584#endif
4585#ifdef HAVE_maxsf3
4586 if (HAVE_maxsf3)
4587 smax_optab->handlers[(int) SFmode].insn_code = CODE_FOR_maxsf3;
4588#endif
4589#ifdef HAVE_maxdf3
4590 if (HAVE_maxdf3)
4591 smax_optab->handlers[(int) DFmode].insn_code = CODE_FOR_maxdf3;
4592#endif
4593#ifdef HAVE_maxxf3
4594 if (HAVE_maxxf3)
4595 smax_optab->handlers[(int) XFmode].insn_code = CODE_FOR_maxxf3;
4596#endif
4597#ifdef HAVE_maxtf3
4598 if (HAVE_maxtf3)
4599 smax_optab->handlers[(int) TFmode].insn_code = CODE_FOR_maxtf3;
4600#endif
4601 init_integral_libfuncs (smax_optab, "max", '3');
4602 init_floating_libfuncs (smax_optab, "max", '3');
4603
4604#ifdef HAVE_uminqi3
4605 if (HAVE_uminqi3)
4606 umin_optab->handlers[(int) QImode].insn_code = CODE_FOR_uminqi3;
4607#endif
4608#ifdef HAVE_uminhi3
4609 if (HAVE_uminhi3)
4610 umin_optab->handlers[(int) HImode].insn_code = CODE_FOR_uminhi3;
4611#endif
4612#ifdef HAVE_uminsi3
4613 if (HAVE_uminsi3)
4614 umin_optab->handlers[(int) SImode].insn_code = CODE_FOR_uminsi3;
4615#endif
4616#ifdef HAVE_umindi3
4617 if (HAVE_umindi3)
4618 umin_optab->handlers[(int) DImode].insn_code = CODE_FOR_umindi3;
4619#endif
4620#ifdef HAVE_uminti3
4621 if (HAVE_uminti3)
4622 umin_optab->handlers[(int) TImode].insn_code = CODE_FOR_uminti3;
4623#endif
4624 init_integral_libfuncs (umin_optab, "umin", '3');
4625
4626#ifdef HAVE_umaxqi3
4627 if (HAVE_umaxqi3)
4628 umax_optab->handlers[(int) QImode].insn_code = CODE_FOR_umaxqi3;
4629#endif
4630#ifdef HAVE_umaxhi3
4631 if (HAVE_umaxhi3)
4632 umax_optab->handlers[(int) HImode].insn_code = CODE_FOR_umaxhi3;
4633#endif
4634#ifdef HAVE_umaxsi3
4635 if (HAVE_umaxsi3)
4636 umax_optab->handlers[(int) SImode].insn_code = CODE_FOR_umaxsi3;
4637#endif
4638#ifdef HAVE_umaxdi3
4639 if (HAVE_umaxdi3)
4640 umax_optab->handlers[(int) DImode].insn_code = CODE_FOR_umaxdi3;
4641#endif
4642#ifdef HAVE_umaxti3
4643 if (HAVE_umaxti3)
4644 umax_optab->handlers[(int) TImode].insn_code = CODE_FOR_umaxti3;
4645#endif
4646 init_integral_libfuncs (umax_optab, "umax", '3');
4647
4648#ifdef HAVE_negqi2
4649 if (HAVE_negqi2)
4650 neg_optab->handlers[(int) QImode].insn_code = CODE_FOR_negqi2;
4651#endif
4652#ifdef HAVE_neghi2
4653 if (HAVE_neghi2)
4654 neg_optab->handlers[(int) HImode].insn_code = CODE_FOR_neghi2;
4655#endif
4656#ifdef HAVE_negpsi2
4657 if (HAVE_negpsi2)
4658 neg_optab->handlers[(int) PSImode].insn_code = CODE_FOR_negpsi2;
4659#endif
4660#ifdef HAVE_negsi2
4661 if (HAVE_negsi2)
4662 neg_optab->handlers[(int) SImode].insn_code = CODE_FOR_negsi2;
4663#endif
4664#ifdef HAVE_negdi2
4665 if (HAVE_negdi2)
4666 neg_optab->handlers[(int) DImode].insn_code = CODE_FOR_negdi2;
4667#endif
4668#ifdef HAVE_negti2
4669 if (HAVE_negti2)
4670 neg_optab->handlers[(int) TImode].insn_code = CODE_FOR_negti2;
4671#endif
4672#ifdef HAVE_negsf2
4673 if (HAVE_negsf2)
4674 neg_optab->handlers[(int) SFmode].insn_code = CODE_FOR_negsf2;
4675#endif
4676#ifdef HAVE_negdf2
4677 if (HAVE_negdf2)
4678 neg_optab->handlers[(int) DFmode].insn_code = CODE_FOR_negdf2;
4679#endif
4680#ifdef HAVE_negxf2
4681 if (HAVE_negxf2)
4682 neg_optab->handlers[(int) XFmode].insn_code = CODE_FOR_negxf2;
4683#endif
4684#ifdef HAVE_negtf2
4685 if (HAVE_negtf2)
4686 neg_optab->handlers[(int) TFmode].insn_code = CODE_FOR_negtf2;
4687#endif
4688 init_integral_libfuncs (neg_optab, "neg", '2');
4689 init_floating_libfuncs (neg_optab, "neg", '2');
4690
4691#ifdef HAVE_absqi2
4692 if (HAVE_absqi2)
4693 abs_optab->handlers[(int) QImode].insn_code = CODE_FOR_absqi2;
4694#endif
4695#ifdef HAVE_abshi2
4696 if (HAVE_abshi2)
4697 abs_optab->handlers[(int) HImode].insn_code = CODE_FOR_abshi2;
4698#endif
4699#ifdef HAVE_abspsi2
4700 if (HAVE_abspsi2)
4701 abs_optab->handlers[(int) PSImode].insn_code = CODE_FOR_abspsi2;
4702#endif
4703#ifdef HAVE_abssi2
4704 if (HAVE_abssi2)
4705 abs_optab->handlers[(int) SImode].insn_code = CODE_FOR_abssi2;
4706#endif
4707#ifdef HAVE_absdi2
4708 if (HAVE_absdi2)
4709 abs_optab->handlers[(int) DImode].insn_code = CODE_FOR_absdi2;
4710#endif
4711#ifdef HAVE_absti2
4712 if (HAVE_absti2)
4713 abs_optab->handlers[(int) TImode].insn_code = CODE_FOR_absti2;
4714#endif
4715#ifdef HAVE_abssf2
4716 if (HAVE_abssf2)
4717 abs_optab->handlers[(int) SFmode].insn_code = CODE_FOR_abssf2;
4718#endif
4719#ifdef HAVE_absdf2
4720 if (HAVE_absdf2)
4721 abs_optab->handlers[(int) DFmode].insn_code = CODE_FOR_absdf2;
4722#endif
4723#ifdef HAVE_absxf2
4724 if (HAVE_absxf2)
4725 abs_optab->handlers[(int) XFmode].insn_code = CODE_FOR_absxf2;
4726#endif
4727#ifdef HAVE_abstf2
4728 if (HAVE_abstf2)
4729 abs_optab->handlers[(int) TFmode].insn_code = CODE_FOR_abstf2;
4730#endif
4731
4732 /* Use cabs for DC complex abs, since systems generally have cabs.
4733 Don't define any libcall for SCmode, so that cabs will be used. */
4734 abs_optab->handlers[(int) DCmode].libfunc
4735 = gen_rtx (SYMBOL_REF, Pmode, "cabs");
4736
4737#ifdef HAVE_sqrtqi2
4738 if (HAVE_sqrtqi2)
4739 sqrt_optab->handlers[(int) QImode].insn_code = CODE_FOR_sqrtqi2;
4740#endif
4741#ifdef HAVE_sqrthi2
4742 if (HAVE_sqrthi2)
4743 sqrt_optab->handlers[(int) HImode].insn_code = CODE_FOR_sqrthi2;
4744#endif
4745#ifdef HAVE_sqrtpsi2
4746 if (HAVE_sqrtpsi2)
4747 sqrt_optab->handlers[(int) PSImode].insn_code = CODE_FOR_sqrtpsi2;
4748#endif
4749#ifdef HAVE_sqrtsi2
4750 if (HAVE_sqrtsi2)
4751 sqrt_optab->handlers[(int) SImode].insn_code = CODE_FOR_sqrtsi2;
4752#endif
4753#ifdef HAVE_sqrtdi2
4754 if (HAVE_sqrtdi2)
4755 sqrt_optab->handlers[(int) DImode].insn_code = CODE_FOR_sqrtdi2;
4756#endif
4757#ifdef HAVE_sqrtti2
4758 if (HAVE_sqrtti2)
4759 sqrt_optab->handlers[(int) TImode].insn_code = CODE_FOR_sqrtti2;
4760#endif
4761#ifdef HAVE_sqrtsf2
4762 if (HAVE_sqrtsf2)
4763 sqrt_optab->handlers[(int) SFmode].insn_code = CODE_FOR_sqrtsf2;
4764#endif
4765#ifdef HAVE_sqrtdf2
4766 if (HAVE_sqrtdf2)
4767 sqrt_optab->handlers[(int) DFmode].insn_code = CODE_FOR_sqrtdf2;
4768#endif
4769#ifdef HAVE_sqrttf2
4770 if (HAVE_sqrttf2)
4771 sqrt_optab->handlers[(int) TFmode].insn_code = CODE_FOR_sqrttf2;
4772#endif
4773 /* No library calls here! If there is no sqrt instruction expand_builtin
4774 should force the library call. */
4775
4776#ifdef HAVE_sinsf2
4777 if (HAVE_sinsf2)
4778 sin_optab->handlers[(int) SFmode].insn_code = CODE_FOR_sinsf2;
4779#endif
4780#ifdef HAVE_sindf2
4781 if (HAVE_sindf2)
4782 sin_optab->handlers[(int) DFmode].insn_code = CODE_FOR_sindf2;
4783#endif
4784#ifdef HAVE_sintf2
4785 if (HAVE_sintf2)
4786 sin_optab->handlers[(int) TFmode].insn_code = CODE_FOR_sintf2;
4787#endif
4788 /* No library calls here! If there is no sin instruction expand_builtin
4789 should force the library call. */
4790
4791#ifdef HAVE_cossf2
4792 if (HAVE_cossf2)
4793 cos_optab->handlers[(int) SFmode].insn_code = CODE_FOR_cossf2;
4794#endif
4795#ifdef HAVE_cosdf2
4796 if (HAVE_cosdf2)
4797 cos_optab->handlers[(int) DFmode].insn_code = CODE_FOR_cosdf2;
4798#endif
4799#ifdef HAVE_costf2
4800 if (HAVE_costf2)
4801 cos_optab->handlers[(int) TFmode].insn_code = CODE_FOR_costf2;
4802#endif
4803 /* No library calls here! If there is no cos instruction expand_builtin
4804 should force the library call. */
4805
4806#ifdef HAVE_strlenqi
4807 if (HAVE_strlenqi)
4808 strlen_optab->handlers[(int) QImode].insn_code = CODE_FOR_strlenqi;
4809#endif
4810#ifdef HAVE_strlenhi
4811 if (HAVE_strlenhi)
4812 strlen_optab->handlers[(int) HImode].insn_code = CODE_FOR_strlenhi;
4813#endif
4814#ifdef HAVE_strlenpsi
4815 if (HAVE_strlenpsi)
4816 strlen_optab->handlers[(int) PSImode].insn_code = CODE_FOR_strlenpsi;
4817#endif
4818#ifdef HAVE_strlensi
4819 if (HAVE_strlensi)
4820 strlen_optab->handlers[(int) SImode].insn_code = CODE_FOR_strlensi;
4821#endif
4822#ifdef HAVE_strlendi
4823 if (HAVE_strlendi)
4824 strlen_optab->handlers[(int) DImode].insn_code = CODE_FOR_strlendi;
4825#endif
4826#ifdef HAVE_strlenti
4827 if (HAVE_strlenti)
4828 strlen_optab->handlers[(int) TImode].insn_code = CODE_FOR_strlenti;
4829#endif
4830 /* No library calls here! If there is no strlen instruction expand_builtin
4831 should force the library call. */
4832
4833#ifdef HAVE_one_cmplqi2
4834 if (HAVE_one_cmplqi2)
4835 one_cmpl_optab->handlers[(int) QImode].insn_code = CODE_FOR_one_cmplqi2;
4836#endif
4837#ifdef HAVE_one_cmplhi2
4838 if (HAVE_one_cmplhi2)
4839 one_cmpl_optab->handlers[(int) HImode].insn_code = CODE_FOR_one_cmplhi2;
4840#endif
4841#ifdef HAVE_one_cmplpsi2
4842 if (HAVE_one_cmplpsi2)
4843 one_cmpl_optab->handlers[(int) PSImode].insn_code = CODE_FOR_one_cmplpsi2;
4844#endif
4845#ifdef HAVE_one_cmplsi2
4846 if (HAVE_one_cmplsi2)
4847 one_cmpl_optab->handlers[(int) SImode].insn_code = CODE_FOR_one_cmplsi2;
4848#endif
4849#ifdef HAVE_one_cmpldi2
4850 if (HAVE_one_cmpldi2)
4851 one_cmpl_optab->handlers[(int) DImode].insn_code = CODE_FOR_one_cmpldi2;
4852#endif
4853#ifdef HAVE_one_cmplti2
4854 if (HAVE_one_cmplti2)
4855 one_cmpl_optab->handlers[(int) TImode].insn_code = CODE_FOR_one_cmplti2;
4856#endif
4857 init_integral_libfuncs (one_cmpl_optab, "one_cmpl", '2');
4858
4859#ifdef HAVE_ffsqi2
4860 if (HAVE_ffsqi2)
4861 ffs_optab->handlers[(int) QImode].insn_code = CODE_FOR_ffsqi2;
4862#endif
4863#ifdef HAVE_ffshi2
4864 if (HAVE_ffshi2)
4865 ffs_optab->handlers[(int) HImode].insn_code = CODE_FOR_ffshi2;
4866#endif
4867#ifdef HAVE_ffspsi2
4868 if (HAVE_ffspsi2)
4869 ffs_optab->handlers[(int) PSImode].insn_code = CODE_FOR_ffspsi2;
4870#endif
4871#ifdef HAVE_ffssi2
4872 if (HAVE_ffssi2)
4873 ffs_optab->handlers[(int) SImode].insn_code = CODE_FOR_ffssi2;
4874#endif
4875#ifdef HAVE_ffsdi2
4876 if (HAVE_ffsdi2)
4877 ffs_optab->handlers[(int) DImode].insn_code = CODE_FOR_ffsdi2;
4878#endif
4879#ifdef HAVE_ffsti2
4880 if (HAVE_ffsti2)
4881 ffs_optab->handlers[(int) TImode].insn_code = CODE_FOR_ffsti2;
4882#endif
4883 init_integral_libfuncs (ffs_optab, "ffs", '2');
4884
4885#ifdef HAVE_movqi
4886 if (HAVE_movqi)
4887 mov_optab->handlers[(int) QImode].insn_code = CODE_FOR_movqi;
4888#endif
4889#ifdef HAVE_movhi
4890 if (HAVE_movhi)
4891 mov_optab->handlers[(int) HImode].insn_code = CODE_FOR_movhi;
4892#endif
4893#ifdef HAVE_movpsi
4894 if (HAVE_movpsi)
4895 mov_optab->handlers[(int) PSImode].insn_code = CODE_FOR_movpsi;
4896#endif
4897#ifdef HAVE_movsi
4898 if (HAVE_movsi)
4899 mov_optab->handlers[(int) SImode].insn_code = CODE_FOR_movsi;
4900#endif
4901#ifdef HAVE_movdi
4902 if (HAVE_movdi)
4903 mov_optab->handlers[(int) DImode].insn_code = CODE_FOR_movdi;
4904#endif
4905#ifdef HAVE_movti
4906 if (HAVE_movti)
4907 mov_optab->handlers[(int) TImode].insn_code = CODE_FOR_movti;
4908#endif
4909#ifdef HAVE_movsf
4910 if (HAVE_movsf)
4911 mov_optab->handlers[(int) SFmode].insn_code = CODE_FOR_movsf;
4912#endif
4913#ifdef HAVE_movdf
4914 if (HAVE_movdf)
4915 mov_optab->handlers[(int) DFmode].insn_code = CODE_FOR_movdf;
4916#endif
4917#ifdef HAVE_movxf
4918 if (HAVE_movxf)
4919 mov_optab->handlers[(int) XFmode].insn_code = CODE_FOR_movxf;
4920#endif
4921#ifdef HAVE_movtf
4922 if (HAVE_movtf)
4923 mov_optab->handlers[(int) TFmode].insn_code = CODE_FOR_movtf;
4924#endif
4925#ifdef HAVE_movcc
4926 if (HAVE_movcc)
4927 mov_optab->handlers[(int) CCmode].insn_code = CODE_FOR_movcc;
4928#endif
4929
4930#ifdef EXTRA_CC_MODES
4931 init_mov_optab ();
4932#endif
4933
4934#ifdef HAVE_movstrictqi
4935 if (HAVE_movstrictqi)
4936 movstrict_optab->handlers[(int) QImode].insn_code = CODE_FOR_movstrictqi;
4937#endif
4938#ifdef HAVE_movstricthi
4939 if (HAVE_movstricthi)
4940 movstrict_optab->handlers[(int) HImode].insn_code = CODE_FOR_movstricthi;
4941#endif
4942#ifdef HAVE_movstrictpsi
4943 if (HAVE_movstrictpsi)
4944 movstrict_optab->handlers[(int) PSImode].insn_code = CODE_FOR_movstrictpsi;
4945#endif
4946#ifdef HAVE_movstrictsi
4947 if (HAVE_movstrictsi)
4948 movstrict_optab->handlers[(int) SImode].insn_code = CODE_FOR_movstrictsi;
4949#endif
4950#ifdef HAVE_movstrictdi
4951 if (HAVE_movstrictdi)
4952 movstrict_optab->handlers[(int) DImode].insn_code = CODE_FOR_movstrictdi;
4953#endif
4954#ifdef HAVE_movstrictti
4955 if (HAVE_movstrictti)
4956 movstrict_optab->handlers[(int) TImode].insn_code = CODE_FOR_movstrictti;
4957#endif
4958
4959#ifdef HAVE_cmpqi
4960 if (HAVE_cmpqi)
4961 cmp_optab->handlers[(int) QImode].insn_code = CODE_FOR_cmpqi;
4962#endif
4963#ifdef HAVE_cmphi
4964 if (HAVE_cmphi)
4965 cmp_optab->handlers[(int) HImode].insn_code = CODE_FOR_cmphi;
4966#endif
4967#ifdef HAVE_cmppsi
4968 if (HAVE_cmppsi)
4969 cmp_optab->handlers[(int) PSImode].insn_code = CODE_FOR_cmppsi;
4970#endif
4971#ifdef HAVE_cmpsi
4972 if (HAVE_cmpsi)
4973 cmp_optab->handlers[(int) SImode].insn_code = CODE_FOR_cmpsi;
4974#endif
4975#ifdef HAVE_cmpdi
4976 if (HAVE_cmpdi)
4977 cmp_optab->handlers[(int) DImode].insn_code = CODE_FOR_cmpdi;
4978#endif
4979#ifdef HAVE_cmpti
4980 if (HAVE_cmpti)
4981 cmp_optab->handlers[(int) TImode].insn_code = CODE_FOR_cmpti;
4982#endif
4983#ifdef HAVE_cmpsf
4984 if (HAVE_cmpsf)
4985 cmp_optab->handlers[(int) SFmode].insn_code = CODE_FOR_cmpsf;
4986#endif
4987#ifdef HAVE_cmpdf
4988 if (HAVE_cmpdf)
4989 cmp_optab->handlers[(int) DFmode].insn_code = CODE_FOR_cmpdf;
4990#endif
4991#ifdef HAVE_cmpxf
4992 if (HAVE_cmpxf)
4993 cmp_optab->handlers[(int) XFmode].insn_code = CODE_FOR_cmpxf;
4994#endif
4995#ifdef HAVE_cmptf
4996 if (HAVE_cmptf)
4997 cmp_optab->handlers[(int) TFmode].insn_code = CODE_FOR_cmptf;
4998#endif
4999 /* Comparison libcalls for integers MUST come in pairs, signed/unsigned. */
5000 init_integral_libfuncs (cmp_optab, "cmp", '2');
5001 init_integral_libfuncs (ucmp_optab, "ucmp", '2');
5002 init_floating_libfuncs (cmp_optab, "cmp", '2');
5003
5004#ifdef HAVE_tstqi
5005 if (HAVE_tstqi)
5006 tst_optab->handlers[(int) QImode].insn_code = CODE_FOR_tstqi;
5007#endif
5008#ifdef HAVE_tsthi
5009 if (HAVE_tsthi)
5010 tst_optab->handlers[(int) HImode].insn_code = CODE_FOR_tsthi;
5011#endif
5012#ifdef HAVE_tstpsi
5013 if (HAVE_tstpsi)
5014 tst_optab->handlers[(int) PSImode].insn_code = CODE_FOR_tstpsi;
5015#endif
5016#ifdef HAVE_tstsi
5017 if (HAVE_tstsi)
5018 tst_optab->handlers[(int) SImode].insn_code = CODE_FOR_tstsi;
5019#endif
5020#ifdef HAVE_tstdi
5021 if (HAVE_tstdi)
5022 tst_optab->handlers[(int) DImode].insn_code = CODE_FOR_tstdi;
5023#endif
5024#ifdef HAVE_tstti
5025 if (HAVE_tstti)
5026 tst_optab->handlers[(int) TImode].insn_code = CODE_FOR_tstti;
5027#endif
5028#ifdef HAVE_tstsf
5029 if (HAVE_tstsf)
5030 tst_optab->handlers[(int) SFmode].insn_code = CODE_FOR_tstsf;
5031#endif
5032#ifdef HAVE_tstdf
5033 if (HAVE_tstdf)
5034 tst_optab->handlers[(int) DFmode].insn_code = CODE_FOR_tstdf;
5035#endif
5036#ifdef HAVE_tstxf
5037 if (HAVE_tstxf)
5038 tst_optab->handlers[(int) XFmode].insn_code = CODE_FOR_tstxf;
5039#endif
5040#ifdef HAVE_tsttf
5041 if (HAVE_tsttf)
5042 tst_optab->handlers[(int) TFmode].insn_code = CODE_FOR_tsttf;
5043#endif
5044
5045#ifdef HAVE_beq
5046 if (HAVE_beq)
5047 bcc_gen_fctn[(int) EQ] = gen_beq;
5048#endif
5049#ifdef HAVE_bne
5050 if (HAVE_bne)
5051 bcc_gen_fctn[(int) NE] = gen_bne;
5052#endif
5053#ifdef HAVE_bgt
5054 if (HAVE_bgt)
5055 bcc_gen_fctn[(int) GT] = gen_bgt;
5056#endif
5057#ifdef HAVE_bge
5058 if (HAVE_bge)
5059 bcc_gen_fctn[(int) GE] = gen_bge;
5060#endif
5061#ifdef HAVE_bgtu
5062 if (HAVE_bgtu)
5063 bcc_gen_fctn[(int) GTU] = gen_bgtu;
5064#endif
5065#ifdef HAVE_bgeu
5066 if (HAVE_bgeu)
5067 bcc_gen_fctn[(int) GEU] = gen_bgeu;
5068#endif
5069#ifdef HAVE_blt
5070 if (HAVE_blt)
5071 bcc_gen_fctn[(int) LT] = gen_blt;
5072#endif
5073#ifdef HAVE_ble
5074 if (HAVE_ble)
5075 bcc_gen_fctn[(int) LE] = gen_ble;
5076#endif
5077#ifdef HAVE_bltu
5078 if (HAVE_bltu)
5079 bcc_gen_fctn[(int) LTU] = gen_bltu;
5080#endif
5081#ifdef HAVE_bleu
5082 if (HAVE_bleu)
5083 bcc_gen_fctn[(int) LEU] = gen_bleu;
5084#endif
5085
5086 for (i = 0; i < NUM_RTX_CODE; i++)
5087 setcc_gen_code[i] = CODE_FOR_nothing;
5088
5089#ifdef HAVE_seq
5090 if (HAVE_seq)
5091 setcc_gen_code[(int) EQ] = CODE_FOR_seq;
5092#endif
5093#ifdef HAVE_sne
5094 if (HAVE_sne)
5095 setcc_gen_code[(int) NE] = CODE_FOR_sne;
5096#endif
5097#ifdef HAVE_sgt
5098 if (HAVE_sgt)
5099 setcc_gen_code[(int) GT] = CODE_FOR_sgt;
5100#endif
5101#ifdef HAVE_sge
5102 if (HAVE_sge)
5103 setcc_gen_code[(int) GE] = CODE_FOR_sge;
5104#endif
5105#ifdef HAVE_sgtu
5106 if (HAVE_sgtu)
5107 setcc_gen_code[(int) GTU] = CODE_FOR_sgtu;
5108#endif
5109#ifdef HAVE_sgeu
5110 if (HAVE_sgeu)
5111 setcc_gen_code[(int) GEU] = CODE_FOR_sgeu;
5112#endif
5113#ifdef HAVE_slt
5114 if (HAVE_slt)
5115 setcc_gen_code[(int) LT] = CODE_FOR_slt;
5116#endif
5117#ifdef HAVE_sle
5118 if (HAVE_sle)
5119 setcc_gen_code[(int) LE] = CODE_FOR_sle;
5120#endif
5121#ifdef HAVE_sltu
5122 if (HAVE_sltu)
5123 setcc_gen_code[(int) LTU] = CODE_FOR_sltu;
5124#endif
5125#ifdef HAVE_sleu
5126 if (HAVE_sleu)
5127 setcc_gen_code[(int) LEU] = CODE_FOR_sleu;
5128#endif
5129
5130 extendsfdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extendsfdf2");
5131 extendsfxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extendsfxf2");
5132 extendsftf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extendsftf2");
5133 extenddfxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extenddfxf2");
5134 extenddftf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extenddftf2");
5135
5136 truncdfsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__truncdfsf2");
5137 truncxfsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__truncxfsf2");
5138 trunctfsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__trunctfsf2");
5139 truncxfdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__truncxfdf2");
5140 trunctfdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__trunctfdf2");
5141
5142 memcpy_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memcpy");
5143 bcopy_libfunc = gen_rtx (SYMBOL_REF, Pmode, "bcopy");
5144 memcmp_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memcmp");
5145 bcmp_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gcc_bcmp");
5146 memset_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memset");
5147 bzero_libfunc = gen_rtx (SYMBOL_REF, Pmode, "bzero");
5148
5149 eqsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqsf2");
5150 nesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nesf2");
5151 gtsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gtsf2");
5152 gesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gesf2");
5153 ltsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ltsf2");
5154 lesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__lesf2");
5155
5156 eqdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqdf2");
5157 nedf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nedf2");
5158 gtdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gtdf2");
5159 gedf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gedf2");
5160 ltdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ltdf2");
5161 ledf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ledf2");
5162
5163 eqxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqxf2");
5164 nexf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nexf2");
5165 gtxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gtxf2");
5166 gexf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gexf2");
5167 ltxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ltxf2");
5168 lexf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__lexf2");
5169
5170 eqtf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqtf2");
5171 netf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__netf2");
5172 gttf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gttf2");
5173 getf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__getf2");
5174 lttf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__lttf2");
5175 letf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__letf2");
5176
5177 floatsisf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsisf");
5178 floatdisf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatdisf");
5179 floattisf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floattisf");
5180
5181 floatsidf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsidf");
5182 floatdidf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatdidf");
5183 floattidf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floattidf");
5184
5185 floatsixf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsixf");
5186 floatdixf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatdixf");
5187 floattixf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floattixf");
5188
5189 floatsitf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsitf");
5190 floatditf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatditf");
5191 floattitf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floattitf");
5192
5193 fixsfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixsfsi");
5194 fixsfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixsfdi");
5195 fixsfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixsfti");
5196
5197 fixdfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixdfsi");
5198 fixdfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixdfdi");
5199 fixdfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixdfti");
5200
5201 fixxfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixxfsi");
5202 fixxfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixxfdi");
5203 fixxfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixxfti");
5204
5205 fixtfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixtfsi");
5206 fixtfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixtfdi");
5207 fixtfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixtfti");
5208
5209 fixunssfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunssfsi");
5210 fixunssfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunssfdi");
5211 fixunssfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunssfti");
5212
5213 fixunsdfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsdfsi");
5214 fixunsdfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsdfdi");
5215 fixunsdfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsdfti");
5216
5217 fixunsxfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsxfsi");
5218 fixunsxfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsxfdi");
5219 fixunsxfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsxfti");
5220
5221 fixunstfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunstfsi");
5222 fixunstfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunstfdi");
5223 fixunstfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunstfti");
5224}
5225\f
5226#ifdef BROKEN_LDEXP
5227
5228/* SCO 3.2 apparently has a broken ldexp. */
5229
5230double
5231ldexp(x,n)
5232 double x;
5233 int n;
5234{
5235 if (n > 0)
5236 while (n--)
5237 x *= 2;
5238
5239 return x;
5240}
5241#endif /* BROKEN_LDEXP */