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