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