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