adding GNU dc ("desk calculator")
[unix-history] / gnu / usr.bin / gcc1 / cc1 / optabs.c
CommitLineData
15637ed4
RG
1/* Expand the basic unary and binary arithmetic operations, for GNU compiler.
2 Copyright (C) 1987, 1988 Free Software Foundation, Inc.
3
4This file is part of GNU CC.
5
6GNU CC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 1, or (at your option)
9any later version.
10
11GNU CC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU CC; see the file COPYING. If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20
21#include "config.h"
22#include "rtl.h"
23#include "tree.h"
24#include "flags.h"
25#include "insn-flags.h"
26#include "insn-codes.h"
27#include "expr.h"
28#include "insn-config.h"
29#include "recog.h"
30
31/* In ANSI C we could write MODE + 1, but traditional C compilers
32 seem to reject it. */
33#define INC_MODE(MODE) (enum machine_mode) ((int)(MODE) + 1)
34
35/* Each optab contains info on how this target machine
36 can perform a particular operation
37 for all sizes and kinds of operands.
38
39 The operation to be performed is often specified
40 by passing one of these optabs as an argument.
41
42 See expr.h for documentation of these optabs. */
43
44optab add_optab;
45optab sub_optab;
46optab smul_optab;
47optab umul_optab;
48optab smul_widen_optab;
49optab umul_widen_optab;
50optab sdiv_optab;
51optab sdivmod_optab;
52optab udiv_optab;
53optab udivmod_optab;
54optab smod_optab;
55optab umod_optab;
56optab flodiv_optab;
57optab ftrunc_optab;
58optab and_optab;
59optab andcb_optab;
60optab ior_optab;
61optab xor_optab;
62optab ashl_optab;
63optab lshr_optab;
64optab lshl_optab;
65optab ashr_optab;
66optab rotl_optab;
67optab rotr_optab;
68
69optab mov_optab;
70optab movstrict_optab;
71
72optab neg_optab;
73optab abs_optab;
74optab one_cmpl_optab;
75optab ffs_optab;
76
77optab cmp_optab;
78optab ucmp_optab; /* Used only for libcalls for unsigned comparisons. */
79optab tst_optab;
80
81/* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
82 gives the gen_function to make a branch to test that condition. */
83
84rtxfun bcc_gen_fctn[NUM_RTX_CODE];
85
86/* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
87 gives the gen_function to make a store-condition insn
88 to test that condition. */
89
90rtxfun setcc_gen_fctn[NUM_RTX_CODE];
91\f
92/* Generate code to perform an operation specified by BINOPTAB
93 on operands OP0 and OP1, with result having machine-mode MODE.
94
95 UNSIGNEDP is for the case where we have to widen the operands
96 to perform the operation. It says to use zero-extension.
97
98 If TARGET is nonzero, the value
99 is generated there, if it is convenient to do so.
100 In all cases an rtx is returned for the locus of the value;
101 this may or may not be TARGET. */
102
103rtx
104expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
105 enum machine_mode mode;
106 optab binoptab;
107 rtx op0, op1;
108 rtx target;
109 int unsignedp;
110 enum optab_methods methods;
111{
112 enum mode_class class;
113 enum machine_mode wider_mode;
114 register rtx temp;
115 rtx last;
116
117 class = GET_MODE_CLASS (mode);
118
119 op0 = protect_from_queue (op0, 0);
120 op1 = protect_from_queue (op1, 0);
121 if (target)
122 target = protect_from_queue (target, 1);
123
124#if 0
125 /* We may get better code by generating the result in a register
126 when the target is not one of the operands. */
127 if (target && ! rtx_equal_p (target, op1) && ! rtx_equal_p (target, op0))
128 target_is_not_an_operand = 1;
129#endif
130
131 if (flag_force_mem)
132 {
133 op0 = force_not_mem (op0);
134 op1 = force_not_mem (op1);
135 }
136
137 /* Record where to delete back to if we backtrack. */
138 last = get_last_insn ();
139
140 /* If operation is commutative,
141 try to make the first operand a register.
142 Even better, try to make it the same as the target.
143 Also try to make the last operand a constant. */
144 if (binoptab == add_optab
145 || binoptab == and_optab
146 || binoptab == ior_optab
147 || binoptab == xor_optab
148 || binoptab == smul_optab
149 || binoptab == umul_optab
150 || binoptab == smul_widen_optab
151 || binoptab == umul_widen_optab)
152 {
153 if (((target == 0 || GET_CODE (target) == REG)
154 ? ((GET_CODE (op1) == REG
155 && GET_CODE (op0) != REG)
156 || target == op1)
157 : rtx_equal_p (op1, target))
158 ||
159 GET_CODE (op0) == CONST_INT)
160 {
161 temp = op1;
162 op1 = op0;
163 op0 = temp;
164 }
165 }
166
167 /* If we can do it with a three-operand insn, do so. */
168
169 if (methods != OPTAB_MUST_WIDEN
170 && binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
171 {
172 int icode = (int) binoptab->handlers[(int) mode].insn_code;
173 enum machine_mode mode0 = insn_operand_mode[icode][1];
174 enum machine_mode mode1 = insn_operand_mode[icode][2];
175 rtx pat;
176 rtx xop0 = op0, xop1 = op1;
177
178 if (target)
179 temp = target;
180 else
181 temp = gen_reg_rtx (mode);
182
183 /* In case the insn wants input operands in modes different from
184 the result, convert the operands. */
185
186 if (GET_MODE (op0) != VOIDmode
187 && GET_MODE (op0) != mode0)
188 xop0 = convert_to_mode (mode0, xop0, unsignedp);
189
190 if (GET_MODE (xop1) != VOIDmode
191 && GET_MODE (xop1) != mode1)
192 xop1 = convert_to_mode (mode1, xop1, unsignedp);
193
194 /* Now, if insn requires register operands, put operands into regs. */
195
196 if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))
197 xop0 = force_reg (mode0, xop0);
198
199 if (! (*insn_operand_predicate[icode][2]) (xop1, mode1))
200 xop1 = force_reg (mode1, xop1);
201
202 if (! (*insn_operand_predicate[icode][0]) (temp, mode))
203 temp = gen_reg_rtx (mode);
204
205 pat = GEN_FCN (icode) (temp, xop0, xop1);
206 if (pat)
207 {
208 emit_insn (pat);
209 return temp;
210 }
211 else
212 delete_insns_since (last);
213 }
214
215 /* It can't be open-coded in this mode.
216 Use a library call if one is available and caller says that's ok. */
217
218 if (binoptab->handlers[(int) mode].lib_call
219 && (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN))
220 {
221 rtx insn_before, insn_first, insn_last;
222 rtx funexp = gen_rtx (SYMBOL_REF, Pmode,
223 binoptab->handlers[(int) mode].lib_call);
224
225 /* Pass the address through a pseudoreg, if desired,
226 before the "beginning" of the library call.
227 So this insn isn't "part of" the library call, in case that
228 is deleted, or cse'd. */
229#ifndef NO_FUNCTION_CSE
230 if (! flag_no_function_cse)
231 funexp = copy_to_mode_reg (Pmode, funexp);
232#endif
233
234 insn_before = get_last_insn ();
235
236 /* Cannot pass FUNEXP since emit_library_call insists
237 on getting a SYMBOL_REF. But cse will make this SYMBOL_REF
238 be replaced with the copy we made just above. */
239 /* Pass 1 for NO_QUEUE so we don't lose any increments
240 if the libcall is cse'd or moved. */
241 emit_library_call (gen_rtx (SYMBOL_REF, Pmode,
242 binoptab->handlers[(int) mode].lib_call),
243 1, mode, 2, op0, mode, op1, mode);
244 target = hard_libcall_value (mode);
245 temp = copy_to_reg (target);
246
247 if (insn_before == 0)
248 insn_first = get_insns ();
249 else
250 insn_first = NEXT_INSN (insn_before);
251 insn_last = get_last_insn ();
252
253 REG_NOTES (insn_last)
254 = gen_rtx (EXPR_LIST, REG_EQUAL,
255 gen_rtx (binoptab->code, mode, op0, op1),
256 gen_rtx (INSN_LIST, REG_RETVAL, insn_first,
257 REG_NOTES (insn_last)));
258 REG_NOTES (insn_first)
259 = gen_rtx (INSN_LIST, REG_LIBCALL, insn_last,
260 REG_NOTES (insn_first));
261 return temp;
262 }
263
264 delete_insns_since (last);
265
266 /* It can't be done in this mode. Can we do it in a wider mode? */
267
268 if (! (methods == OPTAB_WIDEN || methods == OPTAB_LIB_WIDEN
269 || methods == OPTAB_MUST_WIDEN))
270 return 0; /* Caller says, don't even try. */
271
272 /* Compute the value of METHODS to pass to recursive calls.
273 Don't allow widening to be tried recursively. */
274
275 methods = (methods == OPTAB_LIB_WIDEN ? OPTAB_LIB : OPTAB_DIRECT);
276
277 /* Widening is now independent of specific machine modes.
278 It is assumed that widening may be performed to any
279 higher numbered mode in the same mode class. */
280
281 if (class == MODE_INT || class == MODE_FLOAT)
282 {
283 for (wider_mode = INC_MODE (mode);
284 ((int) wider_mode < (int) MAX_MACHINE_MODE
285 && GET_MODE_CLASS (wider_mode) == class);
286 wider_mode = INC_MODE (wider_mode))
287 {
288 if ((binoptab->handlers[(int) wider_mode].insn_code
289 != CODE_FOR_nothing)
290 || (methods == OPTAB_LIB
291 && binoptab->handlers[(int) wider_mode].lib_call))
292 {
293 rtx xop0 = op0, xop1 = op1;
294 int no_extend = 0;
295
296 /* For certain operations, we need not actually extend
297 the narrow operands, as long as we will truncate
298 the results to the same narrowness. */
299
300 if (binoptab == ior_optab || binoptab == and_optab
301 || binoptab == xor_optab || binoptab == andcb_optab
302 || binoptab == add_optab || binoptab == sub_optab
303 || binoptab == smul_optab || binoptab == umul_optab
304 || binoptab == ashl_optab || binoptab == lshl_optab)
305 no_extend = 1;
306
307 if (GET_MODE (xop0) != VOIDmode)
308 {
309 if (no_extend)
310 {
311 temp = force_reg (GET_MODE (xop0), xop0);
312 xop0 = gen_rtx (SUBREG, wider_mode, temp, 0);
313 }
314 else
315 {
316 temp = gen_reg_rtx (wider_mode);
317 convert_move (temp, xop0, unsignedp);
318 xop0 = temp;
319 }
320 }
321 if (GET_MODE (xop1) != VOIDmode)
322 {
323 if (no_extend)
324 {
325 temp = force_reg (GET_MODE (xop1), xop1);
326 xop1 = gen_rtx (SUBREG, wider_mode, temp, 0);
327 }
328 else
329 {
330 temp = gen_reg_rtx (wider_mode);
331 convert_move (temp, xop1, unsignedp);
332 xop1 = temp;
333 }
334 }
335
336 temp = expand_binop (wider_mode, binoptab, xop0, xop1, 0,
337 unsignedp, methods);
338 if (temp)
339 {
340 if (class == MODE_FLOAT)
341 {
342 if (target == 0)
343 target = gen_reg_rtx (mode);
344 convert_move (target, temp, 0);
345 return target;
346 }
347 else
348 return gen_lowpart (mode, temp);
349 }
350 else
351 delete_insns_since (last);
352 }
353 }
354 }
355
356 return 0;
357}
358\f
359/* Expand a binary operator which has both signed and unsigned forms.
360 UOPTAB is the optab for unsigned operations, and SOPTAB is for
361 signed operations.
362
363 If we widen unsigned operands, we may use a signed wider operation instead
364 of an unsigned wider operation, since the result would be the same. */
365
366rtx
367sign_expand_binop (mode, uoptab, soptab, op0, op1, target, unsignedp, methods)
368 enum machine_mode mode;
369 optab uoptab, soptab;
370 rtx op0, op1, target;
371 int unsignedp;
372 enum optab_methods methods;
373{
374 register rtx temp;
375 optab direct_optab = unsignedp ? uoptab : soptab;
376 struct optab wide_soptab;
377
378 /* Do it without widening, if possible. */
379 temp = expand_binop (mode, direct_optab, op0, op1, target,
380 unsignedp, OPTAB_DIRECT);
381 if (temp || methods == OPTAB_DIRECT)
382 return temp;
383
384 /* Try widening to a signed int. Make a fake signed optab that
385 hides any signed insn for direct use. */
386 wide_soptab = *soptab;
387 wide_soptab.handlers[(int) mode].insn_code = CODE_FOR_nothing;
388 wide_soptab.handlers[(int) mode].lib_call = 0;
389
390 temp = expand_binop (mode, &wide_soptab, op0, op1, target,
391 unsignedp, OPTAB_WIDEN);
392
393 /* For unsigned operands, try widening to an unsigned int. */
394 if (temp == 0 && unsignedp)
395 temp = expand_binop (mode, uoptab, op0, op1, target,
396 unsignedp, OPTAB_WIDEN);
397 if (temp || methods == OPTAB_WIDEN)
398 return temp;
399
400 /* Use the right width lib call if that exists. */
401 temp = expand_binop (mode, direct_optab, op0, op1, target, unsignedp, OPTAB_LIB);
402 if (temp || methods == OPTAB_LIB)
403 return temp;
404
405 /* Must widen and use a lib call, use either signed or unsigned. */
406 temp = expand_binop (mode, &wide_soptab, op0, op1, target,
407 unsignedp, methods);
408 if (temp != 0)
409 return temp;
410 if (unsignedp)
411 return expand_binop (mode, uoptab, op0, op1, target,
412 unsignedp, methods);
413 return 0;
414}
415\f
416/* Generate code to perform an operation specified by BINOPTAB
417 on operands OP0 and OP1, with two results to TARG1 and TARG2.
418 We assume that the order of the operands for the instruction
419 is TARG0, OP0, OP1, TARG1, which would fit a pattern like
420 [(set TARG0 (operate OP0 OP1)) (set TARG1 (operate ...))].
421
422 Either TARG0 or TARG1 may be zero, but what that means is that
423 that result is not actually wanted. We will generate it into
424 a dummy pseudo-reg and discard it. They may not both be zero.
425
426 Returns 1 if this operation can be performed; 0 if not. */
427
428int
429expand_twoval_binop (binoptab, op0, op1, targ0, targ1, unsignedp)
430 optab binoptab;
431 rtx op0, op1;
432 rtx targ0, targ1;
433 int unsignedp;
434{
435 enum machine_mode mode = GET_MODE (targ0 ? targ0 : targ1);
436 enum mode_class class;
437 enum machine_mode wider_mode;
438
439 class = GET_MODE_CLASS (mode);
440
441 op0 = protect_from_queue (op0, 0);
442 op1 = protect_from_queue (op1, 0);
443
444 if (flag_force_mem)
445 {
446 op0 = force_not_mem (op0);
447 op1 = force_not_mem (op1);
448 }
449
450 if (targ0)
451 targ0 = protect_from_queue (targ0, 1);
452 else
453 targ0 = gen_reg_rtx (mode);
454 if (targ1)
455 targ1 = protect_from_queue (targ1, 1);
456 else
457 targ1 = gen_reg_rtx (mode);
458
459 if (binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
460 {
461 emit_insn (GEN_FCN (binoptab->handlers[(int) mode].insn_code)
462 (targ0, op0, op1, targ1));
463 return 1;
464 }
465
466 /* It can't be done in this mode. Can we do it in a wider mode? */
467
468 if (class == MODE_INT || class == MODE_FLOAT)
469 {
470 for (wider_mode = INC_MODE (mode);
471 ((int) wider_mode < (int) MAX_MACHINE_MODE
472 && GET_MODE_CLASS (wider_mode) == class);
473 wider_mode = INC_MODE (wider_mode))
474 {
475 if (binoptab->handlers[(int) wider_mode].insn_code
476 != CODE_FOR_nothing)
477 {
478 expand_twoval_binop_convert (binoptab, wider_mode, op0, op1,
479 targ0, targ1, unsignedp);
480 return 1;
481 }
482 }
483 }
484 return 0;
485}
486
487int
488expand_twoval_binop_convert (binoptab, mode, op0, op1, targ0, targ1, unsignedp)
489 register optab binoptab;
490 register rtx op0, op1, targ0, targ1;
491 int unsignedp;
492{
493 register rtx t0 = gen_reg_rtx (SImode);
494 register rtx t1 = gen_reg_rtx (SImode);
495 register rtx temp;
496
497 temp = gen_reg_rtx (SImode);
498 convert_move (temp, op0, unsignedp);
499 op0 = temp;
500 temp = gen_reg_rtx (SImode);
501 convert_move (temp, op1, unsignedp);
502 op1 = temp;
503
504 expand_twoval_binop (binoptab, op0, op1, t0, t1, unsignedp);
505 convert_move (targ0, t0, unsignedp);
506 convert_move (targ1, t1, unsignedp);
507 return 1;
508}
509\f
510/* Generate code to perform an operation specified by UNOPTAB
511 on operand OP0, with result having machine-mode MODE.
512
513 UNSIGNEDP is for the case where we have to widen the operands
514 to perform the operation. It says to use zero-extension.
515
516 If TARGET is nonzero, the value
517 is generated there, if it is convenient to do so.
518 In all cases an rtx is returned for the locus of the value;
519 this may or may not be TARGET. */
520
521rtx
522expand_unop (mode, unoptab, op0, target, unsignedp)
523 enum machine_mode mode;
524 optab unoptab;
525 rtx op0;
526 rtx target;
527 int unsignedp;
528{
529 enum mode_class class;
530 enum machine_mode wider_mode;
531 register rtx temp;
532
533 class = GET_MODE_CLASS (mode);
534
535 op0 = protect_from_queue (op0, 0);
536
537 if (flag_force_mem)
538 {
539 op0 = force_not_mem (op0);
540 }
541
542 if (target)
543 target = protect_from_queue (target, 1);
544
545 if (unoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
546 {
547 int icode = (int) unoptab->handlers[(int) mode].insn_code;
548 enum machine_mode mode0 = insn_operand_mode[icode][1];
549
550 if (target)
551 temp = target;
552 else
553 temp = gen_reg_rtx (mode);
554
555 if (GET_MODE (op0) != VOIDmode
556 && GET_MODE (op0) != mode0)
557 op0 = convert_to_mode (mode0, op0, unsignedp);
558
559 /* Now, if insn requires register operands, put operands into regs. */
560
561 if (! (*insn_operand_predicate[icode][1]) (op0, mode0))
562 op0 = force_reg (mode0, op0);
563
564 if (! (*insn_operand_predicate[icode][0]) (temp, mode))
565 temp = gen_reg_rtx (mode);
566
567 emit_insn (GEN_FCN (icode) (temp, op0));
568 return temp;
569 }
570 else if (unoptab->handlers[(int) mode].lib_call)
571 {
572 rtx insn_before, insn_last;
573 rtx funexp = gen_rtx (SYMBOL_REF, Pmode,
574 unoptab->handlers[(int) mode].lib_call);
575
576 /* Pass the address through a pseudoreg, if desired,
577 before the "beginning" of the library call (for deletion). */
578#ifndef NO_FUNCTION_CSE
579 if (! flag_no_function_cse)
580 funexp = copy_to_mode_reg (Pmode, funexp);
581#endif
582
583 insn_before = get_last_insn ();
584
585 /* Cannot pass FUNEXP since emit_library_call insists
586 on getting a SYMBOL_REF. But cse will make this SYMBOL_REF
587 be replaced with the copy we made just above. */
588 /* Pass 1 for NO_QUEUE so we don't lose any increments
589 if the libcall is cse'd or moved. */
590 emit_library_call (gen_rtx (SYMBOL_REF, Pmode,
591 unoptab->handlers[(int) mode].lib_call),
592 1, mode, 1, op0, mode);
593 target = hard_libcall_value (mode);
594 temp = copy_to_reg (target);
595 insn_last = get_last_insn ();
596 REG_NOTES (insn_last)
597 = gen_rtx (EXPR_LIST, REG_EQUAL,
598 gen_rtx (unoptab->code, mode, op0),
599 gen_rtx (INSN_LIST, REG_RETVAL,
600 NEXT_INSN (insn_before),
601 REG_NOTES (insn_last)));
602 REG_NOTES (NEXT_INSN (insn_before))
603 = gen_rtx (INSN_LIST, REG_LIBCALL, insn_last,
604 REG_NOTES (NEXT_INSN (insn_before)));
605 return temp;
606 }
607
608 /* It can't be done in this mode. Can we do it in a wider mode? */
609
610 if (class == MODE_INT || class == MODE_FLOAT)
611 {
612 for (wider_mode = INC_MODE (mode);
613 ((int) wider_mode < (int) MAX_MACHINE_MODE
614 && GET_MODE_CLASS (wider_mode) == class);
615 wider_mode = INC_MODE (wider_mode))
616 {
617 if ((unoptab->handlers[(int) wider_mode].insn_code
618 != CODE_FOR_nothing)
619 || unoptab->handlers[(int) wider_mode].lib_call)
620 {
621 if (GET_MODE (op0) != VOIDmode)
622 {
623 temp = gen_reg_rtx (wider_mode);
624 convert_move (temp, op0, unsignedp);
625 op0 = temp;
626 }
627
628 target = expand_unop (wider_mode, unoptab, op0, 0, unsignedp);
629 if (class == MODE_FLOAT)
630 {
631 if (target == 0)
632 target = gen_reg_rtx (mode);
633 convert_move (target, temp, 0);
634 return target;
635 }
636 else
637 return gen_lowpart (mode, target);
638 }
639 }
640 }
641
642 return 0;
643}
644\f
645/* Generate an instruction whose insn-code is INSN_CODE,
646 with two operands: an output TARGET and an input OP0.
647 TARGET *must* be nonzero, and the output is always stored there.
648 CODE is an rtx code such that (CODE OP0) is an rtx that describes
649 the value that is stored into TARGET. */
650
651void
652emit_unop_insn (icode, target, op0, code)
653 int icode;
654 rtx target;
655 rtx op0;
656 enum rtx_code code;
657{
658 register rtx temp;
659 enum machine_mode mode0 = insn_operand_mode[icode][1];
660 rtx insn;
661 rtx prev_insn;
662
663 temp = target = protect_from_queue (target, 1);
664
665 op0 = protect_from_queue (op0, 0);
666
667 if (flag_force_mem)
668 op0 = force_not_mem (op0);
669
670 /* Now, if insn requires register operands, put operands into regs. */
671
672 if (! (*insn_operand_predicate[icode][1]) (op0, mode0))
673 op0 = force_reg (mode0, op0);
674
675 if (! (*insn_operand_predicate[icode][0]) (temp, GET_MODE (temp))
676 || (flag_force_mem && GET_CODE (temp) == MEM))
677 temp = gen_reg_rtx (GET_MODE (temp));
678
679 prev_insn = get_last_insn ();
680 insn = emit_insn (GEN_FCN (icode) (temp, op0));
681
682 /* If we just made a multi-insn sequence,
683 record in the last insn an equivalent expression for its value
684 and a pointer to the first insn. This makes cse possible. */
685 if (code != UNKNOWN && PREV_INSN (insn) != prev_insn)
686 REG_NOTES (insn)
687 = gen_rtx (EXPR_LIST, REG_EQUAL,
688 gen_rtx (code, GET_MODE (temp), op0),
689 REG_NOTES (insn));
690
691 if (temp != target)
692 emit_move_insn (target, temp);
693}
694\f
695/* Generate code to store zero in X. */
696
697void
698emit_clr_insn (x)
699 rtx x;
700{
701 emit_move_insn (x, const0_rtx);
702}
703
704/* Generate code to store 1 in X
705 assuming it contains zero beforehand. */
706
707void
708emit_0_to_1_insn (x)
709 rtx x;
710{
711 emit_move_insn (x, const1_rtx);
712}
713
714/* Generate code to compare X with Y
715 so that the condition codes are set.
716
717 UNSIGNEDP nonzero says that X and Y are unsigned;
718 this matters if they need to be widened.
719
720 If they have mode BLKmode, then SIZE specifies the size of both X and Y,
721 and ALIGN specifies the known shared alignment of X and Y. */
722
723void
724emit_cmp_insn (x, y, size, unsignedp, align)
725 rtx x, y;
726 rtx size;
727 int unsignedp;
728 int align;
729{
730 enum machine_mode mode = GET_MODE (x);
731 enum mode_class class;
732 enum machine_mode wider_mode;
733
734 if (mode == VOIDmode) mode = GET_MODE (y);
735 /* They could both be VOIDmode if both args are immediate constants,
736 but we should fold that at an earlier stage.
737 With no special code here, this will call abort,
738 reminding the programmer to implement such folding. */
739
740 class = GET_MODE_CLASS (mode);
741
742 if (mode != BLKmode && flag_force_mem)
743 {
744 x = force_not_mem (x);
745 y = force_not_mem (y);
746 }
747
748 /* Handle all BLKmode compares. */
749
750 if (mode == BLKmode)
751 {
752 emit_queue ();
753 x = protect_from_queue (x, 0);
754 y = protect_from_queue (y, 0);
755
756 if (size == 0)
757 abort ();
758#ifdef HAVE_cmpstrqi
759 if (HAVE_cmpstrqi
760 && GET_CODE (size) == CONST_INT
761 && INTVAL (size) < (1 << GET_MODE_BITSIZE (QImode)))
762 emit_insn (gen_cmpstrqi (x, y, size,
763 gen_rtx (CONST_INT, VOIDmode, align)));
764 else
765#endif
766#ifdef HAVE_cmpstrhi
767 if (HAVE_cmpstrhi
768 && GET_CODE (size) == CONST_INT
769 && INTVAL (size) < (1 << GET_MODE_BITSIZE (HImode)))
770 emit_insn (gen_cmpstrhi (x, y, size,
771 gen_rtx (CONST_INT, VOIDmode, align)));
772 else
773#endif
774#ifdef HAVE_cmpstrsi
775 if (HAVE_cmpstrsi)
776 emit_insn (gen_cmpstrsi (x, y, convert_to_mode (SImode, size, 1),
777 gen_rtx (CONST_INT, VOIDmode, align)));
778 else
779#endif
780 {
781#ifdef TARGET_MEM_FUNCTIONS
782 emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "memcmp"), 0,
783 SImode, 3,
784 XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
785 size, Pmode);
786#else
787 emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "bcmp"), 0,
788 SImode, 3,
789 XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
790 size, Pmode);
791#endif
792 emit_cmp_insn (hard_libcall_value (SImode), const0_rtx, 0, 0, 0);
793 }
794 return;
795 }
796
797 /* Handle some compares against zero. */
798
799 if (y == CONST0_RTX (mode)
800 && tst_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
801 {
802 int icode = (int) tst_optab->handlers[(int) mode].insn_code;
803
804 emit_queue ();
805 x = protect_from_queue (x, 0);
806 y = protect_from_queue (y, 0);
807
808 /* Now, if insn requires register operands, put operands into regs. */
809 if (! (*insn_operand_predicate[icode][0])
810 (x, insn_operand_mode[icode][0]))
811 x = force_reg (insn_operand_mode[icode][0], x);
812
813 emit_insn (GEN_FCN (icode) (x));
814 return;
815 }
816
817 /* Handle compares for which there is a directly suitable insn. */
818
819 if (cmp_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
820 {
821 int icode = (int) cmp_optab->handlers[(int) mode].insn_code;
822
823 emit_queue ();
824 x = protect_from_queue (x, 0);
825 y = protect_from_queue (y, 0);
826
827 /* Now, if insn requires register operands, put operands into regs. */
828 if (! (*insn_operand_predicate[icode][0])
829 (x, insn_operand_mode[icode][0]))
830 x = force_reg (insn_operand_mode[icode][0], x);
831
832 if (! (*insn_operand_predicate[icode][1])
833 (y, insn_operand_mode[icode][1]))
834 y = force_reg (insn_operand_mode[icode][1], y);
835
836 emit_insn (GEN_FCN (icode) (x, y));
837 return;
838 }
839
840 /* Try widening if we can find a direct insn that way. */
841
842 if (class == MODE_INT || class == MODE_FLOAT)
843 {
844 for (wider_mode = INC_MODE (mode);
845 ((int) wider_mode < (int) MAX_MACHINE_MODE
846 && GET_MODE_CLASS (wider_mode) == class);
847 wider_mode = INC_MODE (wider_mode))
848 {
849 if (cmp_optab->handlers[(int) wider_mode].insn_code
850 != CODE_FOR_nothing)
851 {
852 x = convert_to_mode (wider_mode, x, unsignedp);
853 y = convert_to_mode (wider_mode, y, unsignedp);
854 emit_cmp_insn (x, y, 0, unsignedp, align);
855 return;
856 }
857 }
858 }
859
860 /* Handle a lib call just for the mode we are using. */
861
862 if (cmp_optab->handlers[(int) mode].lib_call)
863 {
864 char *string = cmp_optab->handlers[(int) mode].lib_call;
865 /* If we want unsigned, and this mode has a distinct unsigned
866 comparison routine, use that. */
867 if (unsignedp && ucmp_optab->handlers[(int) mode].lib_call)
868 string = ucmp_optab->handlers[(int) mode].lib_call;
869
870 emit_library_call (gen_rtx (SYMBOL_REF, Pmode, string), 0,
871 SImode, 2, x, mode, y, mode);
872
873 /* Integer comparison returns a result that must be compared against 1,
874 so that even if we do an unsigned compare afterward,
875 there is still a value that can represent the result "less than". */
876 if (GET_MODE_CLASS (mode) == MODE_INT)
877 emit_cmp_insn (hard_libcall_value (SImode), const1_rtx, 0, unsignedp, 0);
878 else
879 emit_cmp_insn (hard_libcall_value (SImode), const0_rtx, 0, 0, 0);
880 return;
881 }
882
883 /* Try widening and then using a libcall. */
884
885 if (class == MODE_FLOAT)
886 {
887 for (wider_mode = INC_MODE (mode);
888 ((int) wider_mode < (int) MAX_MACHINE_MODE
889 && GET_MODE_CLASS (wider_mode) == class);
890 wider_mode = INC_MODE (wider_mode))
891 {
892 if ((cmp_optab->handlers[(int) wider_mode].insn_code
893 != CODE_FOR_nothing)
894 || (cmp_optab->handlers[(int) wider_mode].lib_call != 0))
895 {
896 x = convert_to_mode (wider_mode, x, unsignedp);
897 y = convert_to_mode (wider_mode, y, unsignedp);
898 emit_cmp_insn (x, y, 0, unsignedp, align);
899 }
900 }
901 return;
902 }
903
904 abort ();
905}
906\f
907/* These three functions generate an insn body and return it
908 rather than emitting the insn.
909
910 They do not protect from queued increments,
911 because they may be used 1) in protect_from_queue itself
912 and 2) in other passes where there is no queue. */
913
914/* Generate and return an insn body to add Y to X. */
915
916rtx
917gen_add2_insn (x, y)
918 rtx x, y;
919{
920 return (GEN_FCN (add_optab->handlers[(int) GET_MODE (x)].insn_code)
921 (x, x, y));
922}
923
924int
925have_add2_insn (mode)
926 enum machine_mode mode;
927{
928 return add_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing;
929}
930
931/* Generate and return an insn body to subtract Y from X. */
932
933rtx
934gen_sub2_insn (x, y)
935 rtx x, y;
936{
937 return (GEN_FCN (sub_optab->handlers[(int) GET_MODE (x)].insn_code)
938 (x, x, y));
939}
940
941int
942have_sub2_insn (mode)
943 enum machine_mode mode;
944{
945 return add_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing;
946}
947
948/* Generate the body of an instruction to copy Y into X. */
949
950rtx
951gen_move_insn (x, y)
952 rtx x, y;
953{
954 register enum machine_mode mode = GET_MODE (x);
955 if (mode == VOIDmode)
956 mode = GET_MODE (y);
957 return (GEN_FCN (mov_optab->handlers[(int) mode].insn_code) (x, y));
958}
959\f
960#if 0
961/* Tables of patterns for extending one integer mode to another. */
962enum insn_code zero_extend_optab[MAX_MACHINE_MODE][MAX_MACHINE_MODE];
963enum insn_code sign_extend_optab[MAX_MACHINE_MODE][MAX_MACHINE_MODE];
964
965/* Generate the body of an insn to extend Y (with mode MFROM)
966 into X (with mode MTO). Do zero-extension if UNSIGNEDP is nonzero. */
967
968rtx
969gen_extend_insn (x, y, mto, mfrom, unsignedp)
970 rtx x, y;
971 enum machine_mode mto, mfrom;
972 int unsignedp;
973{
974 return (GEN_FCN ((unsignedp ? zero_extend_optab : sign_extend_optab)
975 [(int)mto][(int)mfrom])
976 (x, y));
977}
978
979static void
980init_extends ()
981{
982 bzero (sign_extend_optab, sizeof sign_extend_optab);
983 bzero (zero_extend_optab, sizeof zero_extend_optab);
984 sign_extend_optab[(int) SImode][(int) HImode] = CODE_FOR_extendhisi2;
985 sign_extend_optab[(int) SImode][(int) QImode] = CODE_FOR_extendqisi2;
986 sign_extend_optab[(int) HImode][(int) QImode] = CODE_FOR_extendqihi2;
987 zero_extend_optab[(int) SImode][(int) HImode] = CODE_FOR_zero_extendhisi2;
988 zero_extend_optab[(int) SImode][(int) QImode] = CODE_FOR_zero_extendqisi2;
989 zero_extend_optab[(int) HImode][(int) QImode] = CODE_FOR_zero_extendqihi2;
990}
991#endif
992\f
993/* can_fix_p and can_float_p say whether the target machine
994 can directly convert a given fixed point type to
995 a given floating point type, or vice versa.
996 The returned value is the CODE_FOR_... value to use,
997 or CODE_FOR_nothing if these modes cannot be directly converted. */
998
999static enum insn_code fixtab[2][2][2];
1000static enum insn_code fixtrunctab[2][2][2];
1001static enum insn_code floattab[2][2];
1002
1003/* *TRUNCP_PTR is set to 1 if it is necessary to output
1004 an explicit FTRUNC insn before the fix insn; otherwise 0. */
1005
1006static enum insn_code
1007can_fix_p (fixmode, fltmode, unsignedp, truncp_ptr)
1008 enum machine_mode fltmode, fixmode;
1009 int unsignedp;
1010 int *truncp_ptr;
1011{
1012 *truncp_ptr = 0;
1013 if (fixtrunctab[fltmode != SFmode][fixmode == DImode][unsignedp]
1014 != CODE_FOR_nothing)
1015 return fixtrunctab[fltmode != SFmode][fixmode == DImode][unsignedp];
1016 if (ftrunc_optab->handlers[(int) fltmode].insn_code != CODE_FOR_nothing)
1017 {
1018 *truncp_ptr = 1;
1019 return fixtab[fltmode != SFmode][fixmode == DImode][unsignedp];
1020 }
1021 return CODE_FOR_nothing;
1022}
1023
1024static enum insn_code
1025can_float_p (fltmode, fixmode)
1026 enum machine_mode fixmode, fltmode;
1027{
1028 return floattab[fltmode != SFmode][fixmode == DImode];
1029}
1030
1031void
1032init_fixtab ()
1033{
1034 enum insn_code *p;
1035 for (p = fixtab[0][0];
1036 p < fixtab[0][0] + sizeof fixtab / sizeof (fixtab[0][0][0]);
1037 p++)
1038 *p = CODE_FOR_nothing;
1039 for (p = fixtrunctab[0][0];
1040 p < fixtrunctab[0][0] + sizeof fixtrunctab / sizeof (fixtrunctab[0][0][0]);
1041 p++)
1042 *p = CODE_FOR_nothing;
1043
1044#ifdef HAVE_fixsfsi2
1045 if (HAVE_fixsfsi2)
1046 fixtab[0][0][0] = CODE_FOR_fixsfsi2;
1047#endif
1048#ifdef HAVE_fixsfdi2
1049 if (HAVE_fixsfdi2)
1050 fixtab[0][1][0] = CODE_FOR_fixsfdi2;
1051#endif
1052#ifdef HAVE_fixdfsi2
1053 if (HAVE_fixdfsi2)
1054 fixtab[1][0][0] = CODE_FOR_fixdfsi2;
1055#endif
1056#ifdef HAVE_fixdfdi2
1057 if (HAVE_fixdfdi2)
1058 fixtab[1][1][0] = CODE_FOR_fixdfdi2;
1059#endif
1060
1061#ifdef HAVE_fixunssfsi2
1062 if (HAVE_fixunssfsi2)
1063 fixtab[0][0][1] = CODE_FOR_fixunssfsi2;
1064#endif
1065#ifdef HAVE_fixunssfdi2
1066 if (HAVE_fixunssfdi2)
1067 fixtab[0][1][1] = CODE_FOR_fixunssfdi2;
1068#endif
1069#ifdef HAVE_fixunsdfsi2
1070 if (HAVE_fixunsdfsi2)
1071 fixtab[1][0][1] = CODE_FOR_fixunsdfsi2;
1072#endif
1073#ifdef HAVE_fixunsdfdi2
1074 if (HAVE_fixunsdfdi2)
1075 fixtab[1][1][1] = CODE_FOR_fixunsdfdi2;
1076#endif
1077
1078#ifdef HAVE_fix_truncsfsi2
1079 if (HAVE_fix_truncsfsi2)
1080 fixtrunctab[0][0][0] = CODE_FOR_fix_truncsfsi2;
1081#endif
1082#ifdef HAVE_fix_truncsfdi2
1083 if (HAVE_fix_truncsfdi2)
1084 fixtrunctab[0][1][0] = CODE_FOR_fix_truncsfdi2;
1085#endif
1086#ifdef HAVE_fix_truncdfsi2
1087 if (HAVE_fix_truncdfsi2)
1088 fixtrunctab[1][0][0] = CODE_FOR_fix_truncdfsi2;
1089#endif
1090#ifdef HAVE_fix_truncdfdi2
1091 if (HAVE_fix_truncdfdi2)
1092 fixtrunctab[1][1][0] = CODE_FOR_fix_truncdfdi2;
1093#endif
1094
1095#ifdef HAVE_fixuns_truncsfsi2
1096 if (HAVE_fixuns_truncsfsi2)
1097 fixtrunctab[0][0][1] = CODE_FOR_fixuns_truncsfsi2;
1098#endif
1099#ifdef HAVE_fixuns_truncsfdi2
1100 if (HAVE_fixuns_truncsfdi2)
1101 fixtrunctab[0][1][1] = CODE_FOR_fixuns_truncsfdi2;
1102#endif
1103#ifdef HAVE_fixuns_truncdfsi2
1104 if (HAVE_fixuns_truncdfsi2)
1105 fixtrunctab[1][0][1] = CODE_FOR_fixuns_truncdfsi2;
1106#endif
1107#ifdef HAVE_fixuns_truncdfdi2
1108 if (HAVE_fixuns_truncdfdi2)
1109 fixtrunctab[1][1][1] = CODE_FOR_fixuns_truncdfdi2;
1110#endif
1111
1112#ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC
1113 /* This flag says the same insns that convert to a signed fixnum
1114 also convert validly to an unsigned one. */
1115 {
1116 int i;
1117 int j;
1118 for (i = 0; i < 2; i++)
1119 for (j = 0; j < 2; j++)
1120 fixtrunctab[i][j][1] = fixtrunctab[i][j][0];
1121 }
1122#endif
1123}
1124
1125void
1126init_floattab ()
1127{
1128 enum insn_code *p;
1129 for (p = floattab[0];
1130 p < floattab[0] + sizeof floattab / sizeof (floattab[0][0]);
1131 p++)
1132 *p = CODE_FOR_nothing;
1133
1134#ifdef HAVE_floatsisf2
1135 if (HAVE_floatsisf2)
1136 floattab[0][0] = CODE_FOR_floatsisf2;
1137#endif
1138#ifdef HAVE_floatdisf2
1139 if (HAVE_floatdisf2)
1140 floattab[0][1] = CODE_FOR_floatdisf2;
1141#endif
1142#ifdef HAVE_floatsidf2
1143 if (HAVE_floatsidf2)
1144 floattab[1][0] = CODE_FOR_floatsidf2;
1145#endif
1146#ifdef HAVE_floatdidf2
1147 if (HAVE_floatdidf2)
1148 floattab[1][1] = CODE_FOR_floatdidf2;
1149#endif
1150}
1151\f
1152/* Generate code to convert FROM to floating point
1153 and store in TO. FROM must be fixed point.
1154 UNSIGNEDP nonzero means regard FROM as unsigned.
1155 Normally this is done by correcting the final value
1156 if it is negative. */
1157
1158void
1159expand_float (real_to, from, unsignedp)
1160 rtx real_to, from;
1161 int unsignedp;
1162{
1163 enum insn_code icode;
1164 register rtx to;
1165
1166 /* Constants should get converted in `fold'.
1167 We lose here since we don't know the mode. */
1168 if (GET_MODE (from) == VOIDmode)
1169 abort ();
1170
1171 to = real_to = protect_from_queue (real_to, 1);
1172 from = protect_from_queue (from, 0);
1173
1174 if (flag_force_mem)
1175 {
1176 from = force_not_mem (from);
1177 }
1178
1179 /* If we are about to do some arithmetic to correct for an
1180 unsigned operand, do it in a pseudo-register. */
1181
1182 if (unsignedp
1183 && ! (GET_CODE (to) == REG && REGNO (to) >= FIRST_PSEUDO_REGISTER))
1184 to = gen_reg_rtx (GET_MODE (to));
1185
1186 /* Now do the basic conversion. Do it in the specified modes if possible;
1187 otherwise convert either input, output or both with wider mode;
1188 otherwise use a library call. */
1189
1190 if ((icode = can_float_p (GET_MODE (to), GET_MODE (from)))
1191 != CODE_FOR_nothing)
1192 {
1193 emit_unop_insn (icode, to, from, FLOAT);
1194 }
1195 else if (GET_MODE (to) == SFmode
1196 && ((icode = can_float_p (DFmode, GET_MODE (from)))
1197 != CODE_FOR_nothing))
1198 {
1199 to = gen_reg_rtx (DFmode);
1200 emit_unop_insn (icode, to, from, FLOAT);
1201 }
1202 /* If we can't float a SI, maybe we can float a DI.
1203 If so, convert to DI and then float. */
1204 else if (GET_MODE (from) != DImode
1205 && (can_float_p (GET_MODE (to), DImode) != CODE_FOR_nothing
1206 || can_float_p (DFmode, DImode) != CODE_FOR_nothing))
1207 {
1208 register rtx tem = gen_reg_rtx (DImode);
1209 convert_move (tem, from, unsignedp);
1210 from = tem;
1211 /* If we extend FROM then we don't need to correct
1212 the final value for unsignedness. */
1213 unsignedp = 0;
1214
1215 if ((icode = can_float_p (GET_MODE (to), GET_MODE (from)))
1216 != CODE_FOR_nothing)
1217 {
1218 emit_unop_insn (icode, to, from, FLOAT);
1219 }
1220 else if ((icode = can_float_p (DFmode, DImode))
1221 != CODE_FOR_nothing)
1222 {
1223 to = gen_reg_rtx (DFmode);
1224 emit_unop_insn (icode, to, from, FLOAT);
1225 }
1226 }
1227 /* No hardware instruction available; call a library
1228 to convert from SImode or DImode into DFmode. */
1229 else
1230 {
1231 if (GET_MODE_SIZE (GET_MODE (from)) < GET_MODE_SIZE (SImode))
1232 {
1233 from = convert_to_mode (SImode, from, unsignedp);
1234 unsignedp = 0;
1235 }
1236 emit_library_call (gen_rtx (SYMBOL_REF, Pmode,
1237 (GET_MODE (from) == SImode ? "__floatsidf"
1238 : "__floatdidf")),
1239 0, DFmode, 1, from, GET_MODE (from));
1240 to = copy_to_reg (hard_libcall_value (DFmode));
1241 }
1242
1243 /* If FROM was unsigned but we treated it as signed,
1244 then in the case where it is negative (and therefore TO is negative),
1245 correct its value by 2**bitwidth. */
1246
1247 if (unsignedp)
1248 {
1249 rtx label = gen_label_rtx ();
1250 rtx temp;
1251 REAL_VALUE_TYPE offset;
1252
1253 do_pending_stack_adjust ();
1254 emit_cmp_insn (to, GET_MODE (to) == DFmode ? dconst0_rtx : fconst0_rtx,
1255 0, 0, 0);
1256 emit_jump_insn (gen_bge (label));
1257 offset = REAL_VALUE_LDEXP (1.0, GET_MODE_BITSIZE (GET_MODE (from)));
1258 temp = expand_binop (GET_MODE (to), add_optab, to,
1259 immed_real_const_1 (offset, GET_MODE (to)),
1260 to, 0, OPTAB_LIB_WIDEN);
1261 if (temp != to)
1262 emit_move_insn (to, temp);
1263 do_pending_stack_adjust ();
1264 emit_label (label);
1265 }
1266
1267 /* Copy result to requested destination
1268 if we have been computing in a temp location. */
1269
1270 if (to != real_to)
1271 {
1272 if (GET_MODE (real_to) == GET_MODE (to))
1273 emit_move_insn (real_to, to);
1274 else
1275 convert_move (real_to, to, 0);
1276 }
1277}
1278\f
1279/* expand_fix: generate code to convert FROM to fixed point
1280 and store in TO. FROM must be floating point. */
1281
1282static rtx
1283ftruncify (x)
1284 rtx x;
1285{
1286 rtx temp = gen_reg_rtx (GET_MODE (x));
1287 return expand_unop (GET_MODE (x), ftrunc_optab, x, temp, 0);
1288}
1289
1290void
1291expand_fix (to, from, unsignedp)
1292 register rtx to, from;
1293 int unsignedp;
1294{
1295 enum insn_code icode;
1296 register rtx target;
1297 int must_trunc = 0;
1298
1299 while (1)
1300 {
1301 icode = can_fix_p (GET_MODE (to), GET_MODE (from), unsignedp, &must_trunc);
1302 if (icode != CODE_FOR_nothing)
1303 {
1304 if (must_trunc)
1305 from = ftruncify (from);
1306
1307 emit_unop_insn (icode, to, from, FIX);
1308 return;
1309 }
1310
1311#if 0 /* Turned off. It fails because the positive numbers
1312 that become temporarily negative are rounded up instead of down. */
1313
1314 /* If no insns for unsigned conversion,
1315 we can go via a signed number.
1316 But make sure we won't overflow in the compiler. */
1317 if (unsignedp && GET_MODE_BITSIZE (GET_MODE (to)) <= HOST_BITS_PER_INT
1318 /* Make sure we won't lose significant bits doing this. */
1319 && GET_MODE_BITSIZE (GET_MODE (from)) > GET_MODE_BITSIZE (GET_MODE (to)))
1320 {
1321 icode = can_fix_p (GET_MODE (to), GET_MODE (from),
1322 0, &must_trunc);
1323
1324 if (icode != CODE_FOR_nothing)
1325 {
1326 REAL_VALUE_TYPE offset;
1327 rtx temp, temp1;
1328 int bitsize = GET_MODE_BITSIZE (GET_MODE (to));
1329
1330 if (must_trunc)
1331 from = ftruncify (from);
1332
1333 /* Subtract 2**(N-1), convert to signed number,
1334 then add 2**(N-1). */
1335 offset = REAL_VALUE_LDEXP (1.0, bitsize - 1);
1336 temp = expand_binop (GET_MODE (from), sub_optab, from,
1337 immed_real_const_1 (offset, GET_MODE (from)),
1338 0, 0, OPTAB_LIB_WIDEN);
1339
1340 temp1 = gen_reg_rtx (GET_MODE (to));
1341 emit_unop_insn (icode, temp1, temp, FIX);
1342 temp = expand_binop (GET_MODE (to), add_optab, temp1,
1343 gen_rtx (CONST_INT, VOIDmode,
1344 1 << (bitsize - 1)),
1345 to, 1, OPTAB_LIB_WIDEN);
1346 if (temp != to)
1347 emit_move_insn (to, temp);
1348 return;
1349 }
1350 }
1351#endif
1352 icode = can_fix_p (DImode, GET_MODE (from), unsignedp, &must_trunc);
1353
1354 if (GET_MODE (to) != DImode && icode != CODE_FOR_nothing)
1355 {
1356 register rtx temp = gen_reg_rtx (DImode);
1357
1358 if (must_trunc)
1359 from = ftruncify (from);
1360 emit_unop_insn (icode, temp, from, FIX);
1361 convert_move (to, temp, unsignedp);
1362 return;
1363 }
1364
1365 /* If FROM is not DFmode, convert to DFmode and try again from there. */
1366 if (GET_MODE (from) == DFmode)
1367 break;
1368
1369 from = convert_to_mode (DFmode, from, 0);
1370 }
1371
1372 /* We can't do it with an insn, so use a library call.
1373 The mode of FROM is known to be DFmode. */
1374
1375 to = protect_from_queue (to, 1);
1376 from = protect_from_queue (from, 0);
1377
1378 if (flag_force_mem)
1379 from = force_not_mem (from);
1380
1381 if (GET_MODE (to) != DImode)
1382 {
1383 emit_library_call (gen_rtx (SYMBOL_REF, Pmode,
1384 unsignedp ? "__fixunsdfsi"
1385 : "__fixdfsi"),
1386 0, SImode, 1, from, DFmode);
1387 target = hard_libcall_value (SImode);
1388 }
1389 else
1390 {
1391 emit_library_call (gen_rtx (SYMBOL_REF, Pmode,
1392 unsignedp ? "__fixunsdfdi"
1393 : "__fixdfdi"),
1394 0, DImode, 1, from, DFmode);
1395 target = hard_libcall_value (DImode);
1396 }
1397
1398 if (GET_MODE (to) == GET_MODE (target))
1399 emit_move_insn (to, target);
1400 else
1401 convert_move (to, target, 0);
1402}
1403\f
1404static optab
1405init_optab (code)
1406 enum rtx_code code;
1407{
1408 int i;
1409 optab op = (optab) malloc (sizeof (struct optab));
1410 op->code = code;
1411 for (i = 0; i < NUM_MACHINE_MODES; i++)
1412 {
1413 op->handlers[i].insn_code = CODE_FOR_nothing;
1414 op->handlers[i].lib_call = 0;
1415 }
1416 return op;
1417}
1418
1419/* Call this once to initialize the contents of the optabs
1420 appropriately for the current target machine. */
1421
1422void
1423init_optabs ()
1424{
1425 init_fixtab ();
1426 init_floattab ();
1427 init_comparisons ();
1428/* init_extends (); */
1429
1430 add_optab = init_optab (PLUS);
1431 sub_optab = init_optab (MINUS);
1432 smul_optab = init_optab (MULT);
1433 umul_optab = init_optab (UMULT);
1434 smul_widen_optab = init_optab (MULT);
1435 umul_widen_optab = init_optab (UMULT);
1436 sdiv_optab = init_optab (DIV);
1437 sdivmod_optab = init_optab (UNKNOWN);
1438 udiv_optab = init_optab (UDIV);
1439 udivmod_optab = init_optab (UNKNOWN);
1440 smod_optab = init_optab (MOD);
1441 umod_optab = init_optab (UMOD);
1442 flodiv_optab = init_optab (DIV);
1443 ftrunc_optab = init_optab (UNKNOWN);
1444 and_optab = init_optab (AND);
1445 andcb_optab = init_optab (UNKNOWN);
1446 ior_optab = init_optab (IOR);
1447 xor_optab = init_optab (XOR);
1448 ashl_optab = init_optab (ASHIFT);
1449 ashr_optab = init_optab (ASHIFTRT);
1450 lshl_optab = init_optab (LSHIFT);
1451 lshr_optab = init_optab (LSHIFTRT);
1452 rotl_optab = init_optab (ROTATE);
1453 rotr_optab = init_optab (ROTATERT);
1454 mov_optab = init_optab (UNKNOWN);
1455 movstrict_optab = init_optab (UNKNOWN);
1456 cmp_optab = init_optab (UNKNOWN);
1457 ucmp_optab = init_optab (UNKNOWN);
1458 tst_optab = init_optab (UNKNOWN);
1459 neg_optab = init_optab (NEG);
1460 abs_optab = init_optab (ABS);
1461 one_cmpl_optab = init_optab (NOT);
1462 ffs_optab = init_optab (FFS);
1463
1464#ifdef HAVE_addqi3
1465 if (HAVE_addqi3)
1466 add_optab->handlers[(int) QImode].insn_code = CODE_FOR_addqi3;
1467#endif
1468#ifdef HAVE_addhi3
1469 if (HAVE_addhi3)
1470 add_optab->handlers[(int) HImode].insn_code = CODE_FOR_addhi3;
1471#endif
1472#ifdef HAVE_addsi3
1473 if (HAVE_addsi3)
1474 add_optab->handlers[(int) SImode].insn_code = CODE_FOR_addsi3;
1475#endif
1476#ifdef HAVE_adddi3
1477 if (HAVE_adddi3)
1478 add_optab->handlers[(int) DImode].insn_code = CODE_FOR_adddi3;
1479#endif
1480#ifdef HAVE_addsf3
1481 if (HAVE_addsf3)
1482 add_optab->handlers[(int) SFmode].insn_code = CODE_FOR_addsf3;
1483#endif
1484#ifdef HAVE_adddf3
1485 if (HAVE_adddf3)
1486 add_optab->handlers[(int) DFmode].insn_code = CODE_FOR_adddf3;
1487#endif
1488 add_optab->handlers[(int) DImode].lib_call = "__adddi3";
1489 add_optab->handlers[(int) SFmode].lib_call = "__addsf3";
1490 add_optab->handlers[(int) DFmode].lib_call = "__adddf3";
1491
1492#ifdef HAVE_subqi3
1493 if (HAVE_subqi3)
1494 sub_optab->handlers[(int) QImode].insn_code = CODE_FOR_subqi3;
1495#endif
1496#ifdef HAVE_subhi3
1497 if (HAVE_subhi3)
1498 sub_optab->handlers[(int) HImode].insn_code = CODE_FOR_subhi3;
1499#endif
1500#ifdef HAVE_subsi3
1501 if (HAVE_subsi3)
1502 sub_optab->handlers[(int) SImode].insn_code = CODE_FOR_subsi3;
1503#endif
1504#ifdef HAVE_subdi3
1505 if (HAVE_subdi3)
1506 sub_optab->handlers[(int) DImode].insn_code = CODE_FOR_subdi3;
1507#endif
1508#ifdef HAVE_subsf3
1509 if (HAVE_subsf3)
1510 sub_optab->handlers[(int) SFmode].insn_code = CODE_FOR_subsf3;
1511#endif
1512#ifdef HAVE_subdf3
1513 if (HAVE_subdf3)
1514 sub_optab->handlers[(int) DFmode].insn_code = CODE_FOR_subdf3;
1515#endif
1516 sub_optab->handlers[(int) DImode].lib_call = "__subdi3";
1517 sub_optab->handlers[(int) SFmode].lib_call = "__subsf3";
1518 sub_optab->handlers[(int) DFmode].lib_call = "__subdf3";
1519
1520#ifdef HAVE_mulqi3
1521 if (HAVE_mulqi3)
1522 smul_optab->handlers[(int) QImode].insn_code = CODE_FOR_mulqi3;
1523#endif
1524#ifdef HAVE_mulhi3
1525 if (HAVE_mulhi3)
1526 smul_optab->handlers[(int) HImode].insn_code = CODE_FOR_mulhi3;
1527#endif
1528#ifdef HAVE_mulsi3
1529 if (HAVE_mulsi3)
1530 smul_optab->handlers[(int) SImode].insn_code = CODE_FOR_mulsi3;
1531#endif
1532#ifdef HAVE_muldi3
1533 if (HAVE_muldi3)
1534 smul_optab->handlers[(int) DImode].insn_code = CODE_FOR_muldi3;
1535#endif
1536#ifdef HAVE_mulsf3
1537 if (HAVE_mulsf3)
1538 smul_optab->handlers[(int) SFmode].insn_code = CODE_FOR_mulsf3;
1539#endif
1540#ifdef HAVE_muldf3
1541 if (HAVE_muldf3)
1542 smul_optab->handlers[(int) DFmode].insn_code = CODE_FOR_muldf3;
1543#endif
1544
1545#ifdef MULSI3_LIBCALL
1546 smul_optab->handlers[(int) SImode].lib_call = MULSI3_LIBCALL;
1547#else
1548 smul_optab->handlers[(int) SImode].lib_call = "__mulsi3";
1549#endif
1550 smul_optab->handlers[(int) DImode].lib_call = "__muldi3";
1551 smul_optab->handlers[(int) SFmode].lib_call = "__mulsf3";
1552 smul_optab->handlers[(int) DFmode].lib_call = "__muldf3";
1553
1554#ifdef HAVE_mulqihi3
1555 if (HAVE_mulqihi3)
1556 smul_widen_optab->handlers[(int) HImode].insn_code = CODE_FOR_mulqihi3;
1557#endif
1558#ifdef HAVE_mulhisi3
1559 if (HAVE_mulhisi3)
1560 smul_widen_optab->handlers[(int) SImode].insn_code = CODE_FOR_mulhisi3;
1561#endif
1562#ifdef HAVE_mulsidi3
1563 if (HAVE_mulsidi3)
1564 smul_widen_optab->handlers[(int) DImode].insn_code = CODE_FOR_mulsidi3;
1565#endif
1566
1567#ifdef HAVE_umulqi3
1568 if (HAVE_umulqi3)
1569 umul_optab->handlers[(int) QImode].insn_code = CODE_FOR_umulqi3;
1570#endif
1571#ifdef HAVE_umulhi3
1572 if (HAVE_umulhi3)
1573 umul_optab->handlers[(int) HImode].insn_code = CODE_FOR_umulhi3;
1574#endif
1575#ifdef HAVE_umulsi3
1576 if (HAVE_umulsi3)
1577 umul_optab->handlers[(int) SImode].insn_code = CODE_FOR_umulsi3;
1578#endif
1579#ifdef HAVE_umuldi3
1580 if (HAVE_umuldi3)
1581 umul_optab->handlers[(int) DImode].insn_code = CODE_FOR_umuldi3;
1582#endif
1583#ifdef HAVE_umulsf3
1584 if (HAVE_umulsf3)
1585 umul_optab->handlers[(int) SFmode].insn_code = CODE_FOR_umulsf3;
1586#endif
1587#ifdef HAVE_umuldf3
1588 if (HAVE_umuldf3)
1589 umul_optab->handlers[(int) DFmode].insn_code = CODE_FOR_umuldf3;
1590#endif
1591
1592#ifdef UMULSI3_LIBCALL
1593 umul_optab->handlers[(int) SImode].lib_call = UMULSI3_LIBCALL;
1594#else
1595 umul_optab->handlers[(int) SImode].lib_call = "__umulsi3";
1596#endif
1597 umul_optab->handlers[(int) DImode].lib_call = "__umuldi3";
1598 umul_optab->handlers[(int) SFmode].lib_call = "__umulsf3";
1599 umul_optab->handlers[(int) DFmode].lib_call = "__umuldf3";
1600
1601#ifdef HAVE_umulqihi3
1602 if (HAVE_umulqihi3)
1603 umul_widen_optab->handlers[(int) HImode].insn_code = CODE_FOR_umulqihi3;
1604#endif
1605#ifdef HAVE_umulhisi3
1606 if (HAVE_umulhisi3)
1607 umul_widen_optab->handlers[(int) SImode].insn_code = CODE_FOR_umulhisi3;
1608#endif
1609#ifdef HAVE_umulsidi3
1610 if (HAVE_umulsidi3)
1611 umul_widen_optab->handlers[(int) DImode].insn_code = CODE_FOR_umulsidi3;
1612#endif
1613
1614#ifdef HAVE_divqi3
1615 if (HAVE_divqi3)
1616 sdiv_optab->handlers[(int) QImode].insn_code = CODE_FOR_divqi3;
1617#endif
1618#ifdef HAVE_divhi3
1619 if (HAVE_divhi3)
1620 sdiv_optab->handlers[(int) HImode].insn_code = CODE_FOR_divhi3;
1621#endif
1622#ifdef HAVE_divsi3
1623 if (HAVE_divsi3)
1624 sdiv_optab->handlers[(int) SImode].insn_code = CODE_FOR_divsi3;
1625#endif
1626#ifdef HAVE_divdi3
1627 if (HAVE_divdi3)
1628 sdiv_optab->handlers[(int) DImode].insn_code = CODE_FOR_divdi3;
1629#endif
1630
1631#ifdef DIVSI3_LIBCALL
1632 sdiv_optab->handlers[(int) SImode].lib_call = DIVSI3_LIBCALL;
1633#else
1634 sdiv_optab->handlers[(int) SImode].lib_call = "__divsi3";
1635#endif
1636 sdiv_optab->handlers[(int) DImode].lib_call = "__divdi3";
1637
1638#ifdef HAVE_udivqi3
1639 if (HAVE_udivqi3)
1640 udiv_optab->handlers[(int) QImode].insn_code = CODE_FOR_udivqi3;
1641#endif
1642#ifdef HAVE_udivhi3
1643 if (HAVE_udivhi3)
1644 udiv_optab->handlers[(int) HImode].insn_code = CODE_FOR_udivhi3;
1645#endif
1646#ifdef HAVE_udivsi3
1647 if (HAVE_udivsi3)
1648 udiv_optab->handlers[(int) SImode].insn_code = CODE_FOR_udivsi3;
1649#endif
1650#ifdef HAVE_udivdi3
1651 if (HAVE_udivdi3)
1652 udiv_optab->handlers[(int) DImode].insn_code = CODE_FOR_udivdi3;
1653#endif
1654
1655#ifdef UDIVSI3_LIBCALL
1656 udiv_optab->handlers[(int) SImode].lib_call = UDIVSI3_LIBCALL;
1657#else
1658 udiv_optab->handlers[(int) SImode].lib_call = "__udivsi3";
1659#endif
1660 udiv_optab->handlers[(int) DImode].lib_call = "__udivdi3";
1661
1662#ifdef HAVE_divmodqi4
1663 if (HAVE_divmodqi4)
1664 sdivmod_optab->handlers[(int) QImode].insn_code = CODE_FOR_divmodqi4;
1665#endif
1666#ifdef HAVE_divmodhi4
1667 if (HAVE_divmodhi4)
1668 sdivmod_optab->handlers[(int) HImode].insn_code = CODE_FOR_divmodhi4;
1669#endif
1670#ifdef HAVE_divmodsi4
1671 if (HAVE_divmodsi4)
1672 sdivmod_optab->handlers[(int) SImode].insn_code = CODE_FOR_divmodsi4;
1673#endif
1674#ifdef HAVE_divmoddi4
1675 if (HAVE_divmoddi4)
1676 sdivmod_optab->handlers[(int) DImode].insn_code = CODE_FOR_divmoddi4;
1677#endif
1678
1679#ifdef HAVE_udivmodqi4
1680 if (HAVE_udivmodqi4)
1681 udivmod_optab->handlers[(int) QImode].insn_code = CODE_FOR_udivmodqi4;
1682#endif
1683#ifdef HAVE_udivmodhi4
1684 if (HAVE_udivmodhi4)
1685 udivmod_optab->handlers[(int) HImode].insn_code = CODE_FOR_udivmodhi4;
1686#endif
1687#ifdef HAVE_udivmodsi4
1688 if (HAVE_udivmodsi4)
1689 udivmod_optab->handlers[(int) SImode].insn_code = CODE_FOR_udivmodsi4;
1690#endif
1691#ifdef HAVE_udivmoddi4
1692 if (HAVE_udivmoddi4)
1693 udivmod_optab->handlers[(int) DImode].insn_code = CODE_FOR_udivmoddi4;
1694#endif
1695
1696#ifdef HAVE_modqi3
1697 if (HAVE_modqi3)
1698 smod_optab->handlers[(int) QImode].insn_code = CODE_FOR_modqi3;
1699#endif
1700#ifdef HAVE_modhi3
1701 if (HAVE_modhi3)
1702 smod_optab->handlers[(int) HImode].insn_code = CODE_FOR_modhi3;
1703#endif
1704#ifdef HAVE_modsi3
1705 if (HAVE_modsi3)
1706 smod_optab->handlers[(int) SImode].insn_code = CODE_FOR_modsi3;
1707#endif
1708#ifdef HAVE_moddi3
1709 if (HAVE_moddi3)
1710 smod_optab->handlers[(int) DImode].insn_code = CODE_FOR_moddi3;
1711#endif
1712
1713#ifdef MODSI3_LIBCALL
1714 smod_optab->handlers[(int) SImode].lib_call = MODSI3_LIBCALL;
1715#else
1716 smod_optab->handlers[(int) SImode].lib_call = "__modsi3";
1717#endif
1718 smod_optab->handlers[(int) DImode].lib_call = "__moddi3";
1719
1720#ifdef HAVE_umodqi3
1721 if (HAVE_umodqi3)
1722 umod_optab->handlers[(int) QImode].insn_code = CODE_FOR_umodqi3;
1723#endif
1724#ifdef HAVE_umodhi3
1725 if (HAVE_umodhi3)
1726 umod_optab->handlers[(int) HImode].insn_code = CODE_FOR_umodhi3;
1727#endif
1728#ifdef HAVE_umodsi3
1729 if (HAVE_umodsi3)
1730 umod_optab->handlers[(int) SImode].insn_code = CODE_FOR_umodsi3;
1731#endif
1732#ifdef HAVE_umoddi3
1733 if (HAVE_umoddi3)
1734 umod_optab->handlers[(int) DImode].insn_code = CODE_FOR_umoddi3;
1735#endif
1736
1737#ifdef UMODSI3_LIBCALL
1738 umod_optab->handlers[(int) SImode].lib_call = UMODSI3_LIBCALL;
1739#else
1740 umod_optab->handlers[(int) SImode].lib_call = "__umodsi3";
1741#endif
1742 umod_optab->handlers[(int) DImode].lib_call = "__umoddi3";
1743
1744#ifdef HAVE_divsf3
1745 if (HAVE_divsf3)
1746 flodiv_optab->handlers[(int) SFmode].insn_code = CODE_FOR_divsf3;
1747#endif
1748#ifdef HAVE_divdf3
1749 if (HAVE_divdf3)
1750 flodiv_optab->handlers[(int) DFmode].insn_code = CODE_FOR_divdf3;
1751#endif
1752 flodiv_optab->handlers[(int) SFmode].lib_call = "__divsf3";
1753 flodiv_optab->handlers[(int) DFmode].lib_call = "__divdf3";
1754
1755#ifdef HAVE_ftruncsf2
1756 if (HAVE_ftruncsf2)
1757 ftrunc_optab->handlers[(int) SFmode].insn_code = CODE_FOR_ftruncsf2;
1758#endif
1759#ifdef HAVE_ftruncdf2
1760 if (HAVE_ftruncdf2)
1761 ftrunc_optab->handlers[(int) DFmode].insn_code = CODE_FOR_ftruncdf2;
1762#endif
1763
1764#ifdef HAVE_andqi3
1765 if (HAVE_andqi3)
1766 and_optab->handlers[(int) QImode].insn_code = CODE_FOR_andqi3;
1767#endif
1768#ifdef HAVE_andhi3
1769 if (HAVE_andhi3)
1770 and_optab->handlers[(int) HImode].insn_code = CODE_FOR_andhi3;
1771#endif
1772#ifdef HAVE_andsi3
1773 if (HAVE_andsi3)
1774 and_optab->handlers[(int) SImode].insn_code = CODE_FOR_andsi3;
1775#endif
1776#ifdef HAVE_anddi3
1777 if (HAVE_anddi3)
1778 and_optab->handlers[(int) DImode].insn_code = CODE_FOR_anddi3;
1779#endif
1780 and_optab->handlers[(int) DImode].lib_call = "__anddi3";
1781
1782#ifdef HAVE_andcbqi3
1783 if (HAVE_andcbqi3)
1784 andcb_optab->handlers[(int) QImode].insn_code = CODE_FOR_andcbqi3;
1785#endif
1786#ifdef HAVE_andcbhi3
1787 if (HAVE_andcbhi3)
1788 andcb_optab->handlers[(int) HImode].insn_code = CODE_FOR_andcbhi3;
1789#endif
1790#ifdef HAVE_andcbsi3
1791 if (HAVE_andcbsi3)
1792 andcb_optab->handlers[(int) SImode].insn_code = CODE_FOR_andcbsi3;
1793#endif
1794#ifdef HAVE_andcbdi3
1795 if (HAVE_andcbdi3)
1796 andcb_optab->handlers[(int) DImode].insn_code = CODE_FOR_andcbdi3;
1797#endif
1798 andcb_optab->handlers[(int) DImode].lib_call = "__andcbdi3";
1799
1800#ifdef HAVE_iorqi3
1801 if (HAVE_iorqi3)
1802 ior_optab->handlers[(int) QImode].insn_code = CODE_FOR_iorqi3;
1803#endif
1804#ifdef HAVE_iorhi3
1805 if (HAVE_iorhi3)
1806 ior_optab->handlers[(int) HImode].insn_code = CODE_FOR_iorhi3;
1807#endif
1808#ifdef HAVE_iorsi3
1809 if (HAVE_iorsi3)
1810 ior_optab->handlers[(int) SImode].insn_code = CODE_FOR_iorsi3;
1811#endif
1812#ifdef HAVE_iordi3
1813 if (HAVE_iordi3)
1814 ior_optab->handlers[(int) DImode].insn_code = CODE_FOR_iordi3;
1815#endif
1816 ior_optab->handlers[(int) DImode].lib_call = "__iordi3";
1817
1818#ifdef HAVE_xorqi3
1819 if (HAVE_xorqi3)
1820 xor_optab->handlers[(int) QImode].insn_code = CODE_FOR_xorqi3;
1821#endif
1822#ifdef HAVE_xorhi3
1823 if (HAVE_xorhi3)
1824 xor_optab->handlers[(int) HImode].insn_code = CODE_FOR_xorhi3;
1825#endif
1826#ifdef HAVE_xorsi3
1827 if (HAVE_xorsi3)
1828 xor_optab->handlers[(int) SImode].insn_code = CODE_FOR_xorsi3;
1829#endif
1830#ifdef HAVE_xordi3
1831 if (HAVE_xordi3)
1832 xor_optab->handlers[(int) DImode].insn_code = CODE_FOR_xordi3;
1833#endif
1834 xor_optab->handlers[(int) DImode].lib_call = "__xordi3";
1835
1836#ifdef HAVE_ashlqi3
1837 if (HAVE_ashlqi3)
1838 ashl_optab->handlers[(int) QImode].insn_code = CODE_FOR_ashlqi3;
1839#endif
1840#ifdef HAVE_ashlhi3
1841 if (HAVE_ashlhi3)
1842 ashl_optab->handlers[(int) HImode].insn_code = CODE_FOR_ashlhi3;
1843#endif
1844#ifdef HAVE_ashlsi3
1845 if (HAVE_ashlsi3)
1846 ashl_optab->handlers[(int) SImode].insn_code = CODE_FOR_ashlsi3;
1847#endif
1848#ifdef HAVE_ashldi3
1849 if (HAVE_ashldi3)
1850 ashl_optab->handlers[(int) DImode].insn_code = CODE_FOR_ashldi3;
1851#endif
1852 ashl_optab->handlers[(int) SImode].lib_call = "__ashlsi3";
1853 ashl_optab->handlers[(int) DImode].lib_call = "__ashldi3";
1854
1855#ifdef HAVE_ashrqi3
1856 if (HAVE_ashrqi3)
1857 ashr_optab->handlers[(int) QImode].insn_code = CODE_FOR_ashrqi3;
1858#endif
1859#ifdef HAVE_ashrhi3
1860 if (HAVE_ashrhi3)
1861 ashr_optab->handlers[(int) HImode].insn_code = CODE_FOR_ashrhi3;
1862#endif
1863#ifdef HAVE_ashrsi3
1864 if (HAVE_ashrsi3)
1865 ashr_optab->handlers[(int) SImode].insn_code = CODE_FOR_ashrsi3;
1866#endif
1867#ifdef HAVE_ashrdi3
1868 if (HAVE_ashrdi3)
1869 ashr_optab->handlers[(int) DImode].insn_code = CODE_FOR_ashrdi3;
1870#endif
1871 ashr_optab->handlers[(int) SImode].lib_call = "__ashrsi3";
1872 ashr_optab->handlers[(int) DImode].lib_call = "__ashrdi3";
1873
1874#ifdef HAVE_lshlqi3
1875 if (HAVE_lshlqi3)
1876 lshl_optab->handlers[(int) QImode].insn_code = CODE_FOR_lshlqi3;
1877#endif
1878#ifdef HAVE_lshlhi3
1879 if (HAVE_lshlhi3)
1880 lshl_optab->handlers[(int) HImode].insn_code = CODE_FOR_lshlhi3;
1881#endif
1882#ifdef HAVE_lshlsi3
1883 if (HAVE_lshlsi3)
1884 lshl_optab->handlers[(int) SImode].insn_code = CODE_FOR_lshlsi3;
1885#endif
1886#ifdef HAVE_lshldi3
1887 if (HAVE_lshldi3)
1888 lshl_optab->handlers[(int) DImode].insn_code = CODE_FOR_lshldi3;
1889#endif
1890 lshl_optab->handlers[(int) SImode].lib_call = "__lshlsi3";
1891 lshl_optab->handlers[(int) DImode].lib_call = "__lshldi3";
1892
1893#ifdef HAVE_lshrqi3
1894 if (HAVE_lshrqi3)
1895 lshr_optab->handlers[(int) QImode].insn_code = CODE_FOR_lshrqi3;
1896#endif
1897#ifdef HAVE_lshrhi3
1898 if (HAVE_lshrhi3)
1899 lshr_optab->handlers[(int) HImode].insn_code = CODE_FOR_lshrhi3;
1900#endif
1901#ifdef HAVE_lshrsi3
1902 if (HAVE_lshrsi3)
1903 lshr_optab->handlers[(int) SImode].insn_code = CODE_FOR_lshrsi3;
1904#endif
1905#ifdef HAVE_lshrdi3
1906 if (HAVE_lshrdi3)
1907 lshr_optab->handlers[(int) DImode].insn_code = CODE_FOR_lshrdi3;
1908#endif
1909 lshr_optab->handlers[(int) SImode].lib_call = "__lshrsi3";
1910 lshr_optab->handlers[(int) DImode].lib_call = "__lshrdi3";
1911
1912#ifdef HAVE_rotlqi3
1913 if (HAVE_rotlqi3)
1914 rotl_optab->handlers[(int) QImode].insn_code = CODE_FOR_rotlqi3;
1915#endif
1916#ifdef HAVE_rotlhi3
1917 if (HAVE_rotlhi3)
1918 rotl_optab->handlers[(int) HImode].insn_code = CODE_FOR_rotlhi3;
1919#endif
1920#ifdef HAVE_rotlsi3
1921 if (HAVE_rotlsi3)
1922 rotl_optab->handlers[(int) SImode].insn_code = CODE_FOR_rotlsi3;
1923#endif
1924#ifdef HAVE_rotldi3
1925 if (HAVE_rotldi3)
1926 rotl_optab->handlers[(int) DImode].insn_code = CODE_FOR_rotldi3;
1927#endif
1928 rotl_optab->handlers[(int) SImode].lib_call = "__rotlsi3";
1929 rotl_optab->handlers[(int) DImode].lib_call = "__rotldi3";
1930
1931#ifdef HAVE_rotrqi3
1932 if (HAVE_rotrqi3)
1933 rotr_optab->handlers[(int) QImode].insn_code = CODE_FOR_rotrqi3;
1934#endif
1935#ifdef HAVE_rotrhi3
1936 if (HAVE_rotrhi3)
1937 rotr_optab->handlers[(int) HImode].insn_code = CODE_FOR_rotrhi3;
1938#endif
1939#ifdef HAVE_rotrsi3
1940 if (HAVE_rotrsi3)
1941 rotr_optab->handlers[(int) SImode].insn_code = CODE_FOR_rotrsi3;
1942#endif
1943#ifdef HAVE_rotrdi3
1944 if (HAVE_rotrdi3)
1945 rotr_optab->handlers[(int) DImode].insn_code = CODE_FOR_rotrdi3;
1946#endif
1947 rotr_optab->handlers[(int) SImode].lib_call = "__rotrsi3";
1948 rotr_optab->handlers[(int) DImode].lib_call = "__rotrdi3";
1949
1950#ifdef HAVE_negqi2
1951 if (HAVE_negqi2)
1952 neg_optab->handlers[(int) QImode].insn_code = CODE_FOR_negqi2;
1953#endif
1954#ifdef HAVE_neghi2
1955 if (HAVE_neghi2)
1956 neg_optab->handlers[(int) HImode].insn_code = CODE_FOR_neghi2;
1957#endif
1958#ifdef HAVE_negsi2
1959 if (HAVE_negsi2)
1960 neg_optab->handlers[(int) SImode].insn_code = CODE_FOR_negsi2;
1961#endif
1962#ifdef HAVE_negdi2
1963 if (HAVE_negdi2)
1964 neg_optab->handlers[(int) DImode].insn_code = CODE_FOR_negdi2;
1965#endif
1966#ifdef HAVE_negsf2
1967 if (HAVE_negsf2)
1968 neg_optab->handlers[(int) SFmode].insn_code = CODE_FOR_negsf2;
1969#endif
1970#ifdef HAVE_negdf2
1971 if (HAVE_negdf2)
1972 neg_optab->handlers[(int) DFmode].insn_code = CODE_FOR_negdf2;
1973#endif
1974 neg_optab->handlers[(int) SImode].lib_call = "__negsi2";
1975 neg_optab->handlers[(int) DImode].lib_call = "__negdi2";
1976 neg_optab->handlers[(int) SFmode].lib_call = "__negsf2";
1977 neg_optab->handlers[(int) DFmode].lib_call = "__negdf2";
1978
1979#ifdef HAVE_absqi2
1980 if (HAVE_absqi2)
1981 abs_optab->handlers[(int) QImode].insn_code = CODE_FOR_absqi2;
1982#endif
1983#ifdef HAVE_abshi2
1984 if (HAVE_abshi2)
1985 abs_optab->handlers[(int) HImode].insn_code = CODE_FOR_abshi2;
1986#endif
1987#ifdef HAVE_abssi2
1988 if (HAVE_abssi2)
1989 abs_optab->handlers[(int) SImode].insn_code = CODE_FOR_abssi2;
1990#endif
1991#ifdef HAVE_absdi2
1992 if (HAVE_absdi2)
1993 abs_optab->handlers[(int) DImode].insn_code = CODE_FOR_absdi2;
1994#endif
1995#ifdef HAVE_abssf2
1996 if (HAVE_abssf2)
1997 abs_optab->handlers[(int) SFmode].insn_code = CODE_FOR_abssf2;
1998#endif
1999#ifdef HAVE_absdf2
2000 if (HAVE_absdf2)
2001 abs_optab->handlers[(int) DFmode].insn_code = CODE_FOR_absdf2;
2002#endif
2003 /* No library calls here! If there is no abs instruction,
2004 expand_expr will generate a conditional negation. */
2005
2006#ifdef HAVE_one_cmplqi2
2007 if (HAVE_one_cmplqi2)
2008 one_cmpl_optab->handlers[(int) QImode].insn_code = CODE_FOR_one_cmplqi2;
2009#endif
2010#ifdef HAVE_one_cmplhi2
2011 if (HAVE_one_cmplhi2)
2012 one_cmpl_optab->handlers[(int) HImode].insn_code = CODE_FOR_one_cmplhi2;
2013#endif
2014#ifdef HAVE_one_cmplsi2
2015 if (HAVE_one_cmplsi2)
2016 one_cmpl_optab->handlers[(int) SImode].insn_code = CODE_FOR_one_cmplsi2;
2017#endif
2018#ifdef HAVE_one_cmpldi2
2019 if (HAVE_one_cmpldi2)
2020 one_cmpl_optab->handlers[(int) DImode].insn_code = CODE_FOR_one_cmpldi2;
2021#endif
2022 one_cmpl_optab->handlers[(int) SImode].lib_call = "__one_cmplsi2";
2023 one_cmpl_optab->handlers[(int) DImode].lib_call = "__one_cmpldi2";
2024
2025#ifdef HAVE_ffsqi2
2026 if (HAVE_ffsqi2)
2027 ffs_optab->handlers[(int) QImode].insn_code = CODE_FOR_ffsqi2;
2028#endif
2029#ifdef HAVE_ffshi2
2030 if (HAVE_ffshi2)
2031 ffs_optab->handlers[(int) HImode].insn_code = CODE_FOR_ffshi2;
2032#endif
2033#ifdef HAVE_ffssi2
2034 if (HAVE_ffssi2)
2035 ffs_optab->handlers[(int) SImode].insn_code = CODE_FOR_ffssi2;
2036#endif
2037#ifdef HAVE_ffsdi2
2038 if (HAVE_ffsdi2)
2039 ffs_optab->handlers[(int) DImode].insn_code = CODE_FOR_ffsdi2;
2040#endif
2041 ffs_optab->handlers[(int) SImode].lib_call = "ffs";
2042
2043#ifdef HAVE_movqi
2044 if (HAVE_movqi)
2045 mov_optab->handlers[(int) QImode].insn_code = CODE_FOR_movqi;
2046#endif
2047#ifdef HAVE_movhi
2048 if (HAVE_movhi)
2049 mov_optab->handlers[(int) HImode].insn_code = CODE_FOR_movhi;
2050#endif
2051#ifdef HAVE_movsi
2052 if (HAVE_movsi)
2053 mov_optab->handlers[(int) SImode].insn_code = CODE_FOR_movsi;
2054#endif
2055#ifdef HAVE_movdi
2056 if (HAVE_movdi)
2057 mov_optab->handlers[(int) DImode].insn_code = CODE_FOR_movdi;
2058#endif
2059#ifdef HAVE_movti
2060 if (HAVE_movti)
2061 mov_optab->handlers[(int) TImode].insn_code = CODE_FOR_movti;
2062#endif
2063#ifdef HAVE_movsf
2064 if (HAVE_movsf)
2065 mov_optab->handlers[(int) SFmode].insn_code = CODE_FOR_movsf;
2066#endif
2067#ifdef HAVE_movdf
2068 if (HAVE_movdf)
2069 mov_optab->handlers[(int) DFmode].insn_code = CODE_FOR_movdf;
2070#endif
2071#ifdef HAVE_movtf
2072 if (HAVE_movtf)
2073 mov_optab->handlers[(int) TFmode].insn_code = CODE_FOR_movtf;
2074#endif
2075
2076#ifdef HAVE_movstrictqi
2077 if (HAVE_movstrictqi)
2078 movstrict_optab->handlers[(int) QImode].insn_code = CODE_FOR_movstrictqi;
2079#endif
2080#ifdef HAVE_movstricthi
2081 if (HAVE_movstricthi)
2082 movstrict_optab->handlers[(int) HImode].insn_code = CODE_FOR_movstricthi;
2083#endif
2084#ifdef HAVE_movstrictsi
2085 if (HAVE_movstrictsi)
2086 movstrict_optab->handlers[(int) SImode].insn_code = CODE_FOR_movstrictsi;
2087#endif
2088#ifdef HAVE_movstrictdi
2089 if (HAVE_movstrictdi)
2090 movstrict_optab->handlers[(int) DImode].insn_code = CODE_FOR_movstrictdi;
2091#endif
2092
2093#ifdef HAVE_cmpqi
2094 if (HAVE_cmpqi)
2095 cmp_optab->handlers[(int) QImode].insn_code = CODE_FOR_cmpqi;
2096#endif
2097#ifdef HAVE_cmphi
2098 if (HAVE_cmphi)
2099 cmp_optab->handlers[(int) HImode].insn_code = CODE_FOR_cmphi;
2100#endif
2101#ifdef HAVE_cmpsi
2102 if (HAVE_cmpsi)
2103 cmp_optab->handlers[(int) SImode].insn_code = CODE_FOR_cmpsi;
2104#endif
2105#ifdef HAVE_cmpdi
2106 if (HAVE_cmpdi)
2107 cmp_optab->handlers[(int) DImode].insn_code = CODE_FOR_cmpdi;
2108#endif
2109#ifdef HAVE_cmpsf
2110 if (HAVE_cmpsf)
2111 cmp_optab->handlers[(int) SFmode].insn_code = CODE_FOR_cmpsf;
2112#endif
2113#ifdef HAVE_cmpdf
2114 if (HAVE_cmpdf)
2115 cmp_optab->handlers[(int) DFmode].insn_code = CODE_FOR_cmpdf;
2116#endif
2117#ifdef HAVE_tstqi
2118 if (HAVE_tstqi)
2119 tst_optab->handlers[(int) QImode].insn_code = CODE_FOR_tstqi;
2120#endif
2121#ifdef HAVE_tsthi
2122 if (HAVE_tsthi)
2123 tst_optab->handlers[(int) HImode].insn_code = CODE_FOR_tsthi;
2124#endif
2125#ifdef HAVE_tstsi
2126 if (HAVE_tstsi)
2127 tst_optab->handlers[(int) SImode].insn_code = CODE_FOR_tstsi;
2128#endif
2129#ifdef HAVE_tstdi
2130 if (HAVE_tstdi)
2131 tst_optab->handlers[(int) DImode].insn_code = CODE_FOR_tstdi;
2132#endif
2133#ifdef HAVE_tstsf
2134 if (HAVE_tstsf)
2135 tst_optab->handlers[(int) SFmode].insn_code = CODE_FOR_tstsf;
2136#endif
2137#ifdef HAVE_tstdf
2138 if (HAVE_tstdf)
2139 tst_optab->handlers[(int) DFmode].insn_code = CODE_FOR_tstdf;
2140#endif
2141 /* Comparison libcalls for integers MUST come in pairs, signed/unsigned. */
2142 cmp_optab->handlers[(int) DImode].lib_call = "__cmpdi2";
2143 ucmp_optab->handlers[(int) DImode].lib_call = "__ucmpdi2";
2144 cmp_optab->handlers[(int) SFmode].lib_call = "__cmpsf2";
2145 cmp_optab->handlers[(int) DFmode].lib_call = "__cmpdf2";
2146
2147#if HAVE_beq
2148 if (HAVE_beq)
2149 bcc_gen_fctn[(int) EQ] = gen_beq;
2150#endif
2151#if HAVE_bne
2152 if (HAVE_bne)
2153 bcc_gen_fctn[(int) NE] = gen_bne;
2154#endif
2155#if HAVE_bgt
2156 if (HAVE_bgt)
2157 bcc_gen_fctn[(int) GT] = gen_bgt;
2158#endif
2159#if HAVE_bge
2160 if (HAVE_bge)
2161 bcc_gen_fctn[(int) GE] = gen_bge;
2162#endif
2163#if HAVE_bgtu
2164 if (HAVE_bgtu)
2165 bcc_gen_fctn[(int) GTU] = gen_bgtu;
2166#endif
2167#if HAVE_bgeu
2168 if (HAVE_bgeu)
2169 bcc_gen_fctn[(int) GEU] = gen_bgeu;
2170#endif
2171#if HAVE_blt
2172 if (HAVE_blt)
2173 bcc_gen_fctn[(int) LT] = gen_blt;
2174#endif
2175#if HAVE_ble
2176 if (HAVE_ble)
2177 bcc_gen_fctn[(int) LE] = gen_ble;
2178#endif
2179#if HAVE_bltu
2180 if (HAVE_bltu)
2181 bcc_gen_fctn[(int) LTU] = gen_bltu;
2182#endif
2183#if HAVE_bleu
2184 if (HAVE_bleu)
2185 bcc_gen_fctn[(int) LEU] = gen_bleu;
2186#endif
2187
2188#if HAVE_seq
2189 if (HAVE_seq)
2190 setcc_gen_fctn[(int) EQ] = gen_seq;
2191#endif
2192#if HAVE_sne
2193 if (HAVE_sne)
2194 setcc_gen_fctn[(int) NE] = gen_sne;
2195#endif
2196#if HAVE_sgt
2197 if (HAVE_sgt)
2198 setcc_gen_fctn[(int) GT] = gen_sgt;
2199#endif
2200#if HAVE_sge
2201 if (HAVE_sge)
2202 setcc_gen_fctn[(int) GE] = gen_sge;
2203#endif
2204#if HAVE_sgtu
2205 if (HAVE_sgtu)
2206 setcc_gen_fctn[(int) GTU] = gen_sgtu;
2207#endif
2208#if HAVE_sgeu
2209 if (HAVE_sgeu)
2210 setcc_gen_fctn[(int) GEU] = gen_sgeu;
2211#endif
2212#if HAVE_slt
2213 if (HAVE_slt)
2214 setcc_gen_fctn[(int) LT] = gen_slt;
2215#endif
2216#if HAVE_sle
2217 if (HAVE_sle)
2218 setcc_gen_fctn[(int) LE] = gen_sle;
2219#endif
2220#if HAVE_sltu
2221 if (HAVE_sltu)
2222 setcc_gen_fctn[(int) LTU] = gen_sltu;
2223#endif
2224#if HAVE_sleu
2225 if (HAVE_sleu)
2226 setcc_gen_fctn[(int) LEU] = gen_sleu;
2227#endif
2228}