|
|
1.1 root 1: /* Expand the basic unary and binary arithmetic operations, for GNU compiler.
2: Copyright (C) 1987, 1988, 1992 Free Software Foundation, Inc.
3:
4: This file is part of GNU CC.
5:
6: GNU CC is free software; you can redistribute it and/or modify
7: it under the terms of the GNU General Public License as published by
8: the Free Software Foundation; either version 2, or (at your option)
9: any later version.
10:
11: GNU CC is distributed in the hope that it will be useful,
12: but WITHOUT ANY WARRANTY; without even the implied warranty of
13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14: GNU General Public License for more details.
15:
16: You should have received a copy of the GNU General Public License
17: along with GNU CC; see the file COPYING. If not, write to
18: the Free Software Foundation, 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: /* Each optab contains info on how this target machine
32: can perform a particular operation
33: for all sizes and kinds of operands.
34:
35: The operation to be performed is often specified
36: by passing one of these optabs as an argument.
37:
38: See expr.h for documentation of these optabs. */
39:
40: optab add_optab;
41: optab sub_optab;
42: optab smul_optab;
43: optab smul_widen_optab;
44: optab umul_widen_optab;
45: optab sdiv_optab;
46: optab sdivmod_optab;
47: optab udiv_optab;
48: optab udivmod_optab;
49: optab smod_optab;
50: optab umod_optab;
51: optab flodiv_optab;
52: optab ftrunc_optab;
53: optab and_optab;
54: optab ior_optab;
55: optab xor_optab;
56: optab ashl_optab;
57: optab lshr_optab;
58: optab lshl_optab;
59: optab ashr_optab;
60: optab rotl_optab;
61: optab rotr_optab;
62: optab smin_optab;
63: optab smax_optab;
64: optab umin_optab;
65: optab umax_optab;
66:
67: optab mov_optab;
68: optab movstrict_optab;
69:
70: optab neg_optab;
71: optab abs_optab;
72: optab one_cmpl_optab;
73: optab ffs_optab;
1.1.1.2 root 74: optab sqrt_optab;
1.1 root 75:
76: optab cmp_optab;
77: optab ucmp_optab; /* Used only for libcalls for unsigned comparisons. */
78: optab tst_optab;
79:
1.1.1.3 ! root 80: optab strlen_optab;
! 81:
1.1 root 82: /* SYMBOL_REF rtx's for the library functions that are called
83: implicitly and not via optabs. */
84:
85: rtx extendsfdf2_libfunc;
86: rtx truncdfsf2_libfunc;
87: rtx memcpy_libfunc;
88: rtx bcopy_libfunc;
89: rtx memcmp_libfunc;
90: rtx bcmp_libfunc;
91: rtx memset_libfunc;
92: rtx bzero_libfunc;
93: rtx eqsf2_libfunc;
94: rtx nesf2_libfunc;
95: rtx gtsf2_libfunc;
96: rtx gesf2_libfunc;
97: rtx ltsf2_libfunc;
98: rtx lesf2_libfunc;
99: rtx eqdf2_libfunc;
100: rtx nedf2_libfunc;
101: rtx gtdf2_libfunc;
102: rtx gedf2_libfunc;
103: rtx ltdf2_libfunc;
104: rtx ledf2_libfunc;
105: rtx floatdisf_libfunc;
106: rtx floatsisf_libfunc;
107: rtx floatdidf_libfunc;
108: rtx floatsidf_libfunc;
109: rtx fixsfsi_libfunc;
110: rtx fixsfdi_libfunc;
111: rtx fixdfsi_libfunc;
112: rtx fixdfdi_libfunc;
113: rtx fixunssfsi_libfunc;
114: rtx fixunssfdi_libfunc;
115: rtx fixunsdfsi_libfunc;
116: rtx fixunsdfdi_libfunc;
117:
118: /* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
119: gives the gen_function to make a branch to test that condition. */
120:
121: rtxfun bcc_gen_fctn[NUM_RTX_CODE];
122:
123: /* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
124: gives the insn code to make a store-condition insn
125: to test that condition. */
126:
127: enum insn_code setcc_gen_code[NUM_RTX_CODE];
128:
129: static void emit_float_lib_cmp ();
130:
131: /* Add a REG_EQUAL note to the last insn in SEQ. TARGET is being set to
132: the result of operation CODE applied to OP0 (and OP1 if it is a binary
133: operation).
134:
135: If the last insn does not set TARGET, don't do anything, but return 1.
136:
137: If a previous insn sets TARGET and TARGET is one of OP0 or OP1,
138: don't add the REG_EQUAL note but return 0. Our caller can then try
139: again, ensuring that TARGET is not one of the operands. */
140:
141: static int
142: add_equal_note (seq, target, code, op0, op1)
143: rtx seq;
144: rtx target;
145: enum rtx_code code;
146: rtx op0, op1;
147: {
148: rtx set;
149: int i;
150: rtx note;
151:
152: if ((GET_RTX_CLASS (code) != '1' && GET_RTX_CLASS (code) != '2'
153: && GET_RTX_CLASS (code) != 'c' && GET_RTX_CLASS (code) != '<')
154: || GET_CODE (seq) != SEQUENCE
155: || (set = single_set (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1))) == 0
156: || GET_CODE (target) == ZERO_EXTRACT
157: || (! rtx_equal_p (SET_DEST (set), target)
158: /* For a STRICT_LOW_PART, the REG_NOTE applies to what is inside the
159: SUBREG. */
160: && (GET_CODE (SET_DEST (set)) != STRICT_LOW_PART
161: || ! rtx_equal_p (SUBREG_REG (XEXP (SET_DEST (set), 0)),
162: target))))
163: return 1;
164:
165: /* If TARGET is in OP0 or OP1, check if anything in SEQ sets TARGET
166: besides the last insn. */
167: if (reg_overlap_mentioned_p (target, op0)
168: || (op1 && reg_overlap_mentioned_p (target, op1)))
169: for (i = XVECLEN (seq, 0) - 2; i >= 0; i--)
170: if (reg_set_p (target, XVECEXP (seq, 0, i)))
171: return 0;
172:
173: if (GET_RTX_CLASS (code) == '1')
174: note = gen_rtx (code, GET_MODE (target), op0);
175: else
176: note = gen_rtx (code, GET_MODE (target), op0, op1);
177:
178: REG_NOTES (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1))
179: = gen_rtx (EXPR_LIST, REG_EQUAL, note,
180: REG_NOTES (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1)));
181:
182: return 1;
183: }
184:
185: /* Generate code to perform an operation specified by BINOPTAB
186: on operands OP0 and OP1, with result having machine-mode MODE.
187:
188: UNSIGNEDP is for the case where we have to widen the operands
189: to perform the operation. It says to use zero-extension.
190:
191: If TARGET is nonzero, the value
192: is generated there, if it is convenient to do so.
193: In all cases an rtx is returned for the locus of the value;
194: this may or may not be TARGET. */
195:
196: rtx
197: expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
198: enum machine_mode mode;
199: optab binoptab;
200: rtx op0, op1;
201: rtx target;
202: int unsignedp;
203: enum optab_methods methods;
204: {
205: enum mode_class class;
206: enum machine_mode wider_mode;
207: register rtx temp;
208: int commutative_op = 0;
209: int shift_op = (binoptab->code == ASHIFT
210: || binoptab->code == ASHIFTRT
211: || binoptab->code == LSHIFT
212: || binoptab->code == LSHIFTRT
213: || binoptab->code == ROTATE
214: || binoptab->code == ROTATERT);
215: rtx last;
216:
217: class = GET_MODE_CLASS (mode);
218:
219: op0 = protect_from_queue (op0, 0);
220: op1 = protect_from_queue (op1, 0);
221: if (target)
222: target = protect_from_queue (target, 1);
223:
224: if (flag_force_mem)
225: {
226: op0 = force_not_mem (op0);
227: op1 = force_not_mem (op1);
228: }
229:
230: /* If we are inside an appropriately-short loop and one operand is an
231: expensive constant, force it into a register. */
1.1.1.3 ! root 232: if (CONSTANT_P (op0) && preserve_subexpressions_p ()
! 233: && rtx_cost (op0, binoptab->code) > 2)
1.1 root 234: op0 = force_reg (mode, op0);
235:
1.1.1.3 ! root 236: if (CONSTANT_P (op1) && preserve_subexpressions_p ()
! 237: && rtx_cost (op1, binoptab->code) > 2)
1.1 root 238: op1 = force_reg (shift_op ? word_mode : mode, op1);
239:
240: #if 0 /* Turned off because it seems to be a kludgy method. */
241: /* If subtracting integer from pointer, and the pointer has a special mode,
242: then change it to an add. We use the add insn of Pmode for combining
243: integers with pointers, and the sub insn to subtract two pointers. */
244:
245: if (binoptab == sub_optab
246: && GET_MODE (op0) == Pmode && GET_MODE (op1) != Pmode)
247: {
248: op1 = negate_rtx (GET_MODE(op1), op1);
249: binoptab = add_optab;
250: }
251: #endif /* 0 */
252:
253: /* Record where to delete back to if we backtrack. */
254: last = get_last_insn ();
255:
256: /* If operation is commutative,
257: try to make the first operand a register.
258: Even better, try to make it the same as the target.
259: Also try to make the last operand a constant. */
260: if (GET_RTX_CLASS (binoptab->code) == 'c'
261: || binoptab == smul_widen_optab
262: || binoptab == umul_widen_optab)
263: {
264: commutative_op = 1;
265:
266: if (((target == 0 || GET_CODE (target) == REG)
267: ? ((GET_CODE (op1) == REG
268: && GET_CODE (op0) != REG)
269: || target == op1)
270: : rtx_equal_p (op1, target))
271: || GET_CODE (op0) == CONST_INT)
272: {
273: temp = op1;
274: op1 = op0;
275: op0 = temp;
276: }
277: }
278:
279: /* If we can do it with a three-operand insn, do so. */
280:
281: if (methods != OPTAB_MUST_WIDEN
282: && binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
283: {
284: int icode = (int) binoptab->handlers[(int) mode].insn_code;
285: enum machine_mode mode0 = insn_operand_mode[icode][1];
286: enum machine_mode mode1 = insn_operand_mode[icode][2];
287: rtx pat;
288: rtx xop0 = op0, xop1 = op1;
289:
290: if (target)
291: temp = target;
292: else
293: temp = gen_reg_rtx (mode);
294:
295: /* If it is a commutative operator and the modes would match
296: if we would swap the operands, we can save the conversions. */
297: if (commutative_op)
298: {
299: if (GET_MODE (op0) != mode0 && GET_MODE (op1) != mode1
300: && GET_MODE (op0) == mode1 && GET_MODE (op1) == mode0)
301: {
302: register rtx tmp;
303:
304: tmp = op0; op0 = op1; op1 = tmp;
305: tmp = xop0; xop0 = xop1; xop1 = tmp;
306: }
307: }
308:
309: /* In case the insn wants input operands in modes different from
310: the result, convert the operands. */
311:
312: if (GET_MODE (op0) != VOIDmode
313: && GET_MODE (op0) != mode0)
314: xop0 = convert_to_mode (mode0, xop0, unsignedp);
315:
316: if (GET_MODE (xop1) != VOIDmode
317: && GET_MODE (xop1) != mode1)
318: xop1 = convert_to_mode (mode1, xop1, unsignedp);
319:
320: /* Now, if insn's predicates don't allow our operands, put them into
321: pseudo regs. */
322:
323: if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))
324: xop0 = copy_to_mode_reg (mode0, xop0);
325:
326: if (! (*insn_operand_predicate[icode][2]) (xop1, mode1))
327: xop1 = copy_to_mode_reg (mode1, xop1);
328:
329: if (! (*insn_operand_predicate[icode][0]) (temp, mode))
330: temp = gen_reg_rtx (mode);
331:
332: pat = GEN_FCN (icode) (temp, xop0, xop1);
333: if (pat)
334: {
335: /* If PAT is a multi-insn sequence, try to add an appropriate
336: REG_EQUAL note to it. If we can't because TEMP conflicts with an
337: operand, call ourselves again, this time without a target. */
338: if (GET_CODE (pat) == SEQUENCE
339: && ! add_equal_note (pat, temp, binoptab->code, xop0, xop1))
340: {
341: delete_insns_since (last);
342: return expand_binop (mode, binoptab, op0, op1, 0, unsignedp,
343: methods);
344: }
345:
346: emit_insn (pat);
347: return temp;
348: }
349: else
350: delete_insns_since (last);
351: }
352:
353: /* These can be done a word at a time. */
354: if ((binoptab == and_optab || binoptab == ior_optab || binoptab == xor_optab)
355: && class == MODE_INT
356: && GET_MODE_SIZE (mode) > UNITS_PER_WORD
357: && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
358: {
359: int i;
360: rtx insns;
361: rtx equiv_value;
362:
363: /* If TARGET is the same as one of the operands, the REG_EQUAL note
364: won't be accurate, so use a new target. */
365: if (target == 0 || target == op0 || target == op1)
366: target = gen_reg_rtx (mode);
367:
368: start_sequence ();
369:
370: /* Do the actual arithmetic. */
371: for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)
372: {
373: rtx target_piece = operand_subword (target, i, 1, mode);
374: rtx x = expand_binop (word_mode, binoptab,
375: operand_subword_force (op0, i, mode),
376: operand_subword_force (op1, i, mode),
377: target_piece, unsignedp, methods);
378: if (target_piece != x)
379: emit_move_insn (target_piece, x);
380: }
381:
382: insns = get_insns ();
383: end_sequence ();
384:
385: if (binoptab->code != UNKNOWN)
386: equiv_value = gen_rtx (binoptab->code, mode, op0, op1);
387: else
388: equiv_value = 0;
389:
390: emit_no_conflict_block (insns, target, op0, op1, equiv_value);
391: return target;
392: }
393:
394: /* These can be done a word at a time by propagating carries. */
395: if ((binoptab == add_optab || binoptab == sub_optab)
396: && class == MODE_INT
397: && GET_MODE_SIZE (mode) >= 2 * UNITS_PER_WORD
398: && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
399: {
400: int i;
401: rtx carry_tmp = gen_reg_rtx (word_mode);
402: optab otheroptab = binoptab == add_optab ? sub_optab : add_optab;
403: int nwords = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
404: rtx carry_in, carry_out;
405:
406: /* We can handle either a 1 or -1 value for the carry. If STORE_FLAG
407: value is one of those, use it. Otherwise, use 1 since it is the
408: one easiest to get. */
409: #if STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1
410: int normalizep = STORE_FLAG_VALUE;
411: #else
412: int normalizep = 1;
413: #endif
414:
415: /* Prepare the operands. */
416: op0 = force_reg (mode, op0);
417: op1 = force_reg (mode, op1);
418:
419: if (target == 0 || GET_CODE (target) != REG
420: || target == op0 || target == op1)
421: target = gen_reg_rtx (mode);
422:
423: /* Do the actual arithmetic. */
424: for (i = 0; i < nwords; i++)
425: {
426: int index = (WORDS_BIG_ENDIAN ? nwords - i - 1 : i);
427: rtx target_piece = operand_subword (target, index, 1, mode);
428: rtx op0_piece = operand_subword_force (op0, index, mode);
429: rtx op1_piece = operand_subword_force (op1, index, mode);
430: rtx x;
431:
432: /* Main add/subtract of the input operands. */
433: x = expand_binop (word_mode, binoptab,
434: op0_piece, op1_piece,
435: target_piece, unsignedp, methods);
436: if (x == 0)
437: break;
438:
439: if (i + 1 < nwords)
440: {
441: /* Store carry from main add/subtract. */
442: carry_out = gen_reg_rtx (word_mode);
443: carry_out = emit_store_flag (carry_out,
444: binoptab == add_optab ? LTU : GTU,
445: x, op0_piece,
446: word_mode, 1, normalizep);
447: if (!carry_out)
448: break;
449: }
450:
451: if (i > 0)
452: {
453: /* Add/subtract previous carry to main result. */
454: x = expand_binop (word_mode,
455: normalizep == 1 ? binoptab : otheroptab,
456: x, carry_in,
457: target_piece, 1, methods);
458: if (target_piece != x)
459: emit_move_insn (target_piece, x);
460:
461: if (i + 1 < nwords)
462: {
463: /* THIS CODE HAS NOT BEEN TESTED. */
464: /* Get out carry from adding/subtracting carry in. */
465: carry_tmp = emit_store_flag (carry_tmp,
466: binoptab == add_optab
467: ? LTU : GTU,
468: x, carry_in,
469: word_mode, 1, normalizep);
470: /* Logical-ior the two poss. carry together. */
471: carry_out = expand_binop (word_mode, ior_optab,
472: carry_out, carry_tmp,
473: carry_out, 0, methods);
474: if (!carry_out)
475: break;
476: }
477: }
478:
479: carry_in = carry_out;
480: }
481:
482: if (i == GET_MODE_BITSIZE (mode) / BITS_PER_WORD)
483: {
484: rtx temp;
485:
486: temp = emit_move_insn (target, target);
487: REG_NOTES (temp) = gen_rtx (EXPR_LIST, REG_EQUAL,
488: gen_rtx (binoptab->code, mode, op0, op1),
489: REG_NOTES (temp));
490: return target;
491: }
492: else
493: delete_insns_since (last);
494: }
495:
496: /* If we want to multiply two two-word values and have normal and widening
497: multiplies of single-word values, we can do this with three smaller
498: multiplications. Note that we do not make a REG_NO_CONFLICT block here
499: because we are not operating on one word at a time.
500:
501: The multiplication proceeds as follows:
502: _______________________
503: [__op0_high_|__op0_low__]
504: _______________________
505: * [__op1_high_|__op1_low__]
506: _______________________________________________
507: _______________________
508: (1) [__op0_low__*__op1_low__]
509: _______________________
510: (2a) [__op0_low__*__op1_high_]
511: _______________________
512: (2b) [__op0_high_*__op1_low__]
513: _______________________
514: (3) [__op0_high_*__op1_high_]
515:
516:
517: This gives a 4-word result. Since we are only interested in the
518: lower 2 words, partial result (3) and the upper words of (2a) and
519: (2b) don't need to be calculated. Hence (2a) and (2b) can be
520: calculated using non-widening multiplication.
521:
522: (1), however, needs to be calculated with an unsigned widening
523: multiplication. If this operation is not directly supported we
524: try using a signed widening multiplication and adjust the result.
525: This adjustment works as follows:
526:
527: If both operands are positive then no adjustment is needed.
528:
529: If the operands have different signs, for example op0_low < 0 and
530: op1_low >= 0, the instruction treats the most significant bit of
531: op0_low as a sign bit instead of a bit with significance
532: 2**(BITS_PER_WORD-1), i.e. the instruction multiplies op1_low
533: with 2**BITS_PER_WORD - op0_low, and two's complements the
534: result. Conclusion: We need to add op1_low * 2**BITS_PER_WORD to
535: the result.
536:
537: Similarly, if both operands are negative, we need to add
538: (op0_low + op1_low) * 2**BITS_PER_WORD.
539:
540: We use a trick to adjust quickly. We logically shift op0_low right
541: (op1_low) BITS_PER_WORD-1 steps to get 0 or 1, and add this to
542: op0_high (op1_high) before it is used to calculate 2b (2a). If no
543: logical shift exists, we do an arithmetic right shift and subtract
544: the 0 or -1. */
545:
546: if (binoptab == smul_optab
547: && class == MODE_INT
548: && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
549: && smul_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
550: && add_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
551: && ((umul_widen_optab->handlers[(int) mode].insn_code
552: != CODE_FOR_nothing)
553: || (smul_widen_optab->handlers[(int) mode].insn_code
554: != CODE_FOR_nothing)))
555: {
556: int low = (WORDS_BIG_ENDIAN ? 1 : 0);
557: int high = (WORDS_BIG_ENDIAN ? 0 : 1);
558: rtx op0_high = operand_subword_force (op0, high, mode);
559: rtx op0_low = operand_subword_force (op0, low, mode);
560: rtx op1_high = operand_subword_force (op1, high, mode);
561: rtx op1_low = operand_subword_force (op1, low, mode);
562: rtx product = 0;
563: rtx op0_xhigh;
564: rtx op1_xhigh;
565:
566: /* If the target is the same as one of the inputs, don't use it. This
567: prevents problems with the REG_EQUAL note. */
568: if (target == op0 || target == op1)
569: target = 0;
570:
571: /* Multiply the two lower words to get a double-word product.
572: If unsigned widening multiplication is available, use that;
573: otherwise use the signed form and compensate. */
574:
575: if (umul_widen_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
576: {
577: product = expand_binop (mode, umul_widen_optab, op0_low, op1_low,
578: target, 1, OPTAB_DIRECT);
579:
580: /* If we didn't succeed, delete everything we did so far. */
581: if (product == 0)
582: delete_insns_since (last);
583: else
584: op0_xhigh = op0_high, op1_xhigh = op1_high;
585: }
586:
587: if (product == 0
588: && smul_widen_optab->handlers[(int) mode].insn_code
589: != CODE_FOR_nothing)
590: {
591: rtx wordm1 = gen_rtx (CONST_INT, VOIDmode, BITS_PER_WORD - 1);
592: product = expand_binop (mode, smul_widen_optab, op0_low, op1_low,
593: target, 1, OPTAB_DIRECT);
594: op0_xhigh = expand_binop (word_mode, lshr_optab, op0_low, wordm1,
595: 0, 1, OPTAB_DIRECT);
596: if (op0_xhigh)
597: op0_xhigh = expand_binop (word_mode, add_optab, op0_high,
598: op0_xhigh, op0_xhigh, 0, OPTAB_DIRECT);
599: else
600: {
601: op0_xhigh = expand_binop (word_mode, ashr_optab, op0_low, wordm1,
602: 0, 0, OPTAB_DIRECT);
603: if (op0_xhigh)
604: op0_xhigh = expand_binop (word_mode, sub_optab, op0_high,
605: op0_xhigh, op0_xhigh, 0,
606: OPTAB_DIRECT);
607: }
608:
609: op1_xhigh = expand_binop (word_mode, lshr_optab, op1_low, wordm1,
610: 0, 1, OPTAB_DIRECT);
611: if (op1_xhigh)
612: op1_xhigh = expand_binop (word_mode, add_optab, op1_high,
613: op1_xhigh, op1_xhigh, 0, OPTAB_DIRECT);
614: else
615: {
616: op1_xhigh = expand_binop (word_mode, ashr_optab, op1_low, wordm1,
617: 0, 0, OPTAB_DIRECT);
618: if (op1_xhigh)
619: op1_xhigh = expand_binop (word_mode, sub_optab, op1_high,
620: op1_xhigh, op1_xhigh, 0,
621: OPTAB_DIRECT);
622: }
623: }
624:
625: /* If we have been able to directly compute the product of the
626: low-order words of the operands and perform any required adjustments
627: of the operands, we proceed by trying two more multiplications
628: and then computing the appropriate sum.
629:
630: We have checked above that the required addition is provided.
631: Full-word addition will normally always succeed, especially if
632: it is provided at all, so we don't worry about its failure. The
633: multiplication may well fail, however, so we do handle that. */
634:
635: if (product && op0_xhigh && op1_xhigh)
636: {
637: rtx product_piece;
638: rtx product_high = operand_subword (product, high, 1, mode);
639: rtx temp = expand_binop (word_mode, binoptab, op0_low, op1_xhigh, 0,
640: 0, OPTAB_DIRECT);
641:
642: if (temp)
643: {
644: product_piece = expand_binop (word_mode, add_optab, temp,
645: product_high, product_high,
646: 0, OPTAB_LIB_WIDEN);
647: if (product_piece != product_high)
648: emit_move_insn (product_high, product_piece);
649:
650: temp = expand_binop (word_mode, binoptab, op1_low, op0_xhigh, 0,
651: 0, OPTAB_DIRECT);
652:
653: product_piece = expand_binop (word_mode, add_optab, temp,
654: product_high, product_high,
655: 0, OPTAB_LIB_WIDEN);
656: if (product_piece != product_high)
657: emit_move_insn (product_high, product_piece);
658:
659: temp = emit_move_insn (product, product);
660: REG_NOTES (temp) = gen_rtx (EXPR_LIST, REG_EQUAL,
661: gen_rtx (MULT, mode, op0, op1),
662: REG_NOTES (temp));
663:
664: return product;
665: }
666: }
667:
668: /* If we get here, we couldn't do it for some reason even though we
669: originally thought we could. Delete anything we've emitted in
670: trying to do it. */
671:
672: delete_insns_since (last);
673: }
674:
675: /* It can't be open-coded in this mode.
676: Use a library call if one is available and caller says that's ok. */
677:
678: if (binoptab->handlers[(int) mode].libfunc
679: && (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN))
680: {
681: rtx insns;
682: rtx funexp = binoptab->handlers[(int) mode].libfunc;
683:
684: start_sequence ();
685:
686: /* Pass 1 for NO_QUEUE so we don't lose any increments
687: if the libcall is cse'd or moved. */
688: emit_library_call (binoptab->handlers[(int) mode].libfunc,
689: 1, mode, 2, op0, mode, op1,
690: (shift_op ? word_mode : mode));
691:
692: insns = get_insns ();
693: end_sequence ();
694:
695: target = gen_reg_rtx (mode);
696: emit_libcall_block (insns, target, hard_libcall_value (mode),
697: gen_rtx (binoptab->code, mode, op0, op1));
698:
699: return target;
700: }
701:
702: delete_insns_since (last);
703:
704: /* It can't be done in this mode. Can we do it in a wider mode? */
705:
706: if (! (methods == OPTAB_WIDEN || methods == OPTAB_LIB_WIDEN
707: || methods == OPTAB_MUST_WIDEN))
708: return 0; /* Caller says, don't even try. */
709:
710: /* Compute the value of METHODS to pass to recursive calls.
711: Don't allow widening to be tried recursively. */
712:
713: methods = (methods == OPTAB_LIB_WIDEN ? OPTAB_LIB : OPTAB_DIRECT);
714:
715: /* Look for a wider mode of the same class for which it appears we can do
716: the operation. */
717:
718: if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
719: {
720: for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
721: wider_mode = GET_MODE_WIDER_MODE (wider_mode))
722: {
723: if ((binoptab->handlers[(int) wider_mode].insn_code
724: != CODE_FOR_nothing)
725: || (methods == OPTAB_LIB
726: && binoptab->handlers[(int) wider_mode].libfunc))
727: {
728: rtx xop0 = op0, xop1 = op1;
729: int no_extend = 0;
730:
731: /* For certain integer operations, we need not actually extend
732: the narrow operands, as long as we will truncate
733: the results to the same narrowness. */
734:
735: if ((binoptab == ior_optab || binoptab == and_optab
736: || binoptab == xor_optab
737: || binoptab == add_optab || binoptab == sub_optab
738: || binoptab == smul_optab
739: || binoptab == ashl_optab || binoptab == lshl_optab)
740: && class == MODE_INT)
741: no_extend = 1;
742:
743: /* If an operand is a constant integer, we might as well
744: convert it since that is more efficient than using a SUBREG,
745: unlike the case for other operands. */
746:
747: if (no_extend && GET_MODE (xop0) != VOIDmode)
748: xop0 = gen_rtx (SUBREG, wider_mode,
749: force_reg (GET_MODE (xop0), xop0), 0);
750: else
751: xop0 = convert_to_mode (wider_mode, xop0, unsignedp);
752:
753: if (no_extend && GET_MODE (xop1) != VOIDmode)
754: xop1 = gen_rtx (SUBREG, wider_mode,
755: force_reg (GET_MODE (xop1), xop1), 0);
756: else
757: xop1 = convert_to_mode (wider_mode, xop1, unsignedp);
758:
759: temp = expand_binop (wider_mode, binoptab, xop0, xop1, 0,
760: unsignedp, methods);
761: if (temp)
762: {
763: if (class != MODE_INT)
764: {
765: if (target == 0)
766: target = gen_reg_rtx (mode);
767: convert_move (target, temp, 0);
768: return target;
769: }
770: else
771: return gen_lowpart (mode, temp);
772: }
773: else
774: delete_insns_since (last);
775: }
776: }
777: }
778:
779: return 0;
780: }
781:
782: /* Expand a binary operator which has both signed and unsigned forms.
783: UOPTAB is the optab for unsigned operations, and SOPTAB is for
784: signed operations.
785:
786: If we widen unsigned operands, we may use a signed wider operation instead
787: of an unsigned wider operation, since the result would be the same. */
788:
789: rtx
790: sign_expand_binop (mode, uoptab, soptab, op0, op1, target, unsignedp, methods)
791: enum machine_mode mode;
792: optab uoptab, soptab;
793: rtx op0, op1, target;
794: int unsignedp;
795: enum optab_methods methods;
796: {
797: register rtx temp;
798: optab direct_optab = unsignedp ? uoptab : soptab;
799: struct optab wide_soptab;
800:
801: /* Do it without widening, if possible. */
802: temp = expand_binop (mode, direct_optab, op0, op1, target,
803: unsignedp, OPTAB_DIRECT);
804: if (temp || methods == OPTAB_DIRECT)
805: return temp;
806:
807: /* Try widening to a signed int. Make a fake signed optab that
808: hides any signed insn for direct use. */
809: wide_soptab = *soptab;
810: wide_soptab.handlers[(int) mode].insn_code = CODE_FOR_nothing;
811: wide_soptab.handlers[(int) mode].libfunc = 0;
812:
813: temp = expand_binop (mode, &wide_soptab, op0, op1, target,
814: unsignedp, OPTAB_WIDEN);
815:
816: /* For unsigned operands, try widening to an unsigned int. */
817: if (temp == 0 && unsignedp)
818: temp = expand_binop (mode, uoptab, op0, op1, target,
819: unsignedp, OPTAB_WIDEN);
820: if (temp || methods == OPTAB_WIDEN)
821: return temp;
822:
823: /* Use the right width lib call if that exists. */
824: temp = expand_binop (mode, direct_optab, op0, op1, target, unsignedp, OPTAB_LIB);
825: if (temp || methods == OPTAB_LIB)
826: return temp;
827:
828: /* Must widen and use a lib call, use either signed or unsigned. */
829: temp = expand_binop (mode, &wide_soptab, op0, op1, target,
830: unsignedp, methods);
831: if (temp != 0)
832: return temp;
833: if (unsignedp)
834: return expand_binop (mode, uoptab, op0, op1, target,
835: unsignedp, methods);
836: return 0;
837: }
838:
839: /* Generate code to perform an operation specified by BINOPTAB
840: on operands OP0 and OP1, with two results to TARG1 and TARG2.
841: We assume that the order of the operands for the instruction
842: is TARG0, OP0, OP1, TARG1, which would fit a pattern like
843: [(set TARG0 (operate OP0 OP1)) (set TARG1 (operate ...))].
844:
845: Either TARG0 or TARG1 may be zero, but what that means is that
846: that result is not actually wanted. We will generate it into
847: a dummy pseudo-reg and discard it. They may not both be zero.
848:
849: Returns 1 if this operation can be performed; 0 if not. */
850:
851: int
852: expand_twoval_binop (binoptab, op0, op1, targ0, targ1, unsignedp)
853: optab binoptab;
854: rtx op0, op1;
855: rtx targ0, targ1;
856: int unsignedp;
857: {
858: enum machine_mode mode = GET_MODE (targ0 ? targ0 : targ1);
859: enum mode_class class;
860: enum machine_mode wider_mode;
861: rtx last;
862:
863: class = GET_MODE_CLASS (mode);
864:
865: op0 = protect_from_queue (op0, 0);
866: op1 = protect_from_queue (op1, 0);
867:
868: if (flag_force_mem)
869: {
870: op0 = force_not_mem (op0);
871: op1 = force_not_mem (op1);
872: }
873:
874: /* If we are inside an appropriately-short loop and one operand is an
875: expensive constant, force it into a register. */
1.1.1.3 ! root 876: if (CONSTANT_P (op0) && preserve_subexpressions_p ()
! 877: && rtx_cost (op0, binoptab->code) > 2)
1.1 root 878: op0 = force_reg (mode, op0);
879:
1.1.1.3 ! root 880: if (CONSTANT_P (op1) && preserve_subexpressions_p ()
! 881: && rtx_cost (op1, binoptab->code) > 2)
1.1 root 882: op1 = force_reg (mode, op1);
883:
884: if (targ0)
885: targ0 = protect_from_queue (targ0, 1);
886: else
887: targ0 = gen_reg_rtx (mode);
888: if (targ1)
889: targ1 = protect_from_queue (targ1, 1);
890: else
891: targ1 = gen_reg_rtx (mode);
892:
893: /* Record where to go back to if we fail. */
894: last = get_last_insn ();
895:
896: if (binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
897: {
898: int icode = (int) binoptab->handlers[(int) mode].insn_code;
899: enum machine_mode mode0 = insn_operand_mode[icode][1];
900: enum machine_mode mode1 = insn_operand_mode[icode][2];
901: rtx pat;
902: rtx xop0 = op0, xop1 = op1;
903:
904: /* In case this insn wants input operands in modes different from the
905: result, convert the operands. */
906: if (GET_MODE (op0) != VOIDmode && GET_MODE (op0) != mode0)
907: xop0 = convert_to_mode (mode0, xop0, unsignedp);
908:
909: if (GET_MODE (op1) != VOIDmode && GET_MODE (op1) != mode1)
910: xop1 = convert_to_mode (mode1, xop1, unsignedp);
911:
912: /* Now, if insn doesn't accept these operands, put them into pseudos. */
913: if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))
914: xop0 = copy_to_mode_reg (mode0, xop0);
915:
916: if (! (*insn_operand_predicate[icode][2]) (xop1, mode1))
917: xop1 = copy_to_mode_reg (mode1, xop1);
918:
919: /* We could handle this, but we should always be called with a pseudo
920: for our targets and all insns should take them as outputs. */
921: if (! (*insn_operand_predicate[icode][0]) (targ0, mode)
922: || ! (*insn_operand_predicate[icode][3]) (targ1, mode))
923: abort ();
924:
925: pat = GEN_FCN (icode) (targ0, xop0, xop1, targ1);
926: if (pat)
927: {
928: emit_insn (pat);
929: return 1;
930: }
931: else
932: delete_insns_since (last);
933: }
934:
935: /* It can't be done in this mode. Can we do it in a wider mode? */
936:
937: if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
938: {
939: for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
940: wider_mode = GET_MODE_WIDER_MODE (wider_mode))
941: {
942: if (binoptab->handlers[(int) wider_mode].insn_code
943: != CODE_FOR_nothing)
944: {
945: register rtx t0 = gen_reg_rtx (wider_mode);
946: register rtx t1 = gen_reg_rtx (wider_mode);
947:
948: if (expand_twoval_binop (binoptab,
949: convert_to_mode (wider_mode, op0,
950: unsignedp),
951: convert_to_mode (wider_mode, op1,
952: unsignedp),
953: t0, t1, unsignedp))
954: {
955: convert_move (targ0, t0, unsignedp);
956: convert_move (targ1, t1, unsignedp);
957: return 1;
958: }
959: else
960: delete_insns_since (last);
961: }
962: }
963: }
964:
965: return 0;
966: }
967:
968: /* Generate code to perform an operation specified by UNOPTAB
969: on operand OP0, with result having machine-mode MODE.
970:
971: UNSIGNEDP is for the case where we have to widen the operands
972: to perform the operation. It says to use zero-extension.
973:
974: If TARGET is nonzero, the value
975: is generated there, if it is convenient to do so.
976: In all cases an rtx is returned for the locus of the value;
977: this may or may not be TARGET. */
978:
979: rtx
980: expand_unop (mode, unoptab, op0, target, unsignedp)
981: enum machine_mode mode;
982: optab unoptab;
983: rtx op0;
984: rtx target;
985: int unsignedp;
986: {
987: enum mode_class class;
988: enum machine_mode wider_mode;
989: register rtx temp;
990: rtx last = get_last_insn ();
991: rtx pat;
992:
993: class = GET_MODE_CLASS (mode);
994:
995: op0 = protect_from_queue (op0, 0);
996:
997: if (flag_force_mem)
998: {
999: op0 = force_not_mem (op0);
1000: }
1001:
1002: if (target)
1003: target = protect_from_queue (target, 1);
1004:
1005: if (unoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1006: {
1007: int icode = (int) unoptab->handlers[(int) mode].insn_code;
1008: enum machine_mode mode0 = insn_operand_mode[icode][1];
1009: rtx xop0 = op0;
1010:
1011: if (target)
1012: temp = target;
1013: else
1014: temp = gen_reg_rtx (mode);
1015:
1016: if (GET_MODE (xop0) != VOIDmode
1017: && GET_MODE (xop0) != mode0)
1018: xop0 = convert_to_mode (mode0, xop0, unsignedp);
1019:
1020: /* Now, if insn doesn't accept our operand, put it into a pseudo. */
1021:
1022: if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))
1023: xop0 = copy_to_mode_reg (mode0, xop0);
1024:
1025: if (! (*insn_operand_predicate[icode][0]) (temp, mode))
1026: temp = gen_reg_rtx (mode);
1027:
1028: pat = GEN_FCN (icode) (temp, xop0);
1029: if (pat)
1030: {
1031: if (GET_CODE (pat) == SEQUENCE
1032: && ! add_equal_note (pat, temp, unoptab->code, xop0, 0))
1033: {
1034: delete_insns_since (last);
1035: return expand_unop (mode, unoptab, op0, 0, unsignedp);
1036: }
1037:
1038: emit_insn (pat);
1039:
1040: return temp;
1041: }
1042: else
1043: delete_insns_since (last);
1044: }
1045:
1046: /* These can be done a word at a time. */
1047: if (unoptab == one_cmpl_optab
1048: && class == MODE_INT
1049: && GET_MODE_SIZE (mode) > UNITS_PER_WORD
1050: && unoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
1051: {
1052: int i;
1053: rtx insns;
1054:
1055: if (target == 0 || target == op0)
1056: target = gen_reg_rtx (mode);
1057:
1058: start_sequence ();
1059:
1060: /* Do the actual arithmetic. */
1061: for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)
1062: {
1063: rtx target_piece = operand_subword (target, i, 1, mode);
1064: rtx x = expand_unop (word_mode, unoptab,
1065: operand_subword_force (op0, i, mode),
1066: target_piece, unsignedp);
1067: if (target_piece != x)
1068: emit_move_insn (target_piece, x);
1069: }
1070:
1071: insns = get_insns ();
1072: end_sequence ();
1073:
1074: emit_no_conflict_block (insns, target, op0, 0,
1075: gen_rtx (unoptab->code, mode, op0));
1076: return target;
1077: }
1078:
1079: if (unoptab->handlers[(int) mode].libfunc)
1080: {
1081: rtx insns;
1082: rtx funexp = unoptab->handlers[(int) mode].libfunc;
1083:
1084: start_sequence ();
1085:
1086: /* Pass 1 for NO_QUEUE so we don't lose any increments
1087: if the libcall is cse'd or moved. */
1088: emit_library_call (unoptab->handlers[(int) mode].libfunc,
1089: 1, mode, 1, op0, mode);
1090: insns = get_insns ();
1091: end_sequence ();
1092:
1093: target = gen_reg_rtx (mode);
1094: emit_libcall_block (insns, target, hard_libcall_value (mode),
1095: gen_rtx (unoptab->code, mode, op0));
1096:
1097: return target;
1098: }
1099:
1100: /* It can't be done in this mode. Can we do it in a wider mode? */
1101:
1102: if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
1103: {
1104: for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
1105: wider_mode = GET_MODE_WIDER_MODE (wider_mode))
1106: {
1107: if ((unoptab->handlers[(int) wider_mode].insn_code
1108: != CODE_FOR_nothing)
1109: || unoptab->handlers[(int) wider_mode].libfunc)
1110: {
1111: rtx xop0 = op0;
1112:
1113: /* For certain operations, we need not actually extend
1114: the narrow operand, as long as we will truncate the
1115: results to the same narrowness. */
1116:
1117: if ((unoptab == neg_optab || unoptab == one_cmpl_optab)
1118: && class == MODE_INT)
1119: xop0 = gen_rtx (SUBREG, wider_mode, force_reg (mode, xop0), 0);
1120: else
1121: xop0 = convert_to_mode (wider_mode, xop0, unsignedp);
1122:
1123: temp = expand_unop (wider_mode, unoptab, xop0, 0, unsignedp);
1124:
1125: if (temp)
1126: {
1127: if (class != MODE_INT)
1128: {
1129: if (target == 0)
1130: target = gen_reg_rtx (mode);
1131: convert_move (target, temp, 0);
1132: return target;
1133: }
1134: else
1135: return gen_lowpart (mode, temp);
1136: }
1137: else
1138: delete_insns_since (last);
1139: }
1140: }
1141: }
1142:
1143: return 0;
1144: }
1145:
1146: /* Generate an instruction whose insn-code is INSN_CODE,
1147: with two operands: an output TARGET and an input OP0.
1148: TARGET *must* be nonzero, and the output is always stored there.
1149: CODE is an rtx code such that (CODE OP0) is an rtx that describes
1150: the value that is stored into TARGET. */
1151:
1152: void
1153: emit_unop_insn (icode, target, op0, code)
1154: int icode;
1155: rtx target;
1156: rtx op0;
1157: enum rtx_code code;
1158: {
1159: register rtx temp;
1160: enum machine_mode mode0 = insn_operand_mode[icode][1];
1161: rtx pat;
1162:
1163: temp = target = protect_from_queue (target, 1);
1164:
1165: op0 = protect_from_queue (op0, 0);
1166:
1167: if (flag_force_mem)
1168: op0 = force_not_mem (op0);
1169:
1170: /* Now, if insn does not accept our operands, put them into pseudos. */
1171:
1172: if (! (*insn_operand_predicate[icode][1]) (op0, mode0))
1173: op0 = copy_to_mode_reg (mode0, op0);
1174:
1175: if (! (*insn_operand_predicate[icode][0]) (temp, GET_MODE (temp))
1176: || (flag_force_mem && GET_CODE (temp) == MEM))
1177: temp = gen_reg_rtx (GET_MODE (temp));
1178:
1179: pat = GEN_FCN (icode) (temp, op0);
1180:
1181: if (GET_CODE (pat) == SEQUENCE && code != UNKNOWN)
1182: add_equal_note (pat, temp, code, op0, 0);
1183:
1184: emit_insn (pat);
1185:
1186: if (temp != target)
1187: emit_move_insn (target, temp);
1188: }
1189:
1190: /* Emit code to perform a series of operations on a multi-word quantity, one
1191: word at a time.
1192:
1.1.1.2 root 1193: Such a block is preceded by a CLOBBER of the output, consists of multiple
1.1 root 1194: insns, each setting one word of the output, and followed by a SET copying
1195: the output to itself.
1196:
1197: Each of the insns setting words of the output receives a REG_NO_CONFLICT
1198: note indicating that it doesn't conflict with the (also multi-word)
1199: inputs. The entire block is surrounded by REG_LIBCALL and REG_RETVAL
1200: notes.
1201:
1202: INSNS is a block of code generated to perform the operation, not including
1203: the CLOBBER and final copy. All insns that compute intermediate values
1204: are first emitted, followed by the block as described above. Only
1205: INSNs are allowed in the block; no library calls or jumps may be
1206: present.
1207:
1208: TARGET, OP0, and OP1 are the output and inputs of the operations,
1209: respectively. OP1 may be zero for a unary operation.
1210:
1211: EQUIV, if non-zero, is an expression to be placed into a REG_EQUAL note
1212: on the last insn.
1213:
1214: If TARGET is not a register, INSNS is simply emitted with no special
1215: processing.
1216:
1217: The final insn emitted is returned. */
1218:
1219: rtx
1220: emit_no_conflict_block (insns, target, op0, op1, equiv)
1221: rtx insns;
1222: rtx target;
1223: rtx op0, op1;
1224: rtx equiv;
1225: {
1226: rtx prev, next, first, last, insn;
1227:
1228: if (GET_CODE (target) != REG || reload_in_progress)
1229: return emit_insns (insns);
1230:
1231: /* First emit all insns that do not store into words of the output and remove
1232: these from the list. */
1233: for (insn = insns; insn; insn = next)
1234: {
1235: rtx set = 0;
1236: int i;
1237:
1238: next = NEXT_INSN (insn);
1239:
1240: if (GET_CODE (insn) != INSN)
1241: abort ();
1242:
1243: if (GET_CODE (PATTERN (insn)) == SET)
1244: set = PATTERN (insn);
1245: else if (GET_CODE (PATTERN (insn)) == PARALLEL)
1246: {
1247: for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
1248: if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET)
1249: {
1250: set = XVECEXP (PATTERN (insn), 0, i);
1251: break;
1252: }
1253: }
1254:
1255: if (set == 0)
1256: abort ();
1257:
1258: if (! reg_overlap_mentioned_p (target, SET_DEST (set)))
1259: {
1260: if (PREV_INSN (insn))
1261: NEXT_INSN (PREV_INSN (insn)) = next;
1262: else
1263: insns = next;
1264:
1265: if (next)
1266: PREV_INSN (next) = PREV_INSN (insn);
1267:
1268: add_insn (insn);
1269: }
1270: }
1271:
1272: prev = get_last_insn ();
1273:
1274: /* Now write the CLOBBER of the output, followed by the setting of each
1275: of the words, followed by the final copy. */
1276: if (target != op0 && target != op1)
1277: emit_insn (gen_rtx (CLOBBER, VOIDmode, target));
1278:
1279: for (insn = insns; insn; insn = next)
1280: {
1281: next = NEXT_INSN (insn);
1282: add_insn (insn);
1283:
1284: if (op1 && GET_CODE (op1) == REG)
1285: REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_NO_CONFLICT, op1,
1286: REG_NOTES (insn));
1287:
1288: if (op0 && GET_CODE (op0) == REG)
1289: REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_NO_CONFLICT, op0,
1290: REG_NOTES (insn));
1291: }
1292:
1293: last = emit_move_insn (target, target);
1294: if (equiv)
1295: REG_NOTES (last) = gen_rtx (EXPR_LIST, REG_EQUAL, equiv, REG_NOTES (last));
1296:
1297: if (prev == 0)
1298: first = get_insns ();
1299: else
1300: first = NEXT_INSN (prev);
1301:
1302: /* Encapsulate the block so it gets manipulated as a unit. */
1303: REG_NOTES (first) = gen_rtx (INSN_LIST, REG_LIBCALL, last,
1304: REG_NOTES (first));
1305: REG_NOTES (last) = gen_rtx (INSN_LIST, REG_RETVAL, first, REG_NOTES (last));
1306:
1307: return last;
1308: }
1309:
1310: /* Emit code to make a call to a constant function or a library call.
1311:
1312: INSNS is a list containing all insns emitted in the call.
1313: These insns leave the result in RESULT. Our block is to copy RESULT
1314: to TARGET, which is logically equivalent to EQUIV.
1315:
1316: We first emit any insns that set a pseudo on the assumption that these are
1317: loading constants into registers; doing so allows them to be safely cse'ed
1318: between blocks. Then we emit all the other insns in the block, followed by
1319: an insn to move RESULT to TARGET. This last insn will have a REQ_EQUAL
1320: note with an operand of EQUIV.
1321:
1.1.1.3 ! root 1322: Moving assignments to pseudos outside of the block is done to improve
! 1323: the generated code, but is not required to generate correct code,
! 1324: hence being unable to move an assignment is not grounds for not making
! 1325: a libcall block. There are two reasons why it is safe to leave these
! 1326: insns inside the block: First, we know that these pseudos cannot be
! 1327: used in generated RTL outside the block since they are created for
! 1328: temporary purposes within the block. Second, CSE will not record the
! 1329: values of anything set inside a libcall block, so we know they must
! 1330: be dead at the end of the block.
! 1331:
1.1 root 1332: Except for the first group of insns (the ones setting pseudos), the
1333: block is delimited by REG_RETVAL and REG_LIBCALL notes. */
1334:
1335: void
1336: emit_libcall_block (insns, target, result, equiv)
1337: rtx insns;
1338: rtx target;
1339: rtx result;
1340: rtx equiv;
1341: {
1342: rtx prev, next, first, last, insn;
1343:
1344: /* First emit all insns that set pseudos. Remove them from the list as
1.1.1.3 ! root 1345: we go. Avoid insns that set pseudo which were referenced in previous
! 1346: insns. These can be generated by move_by_pieces, for example,
! 1347: to update an address. */
1.1 root 1348:
1349: for (insn = insns; insn; insn = next)
1350: {
1351: rtx set = single_set (insn);
1352:
1353: next = NEXT_INSN (insn);
1354:
1355: if (set != 0 && GET_CODE (SET_DEST (set)) == REG
1.1.1.3 ! root 1356: && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER
! 1357: && (insn == insns
! 1358: || (! reg_mentioned_p (SET_DEST (set), PATTERN (insns))
! 1359: && ! reg_used_between_p (SET_DEST (set), insns, insn))))
1.1 root 1360: {
1361: if (PREV_INSN (insn))
1362: NEXT_INSN (PREV_INSN (insn)) = next;
1363: else
1364: insns = next;
1365:
1366: if (next)
1367: PREV_INSN (next) = PREV_INSN (insn);
1368:
1369: add_insn (insn);
1370: }
1371: }
1372:
1373: prev = get_last_insn ();
1374:
1375: /* Write the remaining insns followed by the final copy. */
1376:
1377: for (insn = insns; insn; insn = next)
1378: {
1379: next = NEXT_INSN (insn);
1380:
1381: add_insn (insn);
1382: }
1383:
1384: last = emit_move_insn (target, result);
1385: REG_NOTES (last) = gen_rtx (EXPR_LIST, REG_EQUAL, equiv, REG_NOTES (last));
1386:
1387: if (prev == 0)
1388: first = get_insns ();
1389: else
1390: first = NEXT_INSN (prev);
1391:
1392: /* Encapsulate the block so it gets manipulated as a unit. */
1393: REG_NOTES (first) = gen_rtx (INSN_LIST, REG_LIBCALL, last,
1394: REG_NOTES (first));
1395: REG_NOTES (last) = gen_rtx (INSN_LIST, REG_RETVAL, first, REG_NOTES (last));
1396: }
1397:
1398: /* Generate code to store zero in X. */
1399:
1400: void
1401: emit_clr_insn (x)
1402: rtx x;
1403: {
1404: emit_move_insn (x, const0_rtx);
1405: }
1406:
1407: /* Generate code to store 1 in X
1408: assuming it contains zero beforehand. */
1409:
1410: void
1411: emit_0_to_1_insn (x)
1412: rtx x;
1413: {
1414: emit_move_insn (x, const1_rtx);
1415: }
1416:
1417: /* Generate code to compare X with Y
1418: so that the condition codes are set.
1419:
1420: MODE is the mode of the inputs (in case they are const_int).
1421: UNSIGNEDP nonzero says that X and Y are unsigned;
1422: this matters if they need to be widened.
1423:
1424: If they have mode BLKmode, then SIZE specifies the size of both X and Y,
1425: and ALIGN specifies the known shared alignment of X and Y.
1426:
1427: COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).
1428: It is ignored for fixed-point and block comparisons;
1429: it is used only for floating-point comparisons. */
1430:
1431: void
1432: emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align)
1433: rtx x, y;
1434: enum rtx_code comparison;
1435: rtx size;
1.1.1.3 ! root 1436: enum machine_mode mode;
1.1 root 1437: int unsignedp;
1438: int align;
1439: {
1440: enum mode_class class;
1441: enum machine_mode wider_mode;
1442:
1443: class = GET_MODE_CLASS (mode);
1444:
1445: /* They could both be VOIDmode if both args are immediate constants,
1446: but we should fold that at an earlier stage.
1447: With no special code here, this will call abort,
1448: reminding the programmer to implement such folding. */
1449:
1450: if (mode != BLKmode && flag_force_mem)
1451: {
1452: x = force_not_mem (x);
1453: y = force_not_mem (y);
1454: }
1455:
1456: /* If we are inside an appropriately-short loop and one operand is an
1457: expensive constant, force it into a register. */
1.1.1.3 ! root 1458: if (CONSTANT_P (x) && preserve_subexpressions_p () && rtx_cost (x, COMPARE) > 2)
1.1 root 1459: x = force_reg (mode, x);
1460:
1.1.1.3 ! root 1461: if (CONSTANT_P (y) && preserve_subexpressions_p () && rtx_cost (y, COMPARE) > 2)
1.1 root 1462: y = force_reg (mode, y);
1463:
1464: /* Don't let both operands fail to indicate the mode. */
1465: if (GET_MODE (x) == VOIDmode && GET_MODE (y) == VOIDmode)
1466: x = force_reg (mode, x);
1467:
1468: /* Handle all BLKmode compares. */
1469:
1470: if (mode == BLKmode)
1471: {
1472: emit_queue ();
1473: x = protect_from_queue (x, 0);
1474: y = protect_from_queue (y, 0);
1475:
1476: if (size == 0)
1477: abort ();
1478: #ifdef HAVE_cmpstrqi
1479: if (HAVE_cmpstrqi
1480: && GET_CODE (size) == CONST_INT
1481: && INTVAL (size) < (1 << GET_MODE_BITSIZE (QImode)))
1482: {
1483: enum machine_mode result_mode
1484: = insn_operand_mode[(int) CODE_FOR_cmpstrqi][0];
1485: rtx result = gen_reg_rtx (result_mode);
1486: emit_insn (gen_cmpstrqi (result, x, y, size,
1487: gen_rtx (CONST_INT, VOIDmode, align)));
1488: emit_cmp_insn (result, const0_rtx, comparison, 0, result_mode, 0, 0);
1489: }
1490: else
1491: #endif
1492: #ifdef HAVE_cmpstrhi
1493: if (HAVE_cmpstrhi
1494: && GET_CODE (size) == CONST_INT
1495: && INTVAL (size) < (1 << GET_MODE_BITSIZE (HImode)))
1496: {
1497: enum machine_mode result_mode
1498: = insn_operand_mode[(int) CODE_FOR_cmpstrhi][0];
1499: rtx result = gen_reg_rtx (result_mode);
1500: emit_insn (gen_cmpstrhi (result, x, y, size,
1501: gen_rtx (CONST_INT, VOIDmode, align)));
1502: emit_cmp_insn (result, const0_rtx, comparison, 0, result_mode, 0, 0);
1503: }
1504: else
1505: #endif
1506: #ifdef HAVE_cmpstrsi
1507: if (HAVE_cmpstrsi)
1508: {
1509: enum machine_mode result_mode
1510: = insn_operand_mode[(int) CODE_FOR_cmpstrsi][0];
1511: rtx result = gen_reg_rtx (result_mode);
1512: emit_insn (gen_cmpstrsi (result, x, y,
1513: convert_to_mode (SImode, size, 1),
1514: gen_rtx (CONST_INT, VOIDmode, align)));
1515: emit_cmp_insn (result, const0_rtx, comparison, 0, result_mode, 0, 0);
1516: }
1517: else
1518: #endif
1519: {
1520: #ifdef TARGET_MEM_FUNCTIONS
1.1.1.2 root 1521: emit_library_call (memcmp_libfunc, 1,
1.1 root 1522: TYPE_MODE (integer_type_node), 3,
1523: XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
1524: size, Pmode);
1525: #else
1.1.1.2 root 1526: emit_library_call (bcmp_libfunc, 1,
1.1 root 1527: TYPE_MODE (integer_type_node), 3,
1528: XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
1529: size, Pmode);
1530: #endif
1531: emit_cmp_insn (hard_libcall_value (TYPE_MODE (integer_type_node)),
1532: const0_rtx, comparison, 0,
1533: TYPE_MODE (integer_type_node), 0, 0);
1534: }
1535: return;
1536: }
1537:
1538: /* Handle some compares against zero. */
1539:
1540: if (y == CONST0_RTX (mode)
1541: && tst_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1542: {
1543: int icode = (int) tst_optab->handlers[(int) mode].insn_code;
1544:
1545: emit_queue ();
1546: x = protect_from_queue (x, 0);
1547: y = protect_from_queue (y, 0);
1548:
1549: /* Now, if insn does accept these operands, put them into pseudos. */
1550: if (! (*insn_operand_predicate[icode][0])
1551: (x, insn_operand_mode[icode][0]))
1552: x = copy_to_mode_reg (insn_operand_mode[icode][0], x);
1553:
1554: emit_insn (GEN_FCN (icode) (x));
1555: return;
1556: }
1557:
1558: /* Handle compares for which there is a directly suitable insn. */
1559:
1560: if (cmp_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1561: {
1562: int icode = (int) cmp_optab->handlers[(int) mode].insn_code;
1563:
1564: emit_queue ();
1565: x = protect_from_queue (x, 0);
1566: y = protect_from_queue (y, 0);
1567:
1568: /* Now, if insn doesn't accept these operands, put them into pseudos. */
1569: if (! (*insn_operand_predicate[icode][0])
1570: (x, insn_operand_mode[icode][0]))
1571: x = copy_to_mode_reg (insn_operand_mode[icode][0], x);
1572:
1573: if (! (*insn_operand_predicate[icode][1])
1574: (y, insn_operand_mode[icode][1]))
1575: y = copy_to_mode_reg (insn_operand_mode[icode][1], y);
1576:
1577: emit_insn (GEN_FCN (icode) (x, y));
1578: return;
1579: }
1580:
1581: /* Try widening if we can find a direct insn that way. */
1582:
1583: if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
1584: {
1585: for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
1586: wider_mode = GET_MODE_WIDER_MODE (wider_mode))
1587: {
1588: if (cmp_optab->handlers[(int) wider_mode].insn_code
1589: != CODE_FOR_nothing)
1590: {
1591: x = convert_to_mode (wider_mode, x, unsignedp);
1592: y = convert_to_mode (wider_mode, y, unsignedp);
1593: emit_cmp_insn (x, y, comparison, 0,
1594: wider_mode, unsignedp, align);
1595: return;
1596: }
1597: }
1598: }
1599:
1600: /* Handle a lib call just for the mode we are using. */
1601:
1602: if (cmp_optab->handlers[(int) mode].libfunc
1603: && class != MODE_FLOAT)
1604: {
1605: rtx libfunc = cmp_optab->handlers[(int) mode].libfunc;
1606: /* If we want unsigned, and this mode has a distinct unsigned
1607: comparison routine, use that. */
1608: if (unsignedp && ucmp_optab->handlers[(int) mode].libfunc)
1609: libfunc = ucmp_optab->handlers[(int) mode].libfunc;
1610:
1.1.1.2 root 1611: emit_library_call (libfunc, 1,
1.1 root 1612: SImode, 2, x, mode, y, mode);
1613:
1614: /* Integer comparison returns a result that must be compared against 1,
1615: so that even if we do an unsigned compare afterward,
1616: there is still a value that can represent the result "less than". */
1617:
1618: emit_cmp_insn (hard_libcall_value (SImode), const1_rtx,
1619: comparison, 0, SImode, unsignedp, 0);
1620: return;
1621: }
1622:
1623: if (class == MODE_FLOAT)
1624: emit_float_lib_cmp (x, y, comparison);
1625:
1626: else
1627: abort ();
1628: }
1629:
1630: /* Nonzero if a compare of mode MODE can be done straightforwardly
1631: (without splitting it into pieces). */
1632:
1633: int
1634: can_compare_p (mode)
1635: enum machine_mode mode;
1636: {
1637: do
1638: {
1639: if (cmp_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)
1640: return 1;
1641: mode = GET_MODE_WIDER_MODE (mode);
1642: } while (mode != VOIDmode);
1643:
1644: return 0;
1645: }
1646:
1647: /* Emit a library call comparison between floating point X and Y.
1648: COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). */
1649:
1650: static void
1651: emit_float_lib_cmp (x, y, comparison)
1652: rtx x, y;
1653: enum rtx_code comparison;
1654: {
1655: enum machine_mode mode = GET_MODE (x);
1656: rtx libfunc;
1657:
1658: if (mode == SFmode)
1659: switch (comparison)
1660: {
1661: case EQ:
1662: libfunc = eqsf2_libfunc;
1663: break;
1664:
1665: case NE:
1666: libfunc = nesf2_libfunc;
1667: break;
1668:
1669: case GT:
1670: libfunc = gtsf2_libfunc;
1671: break;
1672:
1673: case GE:
1674: libfunc = gesf2_libfunc;
1675: break;
1676:
1677: case LT:
1678: libfunc = ltsf2_libfunc;
1679: break;
1680:
1681: case LE:
1682: libfunc = lesf2_libfunc;
1683: break;
1684: }
1685: else if (mode == DFmode)
1686: switch (comparison)
1687: {
1688: case EQ:
1689: libfunc = eqdf2_libfunc;
1690: break;
1691:
1692: case NE:
1693: libfunc = nedf2_libfunc;
1694: break;
1695:
1696: case GT:
1697: libfunc = gtdf2_libfunc;
1698: break;
1699:
1700: case GE:
1701: libfunc = gedf2_libfunc;
1702: break;
1703:
1704: case LT:
1705: libfunc = ltdf2_libfunc;
1706: break;
1707:
1708: case LE:
1709: libfunc = ledf2_libfunc;
1710: break;
1711: }
1712: else
1713: {
1714: enum machine_mode wider_mode;
1715:
1716: for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
1717: wider_mode = GET_MODE_WIDER_MODE (wider_mode))
1718: {
1719: if ((cmp_optab->handlers[(int) wider_mode].insn_code
1720: != CODE_FOR_nothing)
1721: || (cmp_optab->handlers[(int) wider_mode].libfunc != 0))
1722: {
1723: x = convert_to_mode (wider_mode, x, 0);
1724: y = convert_to_mode (wider_mode, y, 0);
1725: emit_float_lib_cmp (x, y, comparison);
1726: return;
1727: }
1728: }
1729: abort ();
1730: }
1731:
1.1.1.2 root 1732: emit_library_call (libfunc, 1,
1.1 root 1733: SImode, 2, x, mode, y, mode);
1734:
1735: emit_cmp_insn (hard_libcall_value (SImode), const0_rtx, comparison,
1736: 0, SImode, 0, 0);
1737: }
1738:
1739: /* Generate code to indirectly jump to a location given in the rtx LOC. */
1740:
1741: void
1742: emit_indirect_jump (loc)
1743: rtx loc;
1744: {
1745: if (! ((*insn_operand_predicate[(int)CODE_FOR_indirect_jump][0])
1746: (loc, VOIDmode)))
1747: loc = copy_to_mode_reg (insn_operand_mode[(int)CODE_FOR_indirect_jump][0],
1748: loc);
1749:
1750: emit_jump_insn (gen_indirect_jump (loc));
1.1.1.3 ! root 1751: emit_barrier ();
1.1 root 1752: }
1753:
1754: /* These three functions generate an insn body and return it
1755: rather than emitting the insn.
1756:
1757: They do not protect from queued increments,
1758: because they may be used 1) in protect_from_queue itself
1759: and 2) in other passes where there is no queue. */
1760:
1761: /* Generate and return an insn body to add Y to X. */
1762:
1763: rtx
1764: gen_add2_insn (x, y)
1765: rtx x, y;
1766: {
1767: int icode = (int) add_optab->handlers[(int) GET_MODE (x)].insn_code;
1768:
1769: if (! (*insn_operand_predicate[icode][0]) (x, insn_operand_mode[icode][0])
1770: || ! (*insn_operand_predicate[icode][1]) (x, insn_operand_mode[icode][1])
1771: || ! (*insn_operand_predicate[icode][2]) (y, insn_operand_mode[icode][2]))
1772: abort ();
1773:
1774: return (GEN_FCN (icode) (x, x, y));
1775: }
1776:
1777: int
1778: have_add2_insn (mode)
1779: enum machine_mode mode;
1780: {
1781: return add_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing;
1782: }
1783:
1784: /* Generate and return an insn body to subtract Y from X. */
1785:
1786: rtx
1787: gen_sub2_insn (x, y)
1788: rtx x, y;
1789: {
1790: int icode = (int) sub_optab->handlers[(int) GET_MODE (x)].insn_code;
1791:
1792: if (! (*insn_operand_predicate[icode][0]) (x, insn_operand_mode[icode][0])
1793: || ! (*insn_operand_predicate[icode][1]) (x, insn_operand_mode[icode][1])
1794: || ! (*insn_operand_predicate[icode][2]) (y, insn_operand_mode[icode][2]))
1795: abort ();
1796:
1797: return (GEN_FCN (icode) (x, x, y));
1798: }
1799:
1800: int
1801: have_sub2_insn (mode)
1802: enum machine_mode mode;
1803: {
1804: return sub_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing;
1805: }
1806:
1807: /* Generate the body of an instruction to copy Y into X. */
1808:
1809: rtx
1810: gen_move_insn (x, y)
1811: rtx x, y;
1812: {
1813: register enum machine_mode mode = GET_MODE (x);
1814: enum insn_code insn_code;
1815:
1816: if (mode == VOIDmode)
1817: mode = GET_MODE (y);
1818:
1819: insn_code = mov_optab->handlers[(int) mode].insn_code;
1820:
1821: /* Handle MODE_CC modes: If we don't have a special move insn for this mode,
1822: find a mode to do it in. If we have a movcc, use it. Otherwise,
1823: find the MODE_INT mode of the same width. */
1824:
1825: if (insn_code == CODE_FOR_nothing)
1826: {
1827: enum machine_mode tmode = VOIDmode;
1828: rtx x1 = x, y1 = y;
1829:
1830: if (GET_MODE_CLASS (mode) == MODE_CC && mode != CCmode
1831: && mov_optab->handlers[(int) CCmode].insn_code != CODE_FOR_nothing)
1832: tmode = CCmode;
1833: else if (GET_MODE_CLASS (mode) == MODE_CC)
1834: for (tmode = QImode; tmode != VOIDmode;
1835: tmode = GET_MODE_WIDER_MODE (tmode))
1836: if (GET_MODE_SIZE (tmode) == GET_MODE_SIZE (mode))
1837: break;
1838:
1839: if (tmode == VOIDmode)
1840: abort ();
1841:
1842: /* Get X and Y in TMODE. We can't use gen_lowpart here because it
1843: may call change_address which is not appropriate if we were
1844: called when a reload was in progress. We don't have to worry
1845: about changing the address since the size in bytes is supposed to
1846: be the same. Copy the MEM to change the mode and move any
1847: substitutions from the old MEM to the new one. */
1848:
1849: if (reload_in_progress)
1850: {
1851: x = gen_lowpart_common (tmode, x1);
1852: if (x == 0 && GET_CODE (x1) == MEM)
1853: {
1854: x = gen_rtx (MEM, tmode, XEXP (x1, 0));
1855: RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (x1);
1856: MEM_IN_STRUCT_P (x) = MEM_IN_STRUCT_P (x1);
1857: MEM_VOLATILE_P (x) = MEM_VOLATILE_P (x1);
1858: copy_replacements (x1, x);
1859: }
1860:
1861: y = gen_lowpart_common (tmode, y1);
1862: if (y == 0 && GET_CODE (y1) == MEM)
1863: {
1864: y = gen_rtx (MEM, tmode, XEXP (y1, 0));
1865: RTX_UNCHANGING_P (y) = RTX_UNCHANGING_P (y1);
1866: MEM_IN_STRUCT_P (y) = MEM_IN_STRUCT_P (y1);
1867: MEM_VOLATILE_P (y) = MEM_VOLATILE_P (y1);
1868: copy_replacements (y1, y);
1869: }
1870: }
1871: else
1872: {
1873: x = gen_lowpart (tmode, x);
1874: y = gen_lowpart (tmode, y);
1875: }
1876:
1877: insn_code = mov_optab->handlers[(int) tmode].insn_code;
1878: }
1879:
1880: return (GEN_FCN (insn_code) (x, y));
1881: }
1882:
1883: /* Tables of patterns for extending one integer mode to another. */
1884: static enum insn_code extendtab[MAX_MACHINE_MODE][MAX_MACHINE_MODE][2];
1885:
1886: /* Return the insn code used to extend FROM_MODE to TO_MODE.
1887: UNSIGNEDP specifies zero-extension instead of sign-extension. If
1888: no such operation exists, CODE_FOR_nothing will be returned. */
1889:
1890: enum insn_code
1891: can_extend_p (to_mode, from_mode, unsignedp)
1892: enum machine_mode to_mode, from_mode;
1893: int unsignedp;
1894: {
1895: return extendtab[(int) to_mode][(int) from_mode][unsignedp];
1896: }
1897:
1898: /* Generate the body of an insn to extend Y (with mode MFROM)
1899: into X (with mode MTO). Do zero-extension if UNSIGNEDP is nonzero. */
1900:
1901: rtx
1902: gen_extend_insn (x, y, mto, mfrom, unsignedp)
1903: rtx x, y;
1904: enum machine_mode mto, mfrom;
1905: int unsignedp;
1906: {
1907: return (GEN_FCN (extendtab[(int) mto][(int) mfrom][unsignedp]) (x, y));
1908: }
1909:
1910: static void
1911: init_extends ()
1912: {
1913: enum insn_code *p;
1914:
1915: for (p = extendtab[0][0];
1916: p < extendtab[0][0] + sizeof extendtab / sizeof extendtab[0][0][0];
1917: p++)
1918: *p = CODE_FOR_nothing;
1919:
1920: #ifdef HAVE_extendditi2
1921: if (HAVE_extendditi2)
1922: extendtab[(int) TImode][(int) DImode][0] = CODE_FOR_extendditi2;
1923: #endif
1924: #ifdef HAVE_extendsiti2
1925: if (HAVE_extendsiti2)
1926: extendtab[(int) TImode][(int) SImode][0] = CODE_FOR_extendsiti2;
1927: #endif
1928: #ifdef HAVE_extendhiti2
1929: if (HAVE_extendhiti2)
1930: extendtab[(int) TImode][(int) HImode][0] = CODE_FOR_extendhiti2;
1931: #endif
1932: #ifdef HAVE_extendqiti2
1933: if (HAVE_extendqiti2)
1934: extendtab[(int) TImode][(int) QImode][0] = CODE_FOR_extendqiti2;
1935: #endif
1936: #ifdef HAVE_extendsidi2
1937: if (HAVE_extendsidi2)
1938: extendtab[(int) DImode][(int) SImode][0] = CODE_FOR_extendsidi2;
1939: #endif
1940: #ifdef HAVE_extendhidi2
1941: if (HAVE_extendhidi2)
1942: extendtab[(int) DImode][(int) HImode][0] = CODE_FOR_extendhidi2;
1943: #endif
1944: #ifdef HAVE_extendqidi2
1945: if (HAVE_extendqidi2)
1946: extendtab[(int) DImode][(int) QImode][0] = CODE_FOR_extendqidi2;
1947: #endif
1948: #ifdef HAVE_extendhisi2
1949: if (HAVE_extendhisi2)
1950: extendtab[(int) SImode][(int) HImode][0] = CODE_FOR_extendhisi2;
1951: #endif
1952: #ifdef HAVE_extendqisi2
1953: if (HAVE_extendqisi2)
1954: extendtab[(int) SImode][(int) QImode][0] = CODE_FOR_extendqisi2;
1955: #endif
1956: #ifdef HAVE_extendqihi2
1957: if (HAVE_extendqihi2)
1958: extendtab[(int) HImode][(int) QImode][0] = CODE_FOR_extendqihi2;
1959: #endif
1960:
1961: #ifdef HAVE_zero_extendditi2
1962: if (HAVE_zero_extendsiti2)
1963: extendtab[(int) TImode][(int) DImode][1] = CODE_FOR_zero_extendditi2;
1964: #endif
1965: #ifdef HAVE_zero_extendsiti2
1966: if (HAVE_zero_extendsiti2)
1967: extendtab[(int) TImode][(int) SImode][1] = CODE_FOR_zero_extendsiti2;
1968: #endif
1969: #ifdef HAVE_zero_extendhiti2
1970: if (HAVE_zero_extendhiti2)
1971: extendtab[(int) TImode][(int) HImode][1] = CODE_FOR_zero_extendhiti2;
1972: #endif
1973: #ifdef HAVE_zero_extendqiti2
1974: if (HAVE_zero_extendqiti2)
1975: extendtab[(int) TImode][(int) QImode][1] = CODE_FOR_zero_extendqiti2;
1976: #endif
1977: #ifdef HAVE_zero_extendsidi2
1978: if (HAVE_zero_extendsidi2)
1979: extendtab[(int) DImode][(int) SImode][1] = CODE_FOR_zero_extendsidi2;
1980: #endif
1981: #ifdef HAVE_zero_extendhidi2
1982: if (HAVE_zero_extendhidi2)
1983: extendtab[(int) DImode][(int) HImode][1] = CODE_FOR_zero_extendhidi2;
1984: #endif
1985: #ifdef HAVE_zero_extendqidi2
1986: if (HAVE_zero_extendqidi2)
1987: extendtab[(int) DImode][(int) QImode][1] = CODE_FOR_zero_extendqidi2;
1988: #endif
1989: #ifdef HAVE_zero_extendhisi2
1990: if (HAVE_zero_extendhisi2)
1991: extendtab[(int) SImode][(int) HImode][1] = CODE_FOR_zero_extendhisi2;
1992: #endif
1993: #ifdef HAVE_zero_extendqisi2
1994: if (HAVE_zero_extendqisi2)
1995: extendtab[(int) SImode][(int) QImode][1] = CODE_FOR_zero_extendqisi2;
1996: #endif
1997: #ifdef HAVE_zero_extendqihi2
1998: if (HAVE_zero_extendqihi2)
1999: extendtab[(int) HImode][(int) QImode][1] = CODE_FOR_zero_extendqihi2;
2000: #endif
2001: }
2002:
2003: /* can_fix_p and can_float_p say whether the target machine
2004: can directly convert a given fixed point type to
2005: a given floating point type, or vice versa.
2006: The returned value is the CODE_FOR_... value to use,
2007: or CODE_FOR_nothing if these modes cannot be directly converted. */
2008:
2009: static enum insn_code fixtab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
2010: static enum insn_code fixtrunctab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
2011: static enum insn_code floattab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
2012:
2013: /* *TRUNCP_PTR is set to 1 if it is necessary to output
2014: an explicit FTRUNC insn before the fix insn; otherwise 0. */
2015:
2016: static enum insn_code
2017: can_fix_p (fixmode, fltmode, unsignedp, truncp_ptr)
2018: enum machine_mode fltmode, fixmode;
2019: int unsignedp;
2020: int *truncp_ptr;
2021: {
2022: *truncp_ptr = 0;
2023: if (fixtrunctab[(int) fltmode][(int) fixmode][unsignedp] != CODE_FOR_nothing)
2024: return fixtrunctab[(int) fltmode][(int) fixmode][unsignedp];
2025:
2026: if (ftrunc_optab->handlers[(int) fltmode].insn_code != CODE_FOR_nothing)
2027: {
2028: *truncp_ptr = 1;
2029: return fixtab[(int) fltmode][(int) fixmode][unsignedp];
2030: }
2031: return CODE_FOR_nothing;
2032: }
2033:
2034: static enum insn_code
2035: can_float_p (fltmode, fixmode, unsignedp)
2036: enum machine_mode fixmode, fltmode;
2037: int unsignedp;
2038: {
2039: return floattab[(int) fltmode][(int) fixmode][unsignedp];
2040: }
2041:
2042: void
2043: init_fixtab ()
2044: {
2045: enum insn_code *p;
2046: for (p = fixtab[0][0];
2047: p < fixtab[0][0] + sizeof fixtab / sizeof (fixtab[0][0][0]);
2048: p++)
2049: *p = CODE_FOR_nothing;
2050: for (p = fixtrunctab[0][0];
2051: p < fixtrunctab[0][0] + sizeof fixtrunctab / sizeof (fixtrunctab[0][0][0]);
2052: p++)
2053: *p = CODE_FOR_nothing;
2054:
2055: #ifdef HAVE_fixsfqi2
2056: if (HAVE_fixsfqi2)
2057: fixtab[(int) SFmode][(int) QImode][0] = CODE_FOR_fixsfqi2;
2058: #endif
2059: #ifdef HAVE_fixsfhi2
2060: if (HAVE_fixsfhi2)
2061: fixtab[(int) SFmode][(int) HImode][0] = CODE_FOR_fixsfhi2;
2062: #endif
2063: #ifdef HAVE_fixsfsi2
2064: if (HAVE_fixsfsi2)
2065: fixtab[(int) SFmode][(int) SImode][0] = CODE_FOR_fixsfsi2;
2066: #endif
2067: #ifdef HAVE_fixsfdi2
2068: if (HAVE_fixsfdi2)
2069: fixtab[(int) SFmode][(int) DImode][0] = CODE_FOR_fixsfdi2;
2070: #endif
2071:
2072: #ifdef HAVE_fixdfqi2
2073: if (HAVE_fixdfqi2)
2074: fixtab[(int) DFmode][(int) QImode][0] = CODE_FOR_fixdfqi2;
2075: #endif
2076: #ifdef HAVE_fixdfhi2
2077: if (HAVE_fixdfhi2)
2078: fixtab[(int) DFmode][(int) HImode][0] = CODE_FOR_fixdfhi2;
2079: #endif
2080: #ifdef HAVE_fixdfsi2
2081: if (HAVE_fixdfsi2)
2082: fixtab[(int) DFmode][(int) SImode][0] = CODE_FOR_fixdfsi2;
2083: #endif
2084: #ifdef HAVE_fixdfdi2
2085: if (HAVE_fixdfdi2)
2086: fixtab[(int) DFmode][(int) DImode][0] = CODE_FOR_fixdfdi2;
2087: #endif
2088: #ifdef HAVE_fixdfti2
2089: if (HAVE_fixdfti2)
2090: fixtab[(int) DFmode][(int) TImode][0] = CODE_FOR_fixdfti2;
2091: #endif
2092:
2093: #ifdef HAVE_fixtfqi2
2094: if (HAVE_fixtfqi2)
2095: fixtab[(int) TFmode][(int) QImode][0] = CODE_FOR_fixtfqi2;
2096: #endif
2097: #ifdef HAVE_fixtfhi2
2098: if (HAVE_fixtfhi2)
2099: fixtab[(int) TFmode][(int) HImode][0] = CODE_FOR_fixtfhi2;
2100: #endif
2101: #ifdef HAVE_fixtfsi2
2102: if (HAVE_fixtfsi2)
2103: fixtab[(int) TFmode][(int) SImode][0] = CODE_FOR_fixtfsi2;
2104: #endif
2105: #ifdef HAVE_fixtfdi2
2106: if (HAVE_fixtfdi2)
2107: fixtab[(int) TFmode][(int) DImode][0] = CODE_FOR_fixtfdi2;
2108: #endif
2109: #ifdef HAVE_fixtfti2
2110: if (HAVE_fixtfti2)
2111: fixtab[(int) TFmode][(int) TImode][0] = CODE_FOR_fixtfti2;
2112: #endif
2113:
2114: #ifdef HAVE_fixunssfqi2
2115: if (HAVE_fixunssfqi2)
2116: fixtab[(int) SFmode][(int) QImode][1] = CODE_FOR_fixunssfqi2;
2117: #endif
2118: #ifdef HAVE_fixunssfhi2
2119: if (HAVE_fixunssfhi2)
2120: fixtab[(int) SFmode][(int) HImode][1] = CODE_FOR_fixunssfhi2;
2121: #endif
2122: #ifdef HAVE_fixunssfsi2
2123: if (HAVE_fixunssfsi2)
2124: fixtab[(int) SFmode][(int) SImode][1] = CODE_FOR_fixunssfsi2;
2125: #endif
2126: #ifdef HAVE_fixunssfdi2
2127: if (HAVE_fixunssfdi2)
2128: fixtab[(int) SFmode][(int) DImode][1] = CODE_FOR_fixunssfdi2;
2129: #endif
2130:
2131: #ifdef HAVE_fixunsdfqi2
2132: if (HAVE_fixunsdfqi2)
2133: fixtab[(int) DFmode][(int) QImode][1] = CODE_FOR_fixunsdfqi2;
2134: #endif
2135: #ifdef HAVE_fixunsdfhi2
2136: if (HAVE_fixunsdfhi2)
2137: fixtab[(int) DFmode][(int) HImode][1] = CODE_FOR_fixunsdfhi2;
2138: #endif
2139: #ifdef HAVE_fixunsdfsi2
2140: if (HAVE_fixunsdfsi2)
2141: fixtab[(int) DFmode][(int) SImode][1] = CODE_FOR_fixunsdfsi2;
2142: #endif
2143: #ifdef HAVE_fixunsdfdi2
2144: if (HAVE_fixunsdfdi2)
2145: fixtab[(int) DFmode][(int) DImode][1] = CODE_FOR_fixunsdfdi2;
2146: #endif
2147: #ifdef HAVE_fixunsdfti2
2148: if (HAVE_fixunsdfti2)
2149: fixtab[(int) DFmode][(int) TImode][1] = CODE_FOR_fixunsdfti2;
2150: #endif
2151:
2152: #ifdef HAVE_fixunstfqi2
2153: if (HAVE_fixunstfqi2)
2154: fixtab[(int) TFmode][(int) QImode][1] = CODE_FOR_fixunstfqi2;
2155: #endif
2156: #ifdef HAVE_fixunstfhi2
2157: if (HAVE_fixunstfhi2)
2158: fixtab[(int) TFmode][(int) HImode][1] = CODE_FOR_fixunstfhi2;
2159: #endif
2160: #ifdef HAVE_fixunstfsi2
2161: if (HAVE_fixunstfsi2)
2162: fixtab[(int) TFmode][(int) SImode][1] = CODE_FOR_fixunstfsi2;
2163: #endif
2164: #ifdef HAVE_fixunstfdi2
2165: if (HAVE_fixunstfdi2)
2166: fixtab[(int) TFmode][(int) DImode][1] = CODE_FOR_fixunstfdi2;
2167: #endif
2168: #ifdef HAVE_fixunstfti2
2169: if (HAVE_fixunstfti2)
2170: fixtab[(int) TFmode][(int) TImode][1] = CODE_FOR_fixunstfti2;
2171: #endif
2172:
2173: #ifdef HAVE_fix_truncsfqi2
2174: if (HAVE_fix_truncsfqi2)
2175: fixtrunctab[(int) SFmode][(int) QImode][0] = CODE_FOR_fix_truncsfqi2;
2176: #endif
2177: #ifdef HAVE_fix_truncsfhi2
2178: if (HAVE_fix_truncsfhi2)
2179: fixtrunctab[(int) SFmode][(int) HImode][0] = CODE_FOR_fix_truncsfhi2;
2180: #endif
2181: #ifdef HAVE_fix_truncsfsi2
2182: if (HAVE_fix_truncsfsi2)
2183: fixtrunctab[(int) SFmode][(int) SImode][0] = CODE_FOR_fix_truncsfsi2;
2184: #endif
2185: #ifdef HAVE_fix_truncsfdi2
2186: if (HAVE_fix_truncsfdi2)
2187: fixtrunctab[(int) SFmode][(int) DImode][0] = CODE_FOR_fix_truncsfdi2;
2188: #endif
2189:
2190: #ifdef HAVE_fix_truncdfqi2
2191: if (HAVE_fix_truncdfsi2)
2192: fixtrunctab[(int) DFmode][(int) QImode][0] = CODE_FOR_fix_truncdfqi2;
2193: #endif
2194: #ifdef HAVE_fix_truncdfhi2
2195: if (HAVE_fix_truncdfhi2)
2196: fixtrunctab[(int) DFmode][(int) HImode][0] = CODE_FOR_fix_truncdfhi2;
2197: #endif
2198: #ifdef HAVE_fix_truncdfsi2
2199: if (HAVE_fix_truncdfsi2)
2200: fixtrunctab[(int) DFmode][(int) SImode][0] = CODE_FOR_fix_truncdfsi2;
2201: #endif
2202: #ifdef HAVE_fix_truncdfdi2
2203: if (HAVE_fix_truncdfdi2)
2204: fixtrunctab[(int) DFmode][(int) DImode][0] = CODE_FOR_fix_truncdfdi2;
2205: #endif
2206: #ifdef HAVE_fix_truncdfti2
2207: if (HAVE_fix_truncdfti2)
2208: fixtrunctab[(int) DFmode][(int) TImode][0] = CODE_FOR_fix_truncdfti2;
2209: #endif
2210:
2211: #ifdef HAVE_fix_trunctfqi2
2212: if (HAVE_fix_trunctfqi2)
2213: fixtrunctab[(int) TFmode][(int) QImode][0] = CODE_FOR_fix_trunctfqi2;
2214: #endif
2215: #ifdef HAVE_fix_trunctfhi2
2216: if (HAVE_fix_trunctfhi2)
2217: fixtrunctab[(int) TFmode][(int) HImode][0] = CODE_FOR_fix_trunctfhi2;
2218: #endif
2219: #ifdef HAVE_fix_trunctfsi2
2220: if (HAVE_fix_trunctfsi2)
2221: fixtrunctab[(int) TFmode][(int) SImode][0] = CODE_FOR_fix_trunctfsi2;
2222: #endif
2223: #ifdef HAVE_fix_trunctfdi2
2224: if (HAVE_fix_trunctfdi2)
2225: fixtrunctab[(int) TFmode][(int) DImode][0] = CODE_FOR_fix_trunctfdi2;
2226: #endif
2227: #ifdef HAVE_fix_trunctfti2
2228: if (HAVE_fix_trunctfti2)
2229: fixtrunctab[(int) TFmode][(int) TImode][0] = CODE_FOR_fix_trunctfti2;
2230: #endif
2231:
2232: #ifdef HAVE_fixuns_truncsfqi2
2233: if (HAVE_fixuns_truncsfqi2)
2234: fixtrunctab[(int) SFmode][(int) QImode][1] = CODE_FOR_fixuns_truncsfqi2;
2235: #endif
2236: #ifdef HAVE_fixuns_truncsfhi2
2237: if (HAVE_fixuns_truncsfhi2)
2238: fixtrunctab[(int) SFmode][(int) HImode][1] = CODE_FOR_fixuns_truncsfhi2;
2239: #endif
2240: #ifdef HAVE_fixuns_truncsfsi2
2241: if (HAVE_fixuns_truncsfsi2)
2242: fixtrunctab[(int) SFmode][(int) SImode][1] = CODE_FOR_fixuns_truncsfsi2;
2243: #endif
2244: #ifdef HAVE_fixuns_truncsfdi2
2245: if (HAVE_fixuns_truncsfdi2)
2246: fixtrunctab[(int) SFmode][(int) DImode][1] = CODE_FOR_fixuns_truncsfdi2;
2247: #endif
2248:
2249: #ifdef HAVE_fixuns_truncdfqi2
2250: if (HAVE_fixuns_truncdfqi2)
2251: fixtrunctab[(int) DFmode][(int) QImode][1] = CODE_FOR_fixuns_truncdfqi2;
2252: #endif
2253: #ifdef HAVE_fixuns_truncdfhi2
2254: if (HAVE_fixuns_truncdfhi2)
2255: fixtrunctab[(int) DFmode][(int) HImode][1] = CODE_FOR_fixuns_truncdfhi2;
2256: #endif
2257: #ifdef HAVE_fixuns_truncdfsi2
2258: if (HAVE_fixuns_truncdfsi2)
2259: fixtrunctab[(int) DFmode][(int) SImode][1] = CODE_FOR_fixuns_truncdfsi2;
2260: #endif
2261: #ifdef HAVE_fixuns_truncdfdi2
2262: if (HAVE_fixuns_truncdfdi2)
2263: fixtrunctab[(int) DFmode][(int) DImode][1] = CODE_FOR_fixuns_truncdfdi2;
2264: #endif
2265: #ifdef HAVE_fixuns_truncdfti2
2266: if (HAVE_fixuns_truncdfti2)
2267: fixtrunctab[(int) DFmode][(int) TImode][1] = CODE_FOR_fixuns_truncdfti2;
2268: #endif
2269:
2270: #ifdef HAVE_fixuns_trunctfqi2
2271: if (HAVE_fixuns_trunctfqi2)
2272: fixtrunctab[(int) TFmode][(int) QImode][1] = CODE_FOR_fixuns_trunctfqi2;
2273: #endif
2274: #ifdef HAVE_fixuns_trunctfhi2
2275: if (HAVE_fixuns_trunctfhi2)
2276: fixtrunctab[(int) TFmode][(int) HImode][1] = CODE_FOR_fixuns_trunctfhi2;
2277: #endif
2278: #ifdef HAVE_fixuns_trunctfsi2
2279: if (HAVE_fixuns_trunctfsi2)
2280: fixtrunctab[(int) TFmode][(int) SImode][1] = CODE_FOR_fixuns_trunctfsi2;
2281: #endif
2282: #ifdef HAVE_fixuns_trunctfdi2
2283: if (HAVE_fixuns_trunctfdi2)
2284: fixtrunctab[(int) TFmode][(int) DImode][1] = CODE_FOR_fixuns_trunctfdi2;
2285: #endif
2286: #ifdef HAVE_fixuns_trunctfti2
2287: if (HAVE_fixuns_trunctfti2)
2288: fixtrunctab[(int) TFmode][(int) TImode][1] = CODE_FOR_fixuns_trunctfti2;
2289: #endif
2290:
2291: #ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC
2292: /* This flag says the same insns that convert to a signed fixnum
2293: also convert validly to an unsigned one. */
2294: {
2295: int i;
2296: int j;
2297: for (i = 0; i < NUM_MACHINE_MODES; i++)
2298: for (j = 0; j < NUM_MACHINE_MODES; j++)
2299: fixtrunctab[i][j][1] = fixtrunctab[i][j][0];
2300: }
2301: #endif
2302: }
2303:
2304: void
2305: init_floattab ()
2306: {
2307: enum insn_code *p;
2308: for (p = floattab[0][0];
2309: p < floattab[0][0] + sizeof floattab / sizeof (floattab[0][0][0]);
2310: p++)
2311: *p = CODE_FOR_nothing;
2312:
2313: #ifdef HAVE_floatqisf2
2314: if (HAVE_floatqisf2)
2315: floattab[(int) SFmode][(int) QImode][0] = CODE_FOR_floatqisf2;
2316: #endif
2317: #ifdef HAVE_floathisf2
2318: if (HAVE_floathisf2)
2319: floattab[(int) SFmode][(int) HImode][0] = CODE_FOR_floathisf2;
2320: #endif
2321: #ifdef HAVE_floatsisf2
2322: if (HAVE_floatsisf2)
2323: floattab[(int) SFmode][(int) SImode][0] = CODE_FOR_floatsisf2;
2324: #endif
2325: #ifdef HAVE_floatdisf2
2326: if (HAVE_floatdisf2)
2327: floattab[(int) SFmode][(int) DImode][0] = CODE_FOR_floatdisf2;
2328: #endif
2329: #ifdef HAVE_floattisf2
2330: if (HAVE_floattisf2)
2331: floattab[(int) SFmode][(int) TImode][0] = CODE_FOR_floattisf2;
2332: #endif
2333:
2334: #ifdef HAVE_floatqidf2
2335: if (HAVE_floatqidf2)
2336: floattab[(int) DFmode][(int) QImode][0] = CODE_FOR_floatqidf2;
2337: #endif
2338: #ifdef HAVE_floathidf2
2339: if (HAVE_floathidf2)
2340: floattab[(int) DFmode][(int) HImode][0] = CODE_FOR_floathidf2;
2341: #endif
2342: #ifdef HAVE_floatsidf2
2343: if (HAVE_floatsidf2)
2344: floattab[(int) DFmode][(int) SImode][0] = CODE_FOR_floatsidf2;
2345: #endif
2346: #ifdef HAVE_floatdidf2
2347: if (HAVE_floatdidf2)
2348: floattab[(int) DFmode][(int) DImode][0] = CODE_FOR_floatdidf2;
2349: #endif
2350: #ifdef HAVE_floattidf2
2351: if (HAVE_floattidf2)
2352: floattab[(int) DFmode][(int) TImode][0] = CODE_FOR_floattidf2;
2353: #endif
2354:
2355: #ifdef HAVE_floatqitf2
2356: if (HAVE_floatqitf2)
2357: floattab[(int) TFmode][(int) QImode][0] = CODE_FOR_floatqitf2;
2358: #endif
2359: #ifdef HAVE_floathitf2
2360: if (HAVE_floathitf2)
2361: floattab[(int) TFmode][(int) HImode][0] = CODE_FOR_floathitf2;
2362: #endif
2363: #ifdef HAVE_floatsitf2
2364: if (HAVE_floatsitf2)
2365: floattab[(int) TFmode][(int) SImode][0] = CODE_FOR_floatsitf2;
2366: #endif
2367: #ifdef HAVE_floatditf2
2368: if (HAVE_floatditf2)
2369: floattab[(int) TFmode][(int) DImode][0] = CODE_FOR_floatditf2;
2370: #endif
2371: #ifdef HAVE_floattitf2
2372: if (HAVE_floattitf2)
2373: floattab[(int) TFmode][(int) TImode][0] = CODE_FOR_floattitf2;
2374: #endif
2375:
2376: #ifdef HAVE_floatunsqisf2
2377: if (HAVE_floatunsqisf2)
2378: floattab[(int) SFmode][(int) QImode][1] = CODE_FOR_floatunsqisf2;
2379: #endif
2380: #ifdef HAVE_floatunshisf2
2381: if (HAVE_floatunshisf2)
2382: floattab[(int) SFmode][(int) HImode][1] = CODE_FOR_floatunshisf2;
2383: #endif
2384: #ifdef HAVE_floatunssisf2
2385: if (HAVE_floatunssisf2)
2386: floattab[(int) SFmode][(int) SImode][1] = CODE_FOR_floatunssisf2;
2387: #endif
2388: #ifdef HAVE_floatunsdisf2
2389: if (HAVE_floatunsdisf2)
2390: floattab[(int) SFmode][(int) DImode][1] = CODE_FOR_floatunsdisf2;
2391: #endif
2392: #ifdef HAVE_floatunstisf2
2393: if (HAVE_floatunstisf2)
2394: floattab[(int) SFmode][(int) TImode][1] = CODE_FOR_floatunstisf2;
2395: #endif
2396:
2397: #ifdef HAVE_floatunsqidf2
2398: if (HAVE_floatunsqidf2)
2399: floattab[(int) DFmode][(int) QImode][1] = CODE_FOR_floatunsqidf2;
2400: #endif
2401: #ifdef HAVE_floatunshidf2
2402: if (HAVE_floatunshidf2)
2403: floattab[(int) DFmode][(int) HImode][1] = CODE_FOR_floatunshidf2;
2404: #endif
2405: #ifdef HAVE_floatunssidf2
2406: if (HAVE_floatunssidf2)
2407: floattab[(int) DFmode][(int) SImode][1] = CODE_FOR_floatunssidf2;
2408: #endif
2409: #ifdef HAVE_floatunsdidf2
2410: if (HAVE_floatunsdidf2)
2411: floattab[(int) DFmode][(int) DImode][1] = CODE_FOR_floatunsdidf2;
2412: #endif
2413: #ifdef HAVE_floatunstidf2
2414: if (HAVE_floatunstidf2)
2415: floattab[(int) DFmode][(int) TImode][1] = CODE_FOR_floatunstidf2;
2416: #endif
2417:
2418: #ifdef HAVE_floatunsqitf2
2419: if (HAVE_floatunsqitf2)
2420: floattab[(int) TFmode][(int) QImode][1] = CODE_FOR_floatunsqitf2;
2421: #endif
2422: #ifdef HAVE_floatunshitf2
2423: if (HAVE_floatunshitf2)
2424: floattab[(int) TFmode][(int) HImode][1] = CODE_FOR_floatunshitf2;
2425: #endif
2426: #ifdef HAVE_floatunssitf2
2427: if (HAVE_floatunssitf2)
2428: floattab[(int) TFmode][(int) SImode][1] = CODE_FOR_floatunssitf2;
2429: #endif
2430: #ifdef HAVE_floatunsditf2
2431: if (HAVE_floatunsditf2)
2432: floattab[(int) TFmode][(int) DImode][1] = CODE_FOR_floatunsditf2;
2433: #endif
2434: #ifdef HAVE_floatunstitf2
2435: if (HAVE_floatunstitf2)
2436: floattab[(int) TFmode][(int) TImode][1] = CODE_FOR_floatunstitf2;
2437: #endif
2438: }
2439:
2440: /* Generate code to convert FROM to floating point
2441: and store in TO. FROM must be fixed point and not VOIDmode.
2442: UNSIGNEDP nonzero means regard FROM as unsigned.
2443: Normally this is done by correcting the final value
2444: if it is negative. */
2445:
2446: void
2447: expand_float (to, from, unsignedp)
2448: rtx to, from;
2449: int unsignedp;
2450: {
2451: enum insn_code icode;
2452: register rtx target = to;
2453: enum machine_mode fmode, imode;
2454:
2455: /* Crash now, because we won't be able to decide which mode to use. */
2456: if (GET_MODE (from) == VOIDmode)
2457: abort ();
2458:
2459: /* Look for an insn to do the conversion. Do it in the specified
2460: modes if possible; otherwise convert either input, output or both to
2461: wider mode. If the integer mode is wider than the mode of FROM,
2462: we can do the conversion signed even if the input is unsigned. */
2463:
2464: for (imode = GET_MODE (from); imode != VOIDmode;
2465: imode = GET_MODE_WIDER_MODE (imode))
2466: for (fmode = GET_MODE (to); fmode != VOIDmode;
2467: fmode = GET_MODE_WIDER_MODE (fmode))
2468: {
2469: int doing_unsigned = unsignedp;
2470:
2471: icode = can_float_p (fmode, imode, unsignedp);
2472: if (icode == CODE_FOR_nothing && imode != GET_MODE (from) && unsignedp)
2473: icode = can_float_p (fmode, imode, 0), doing_unsigned = 0;
2474:
2475: if (icode != CODE_FOR_nothing)
2476: {
2477: to = protect_from_queue (to, 1);
2478:
2479: if (imode != GET_MODE (from))
2480: from = convert_to_mode (imode, from, unsignedp);
2481: else
2482: from = protect_from_queue (from, 0);
2483:
2484: if (fmode != GET_MODE (to))
2485: target = gen_reg_rtx (fmode);
2486:
2487: emit_unop_insn (icode, target, from,
2488: doing_unsigned ? UNSIGNED_FLOAT : FLOAT);
2489:
2490: if (target != to)
2491: convert_move (to, target, 0);
2492: return;
2493: }
2494: }
2495:
2496: #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
2497:
2498: /* Unsigned integer, and no way to convert directly.
2499: Convert as signed, then conditionally adjust the result. */
2500: if (unsignedp)
2501: {
2502: rtx label = gen_label_rtx ();
2503: rtx temp;
2504: REAL_VALUE_TYPE offset;
2505:
2506: emit_queue ();
2507:
2508: to = protect_from_queue (to, 1);
2509: from = protect_from_queue (from, 0);
2510:
2511: if (flag_force_mem)
2512: from = force_not_mem (from);
2513:
2514: /* If we are about to do some arithmetic to correct for an
2515: unsigned operand, do it in a pseudo-register. */
2516:
2517: if (GET_CODE (to) != REG || REGNO (to) <= LAST_VIRTUAL_REGISTER)
2518: target = gen_reg_rtx (GET_MODE (to));
2519:
2520: /* Convert as signed integer to floating. */
2521: expand_float (target, from, 0);
2522:
2523: /* If FROM is negative (and therefore TO is negative),
2524: correct its value by 2**bitwidth. */
2525:
2526: do_pending_stack_adjust ();
2527: emit_cmp_insn (from, const0_rtx, GE, 0, GET_MODE (from), 0, 0);
2528: emit_jump_insn (gen_bge (label));
2529: /* On SCO 3.2.1, ldexp rejects values outside [0.5, 1).
2530: Rather than setting up a dconst_dot_5, let's hope SCO
2531: fixes the bug. */
2532: offset = REAL_VALUE_LDEXP (dconst1, GET_MODE_BITSIZE (GET_MODE (from)));
2533: temp = expand_binop (GET_MODE (to), add_optab, target,
2534: immed_real_const_1 (offset, GET_MODE (to)),
2535: target, 0, OPTAB_LIB_WIDEN);
2536: if (temp != target)
2537: emit_move_insn (target, temp);
2538: do_pending_stack_adjust ();
2539: emit_label (label);
2540: }
2541: else
2542: #endif
2543:
2544: /* No hardware instruction available; call a library
2545: to convert from SImode or DImode into SFmode or DFmode. */
2546: {
2547: rtx libfcn;
2548: rtx insns;
2549:
2550: to = protect_from_queue (to, 1);
2551:
2552: if (GET_MODE_SIZE (GET_MODE (from)) < GET_MODE_SIZE (SImode))
2553: from = convert_to_mode (SImode, from, unsignedp);
2554: else
2555: from = protect_from_queue (from, 0);
2556:
2557: if (flag_force_mem)
2558: from = force_not_mem (from);
2559:
2560: if (GET_MODE (to) == SFmode)
2561: {
2562: if (GET_MODE (from) == SImode)
2563: libfcn = floatsisf_libfunc;
2564: else if (GET_MODE (from) == DImode)
2565: libfcn = floatdisf_libfunc;
2566: else
2567: abort ();
2568: }
2569: else if (GET_MODE (to) == DFmode)
2570: {
2571: if (GET_MODE (from) == SImode)
2572: libfcn = floatsidf_libfunc;
2573: else if (GET_MODE (from) == DImode)
2574: libfcn = floatdidf_libfunc;
2575: else
2576: abort ();
2577: }
2578: else
2579: abort ();
2580:
2581: start_sequence ();
2582:
1.1.1.2 root 2583: emit_library_call (libfcn, 1, GET_MODE (to), 1, from, GET_MODE (from));
1.1 root 2584: insns = get_insns ();
2585: end_sequence ();
2586:
2587: emit_libcall_block (insns, target, hard_libcall_value (GET_MODE (to)),
2588: gen_rtx (FLOAT, GET_MODE (to), from));
2589: }
2590:
2591: /* Copy result to requested destination
2592: if we have been computing in a temp location. */
2593:
2594: if (target != to)
2595: {
2596: if (GET_MODE (target) == GET_MODE (to))
2597: emit_move_insn (to, target);
2598: else
2599: convert_move (to, target, 0);
2600: }
2601: }
2602:
2603: /* expand_fix: generate code to convert FROM to fixed point
2604: and store in TO. FROM must be floating point. */
2605:
2606: static rtx
2607: ftruncify (x)
2608: rtx x;
2609: {
2610: rtx temp = gen_reg_rtx (GET_MODE (x));
2611: return expand_unop (GET_MODE (x), ftrunc_optab, x, temp, 0);
2612: }
2613:
2614: void
2615: expand_fix (to, from, unsignedp)
2616: register rtx to, from;
2617: int unsignedp;
2618: {
2619: enum insn_code icode;
2620: register rtx target = to;
2621: enum machine_mode fmode, imode;
2622: int must_trunc = 0;
2623: rtx libfcn = 0;
2624:
2625: /* We first try to find a pair of modes, one real and one integer, at
2626: least as wide as FROM and TO, respectively, in which we can open-code
2627: this conversion. If the integer mode is wider than the mode of TO,
2628: we can do the conversion either signed or unsigned. */
2629:
2630: for (imode = GET_MODE (to); imode != VOIDmode;
2631: imode = GET_MODE_WIDER_MODE (imode))
2632: for (fmode = GET_MODE (from); fmode != VOIDmode;
2633: fmode = GET_MODE_WIDER_MODE (fmode))
2634: {
2635: int doing_unsigned = unsignedp;
2636:
2637: icode = can_fix_p (imode, fmode, unsignedp, &must_trunc);
2638: if (icode == CODE_FOR_nothing && imode != GET_MODE (to) && unsignedp)
2639: icode = can_fix_p (imode, fmode, 0, &must_trunc), doing_unsigned = 0;
2640:
2641: if (icode != CODE_FOR_nothing)
2642: {
2643: to = protect_from_queue (to, 1);
2644:
2645: if (fmode != GET_MODE (from))
2646: from = convert_to_mode (fmode, from, 0);
2647: else
2648: from = protect_from_queue (from, 0);
2649:
2650: if (must_trunc)
2651: from = ftruncify (from);
2652:
2653: if (imode != GET_MODE (to))
2654: target = gen_reg_rtx (imode);
2655:
2656: emit_unop_insn (icode, target, from,
2657: doing_unsigned ? UNSIGNED_FIX : FIX);
2658: if (target != to)
2659: convert_move (to, target, unsignedp);
2660: return;
2661: }
2662: }
2663:
2664: #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
2665: /* For an unsigned conversion, there is one more way to do it.
2666: If we have a signed conversion, we generate code that compares
2667: the real value to the largest representable positive number. If if
2668: is smaller, the conversion is done normally. Otherwise, subtract
2669: one plus the highest signed number, convert, and add it back.
2670:
2671: We only need to check all real modes, since we know we didn't find
1.1.1.3 ! root 2672: anything with a wider integer mode. */
1.1 root 2673:
2674: if (unsignedp && GET_MODE_BITSIZE (GET_MODE (to)) <= HOST_BITS_PER_INT)
2675: for (fmode = GET_MODE (from); fmode != VOIDmode;
2676: fmode = GET_MODE_WIDER_MODE (fmode))
2677: /* Make sure we won't lose significant bits doing this. */
2678: if (GET_MODE_BITSIZE (fmode) > GET_MODE_BITSIZE (GET_MODE (to))
2679: && CODE_FOR_nothing != can_fix_p (GET_MODE (to), fmode, 0,
2680: &must_trunc))
2681: {
2682: int bitsize = GET_MODE_BITSIZE (GET_MODE (to));
2683: REAL_VALUE_TYPE offset = REAL_VALUE_LDEXP (dconst1, bitsize - 1);
2684: rtx limit = immed_real_const_1 (offset, fmode);
2685: rtx lab1 = gen_label_rtx ();
2686: rtx lab2 = gen_label_rtx ();
2687: rtx insn;
2688:
2689: emit_queue ();
2690: to = protect_from_queue (to, 1);
2691: from = protect_from_queue (from, 0);
2692:
2693: if (flag_force_mem)
2694: from = force_not_mem (from);
2695:
2696: if (fmode != GET_MODE (from))
2697: from = convert_to_mode (fmode, from, 0);
2698:
2699: /* See if we need to do the subtraction. */
2700: do_pending_stack_adjust ();
2701: emit_cmp_insn (from, limit, GE, 0, GET_MODE (from), 0, 0);
2702: emit_jump_insn (gen_bge (lab1));
2703:
2704: /* If not, do the signed "fix" and branch around fixup code. */
2705: expand_fix (to, from, 0);
2706: emit_jump_insn (gen_jump (lab2));
2707: emit_barrier ();
2708:
2709: /* Otherwise, subtract 2**(N-1), convert to signed number,
2710: then add 2**(N-1). Do the addition using XOR since this
2711: will often generate better code. */
2712: emit_label (lab1);
2713: target = expand_binop (GET_MODE (from), sub_optab, from, limit,
2714: 0, 0, OPTAB_LIB_WIDEN);
2715: expand_fix (to, target, 0);
2716: target = expand_binop (GET_MODE (to), xor_optab, to,
2717: gen_rtx (CONST_INT, VOIDmode,
2718: 1 << (bitsize - 1)),
2719: to, 1, OPTAB_LIB_WIDEN);
2720:
2721: if (target != to)
2722: emit_move_insn (to, target);
2723:
2724: emit_label (lab2);
2725:
2726: /* Make a place for a REG_NOTE and add it. */
2727: insn = emit_move_insn (to, to);
2728: REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL,
2729: gen_rtx (UNSIGNED_FIX, GET_MODE (to),
2730: from), REG_NOTES (insn));
2731:
2732: return;
2733: }
2734: #endif
2735:
2736: /* We can't do it with an insn, so use a library call. But first ensure
2737: that the mode of TO is at least as wide as SImode, since those are the
2738: only library calls we know about. */
2739:
2740: if (GET_MODE_SIZE (GET_MODE (to)) < GET_MODE_SIZE (SImode))
2741: {
2742: target = gen_reg_rtx (SImode);
2743:
2744: expand_fix (target, from, unsignedp);
2745: }
2746: else if (GET_MODE (from) == SFmode)
2747: {
2748: if (GET_MODE (to) == SImode)
2749: libfcn = unsignedp ? fixunssfsi_libfunc : fixsfsi_libfunc;
2750: else if (GET_MODE (to) == DImode)
2751: libfcn = unsignedp ? fixunssfdi_libfunc : fixsfdi_libfunc;
2752: else
2753: abort ();
2754: }
2755: else if (GET_MODE (from) == DFmode)
2756: {
2757: if (GET_MODE (to) == SImode)
2758: libfcn = unsignedp ? fixunsdfsi_libfunc : fixdfsi_libfunc;
2759: else if (GET_MODE (to) == DImode)
2760: libfcn = unsignedp ? fixunsdfdi_libfunc : fixdfdi_libfunc;
2761: else
2762: abort ();
2763: }
2764: else
2765: abort ();
2766:
2767: if (libfcn)
2768: {
2769: rtx insns;
2770:
2771: to = protect_from_queue (to, 1);
2772: from = protect_from_queue (from, 0);
2773:
2774: if (flag_force_mem)
2775: from = force_not_mem (from);
2776:
2777: start_sequence ();
2778:
1.1.1.2 root 2779: emit_library_call (libfcn, 1, GET_MODE (to), 1, from, GET_MODE (from));
1.1 root 2780: insns = get_insns ();
2781: end_sequence ();
2782:
2783: emit_libcall_block (insns, target, hard_libcall_value (GET_MODE (to)),
2784: gen_rtx (unsignedp ? FIX : UNSIGNED_FIX,
2785: GET_MODE (to), from));
2786: }
2787:
2788: if (GET_MODE (to) == GET_MODE (target))
2789: emit_move_insn (to, target);
2790: else
2791: convert_move (to, target, 0);
2792: }
2793:
2794: static optab
2795: init_optab (code)
2796: enum rtx_code code;
2797: {
2798: int i;
2799: optab op = (optab) xmalloc (sizeof (struct optab));
2800: op->code = code;
2801: for (i = 0; i < NUM_MACHINE_MODES; i++)
2802: {
2803: op->handlers[i].insn_code = CODE_FOR_nothing;
2804: op->handlers[i].libfunc = 0;
2805: }
2806: return op;
2807: }
2808:
2809: /* Call this once to initialize the contents of the optabs
2810: appropriately for the current target machine. */
2811:
2812: void
2813: init_optabs ()
2814: {
2815: int i;
2816:
2817: init_fixtab ();
2818: init_floattab ();
2819: init_extends ();
2820:
2821: add_optab = init_optab (PLUS);
2822: sub_optab = init_optab (MINUS);
2823: smul_optab = init_optab (MULT);
2824: smul_widen_optab = init_optab (UNKNOWN);
2825: umul_widen_optab = init_optab (UNKNOWN);
2826: sdiv_optab = init_optab (DIV);
2827: sdivmod_optab = init_optab (UNKNOWN);
2828: udiv_optab = init_optab (UDIV);
2829: udivmod_optab = init_optab (UNKNOWN);
2830: smod_optab = init_optab (MOD);
2831: umod_optab = init_optab (UMOD);
2832: flodiv_optab = init_optab (DIV);
2833: ftrunc_optab = init_optab (UNKNOWN);
2834: and_optab = init_optab (AND);
2835: ior_optab = init_optab (IOR);
2836: xor_optab = init_optab (XOR);
2837: ashl_optab = init_optab (ASHIFT);
2838: ashr_optab = init_optab (ASHIFTRT);
2839: lshl_optab = init_optab (LSHIFT);
2840: lshr_optab = init_optab (LSHIFTRT);
2841: rotl_optab = init_optab (ROTATE);
2842: rotr_optab = init_optab (ROTATERT);
2843: smin_optab = init_optab (SMIN);
2844: smax_optab = init_optab (SMAX);
2845: umin_optab = init_optab (UMIN);
2846: umax_optab = init_optab (UMAX);
2847: mov_optab = init_optab (UNKNOWN);
2848: movstrict_optab = init_optab (UNKNOWN);
2849: cmp_optab = init_optab (UNKNOWN);
2850: ucmp_optab = init_optab (UNKNOWN);
2851: tst_optab = init_optab (UNKNOWN);
2852: neg_optab = init_optab (NEG);
2853: abs_optab = init_optab (ABS);
2854: one_cmpl_optab = init_optab (NOT);
2855: ffs_optab = init_optab (FFS);
1.1.1.2 root 2856: sqrt_optab = init_optab (SQRT);
1.1.1.3 ! root 2857: strlen_optab = init_optab (UNKNOWN);
1.1 root 2858:
2859: #ifdef HAVE_addqi3
2860: if (HAVE_addqi3)
2861: add_optab->handlers[(int) QImode].insn_code = CODE_FOR_addqi3;
2862: #endif
2863: #ifdef HAVE_addhi3
2864: if (HAVE_addhi3)
2865: add_optab->handlers[(int) HImode].insn_code = CODE_FOR_addhi3;
2866: #endif
2867: #ifdef HAVE_addpsi3
2868: if (HAVE_addpsi3)
2869: add_optab->handlers[(int) PSImode].insn_code = CODE_FOR_addpsi3;
2870: #endif
2871: #ifdef HAVE_addsi3
2872: if (HAVE_addsi3)
2873: add_optab->handlers[(int) SImode].insn_code = CODE_FOR_addsi3;
2874: #endif
2875: #ifdef HAVE_adddi3
2876: if (HAVE_adddi3)
2877: add_optab->handlers[(int) DImode].insn_code = CODE_FOR_adddi3;
2878: #endif
2879: #ifdef HAVE_addti3
2880: if (HAVE_addti3)
2881: add_optab->handlers[(int) TImode].insn_code = CODE_FOR_addti3;
2882: #endif
2883: #ifdef HAVE_addsf3
2884: if (HAVE_addsf3)
2885: add_optab->handlers[(int) SFmode].insn_code = CODE_FOR_addsf3;
2886: #endif
2887: #ifdef HAVE_adddf3
2888: if (HAVE_adddf3)
2889: add_optab->handlers[(int) DFmode].insn_code = CODE_FOR_adddf3;
2890: #endif
2891: #ifdef HAVE_addtf3
2892: if (HAVE_addtf3)
2893: add_optab->handlers[(int) TFmode].insn_code = CODE_FOR_addtf3;
2894: #endif
2895: add_optab->handlers[(int) SFmode].libfunc
2896: = gen_rtx (SYMBOL_REF, Pmode, "__addsf3");
2897: add_optab->handlers[(int) DFmode].libfunc
2898: = gen_rtx (SYMBOL_REF, Pmode, "__adddf3");
2899:
2900: #ifdef HAVE_subqi3
2901: if (HAVE_subqi3)
2902: sub_optab->handlers[(int) QImode].insn_code = CODE_FOR_subqi3;
2903: #endif
2904: #ifdef HAVE_subhi3
2905: if (HAVE_subhi3)
2906: sub_optab->handlers[(int) HImode].insn_code = CODE_FOR_subhi3;
2907: #endif
2908: #ifdef HAVE_subpsi3
2909: if (HAVE_subpsi3)
2910: sub_optab->handlers[(int) PSImode].insn_code = CODE_FOR_subpsi3;
2911: #endif
2912: #ifdef HAVE_subsi3
2913: if (HAVE_subsi3)
2914: sub_optab->handlers[(int) SImode].insn_code = CODE_FOR_subsi3;
2915: #endif
2916: #ifdef HAVE_subdi3
2917: if (HAVE_subdi3)
2918: sub_optab->handlers[(int) DImode].insn_code = CODE_FOR_subdi3;
2919: #endif
2920: #ifdef HAVE_subti3
2921: if (HAVE_subti3)
1.1.1.2 root 2922: sub_optab->handlers[(int) TImode].insn_code = CODE_FOR_subti3;
1.1 root 2923: #endif
2924: #ifdef HAVE_subsf3
2925: if (HAVE_subsf3)
2926: sub_optab->handlers[(int) SFmode].insn_code = CODE_FOR_subsf3;
2927: #endif
2928: #ifdef HAVE_subdf3
2929: if (HAVE_subdf3)
2930: sub_optab->handlers[(int) DFmode].insn_code = CODE_FOR_subdf3;
2931: #endif
2932: #ifdef HAVE_subtf3
2933: if (HAVE_subtf3)
2934: sub_optab->handlers[(int) TFmode].insn_code = CODE_FOR_subtf3;
2935: #endif
2936: sub_optab->handlers[(int) SFmode].libfunc
2937: = gen_rtx (SYMBOL_REF, Pmode, "__subsf3");
2938: sub_optab->handlers[(int) DFmode].libfunc
2939: = gen_rtx (SYMBOL_REF, Pmode, "__subdf3");
2940:
2941: #ifdef HAVE_mulqi3
2942: if (HAVE_mulqi3)
2943: smul_optab->handlers[(int) QImode].insn_code = CODE_FOR_mulqi3;
2944: #endif
2945: #ifdef HAVE_mulhi3
2946: if (HAVE_mulhi3)
2947: smul_optab->handlers[(int) HImode].insn_code = CODE_FOR_mulhi3;
2948: #endif
2949: #ifdef HAVE_mulpsi3
2950: if (HAVE_mulpsi3)
2951: smul_optab->handlers[(int) PSImode].insn_code = CODE_FOR_mulpsi3;
2952: #endif
2953: #ifdef HAVE_mulsi3
2954: if (HAVE_mulsi3)
2955: smul_optab->handlers[(int) SImode].insn_code = CODE_FOR_mulsi3;
2956: #endif
2957: #ifdef HAVE_muldi3
2958: if (HAVE_muldi3)
2959: smul_optab->handlers[(int) DImode].insn_code = CODE_FOR_muldi3;
2960: #endif
2961: #ifdef HAVE_multi3
2962: if (HAVE_multi3)
2963: smul_optab->handlers[(int) TImode].insn_code = CODE_FOR_multi3;
2964: #endif
2965: #ifdef HAVE_mulsf3
2966: if (HAVE_mulsf3)
2967: smul_optab->handlers[(int) SFmode].insn_code = CODE_FOR_mulsf3;
2968: #endif
2969: #ifdef HAVE_muldf3
2970: if (HAVE_muldf3)
2971: smul_optab->handlers[(int) DFmode].insn_code = CODE_FOR_muldf3;
2972: #endif
2973: #ifdef HAVE_multf3
2974: if (HAVE_multf3)
2975: smul_optab->handlers[(int) TFmode].insn_code = CODE_FOR_multf3;
2976: #endif
2977:
2978: #ifdef MULSI3_LIBCALL
2979: smul_optab->handlers[(int) SImode].libfunc
2980: = gen_rtx (SYMBOL_REF, Pmode, MULSI3_LIBCALL);
2981: #else
2982: smul_optab->handlers[(int) SImode].libfunc
2983: = gen_rtx (SYMBOL_REF, Pmode, "__mulsi3");
2984: #endif
2985: #ifdef MULDI3_LIBCALL
2986: smul_optab->handlers[(int) DImode].libfunc
2987: = gen_rtx (SYMBOL_REF, Pmode, MULDI3_LIBCALL);
2988: #else
2989: smul_optab->handlers[(int) DImode].libfunc
2990: = gen_rtx (SYMBOL_REF, Pmode, "__muldi3");
2991: #endif
2992: smul_optab->handlers[(int) SFmode].libfunc
2993: = gen_rtx (SYMBOL_REF, Pmode, "__mulsf3");
2994: smul_optab->handlers[(int) DFmode].libfunc
2995: = gen_rtx (SYMBOL_REF, Pmode, "__muldf3");
2996:
2997: #ifdef HAVE_mulqihi3
2998: if (HAVE_mulqihi3)
2999: smul_widen_optab->handlers[(int) HImode].insn_code = CODE_FOR_mulqihi3;
3000: #endif
3001: #ifdef HAVE_mulhisi3
3002: if (HAVE_mulhisi3)
3003: smul_widen_optab->handlers[(int) SImode].insn_code = CODE_FOR_mulhisi3;
3004: #endif
3005: #ifdef HAVE_mulsidi3
3006: if (HAVE_mulsidi3)
3007: smul_widen_optab->handlers[(int) DImode].insn_code = CODE_FOR_mulsidi3;
3008: #endif
3009: #ifdef HAVE_mulditi3
3010: if (HAVE_mulditi3)
3011: smul_widen_optab->handlers[(int) TImode].insn_code = CODE_FOR_mulditi3;
3012: #endif
3013:
3014: #ifdef HAVE_umulqihi3
3015: if (HAVE_umulqihi3)
3016: umul_widen_optab->handlers[(int) HImode].insn_code = CODE_FOR_umulqihi3;
3017: #endif
3018: #ifdef HAVE_umulhisi3
3019: if (HAVE_umulhisi3)
3020: umul_widen_optab->handlers[(int) SImode].insn_code = CODE_FOR_umulhisi3;
3021: #endif
3022: #ifdef HAVE_umulsidi3
3023: if (HAVE_umulsidi3)
3024: umul_widen_optab->handlers[(int) DImode].insn_code = CODE_FOR_umulsidi3;
3025: #endif
3026: #ifdef HAVE_umulditi3
3027: if (HAVE_umulditi3)
3028: umul_widen_optab->handlers[(int) TImode].insn_code = CODE_FOR_umulditi3;
3029: #endif
3030:
3031: #ifdef HAVE_divqi3
3032: if (HAVE_divqi3)
3033: sdiv_optab->handlers[(int) QImode].insn_code = CODE_FOR_divqi3;
3034: #endif
3035: #ifdef HAVE_divhi3
3036: if (HAVE_divhi3)
3037: sdiv_optab->handlers[(int) HImode].insn_code = CODE_FOR_divhi3;
3038: #endif
3039: #ifdef HAVE_divpsi3
3040: if (HAVE_divpsi3)
3041: sdiv_optab->handlers[(int) PSImode].insn_code = CODE_FOR_divpsi3;
3042: #endif
3043: #ifdef HAVE_divsi3
3044: if (HAVE_divsi3)
3045: sdiv_optab->handlers[(int) SImode].insn_code = CODE_FOR_divsi3;
3046: #endif
3047: #ifdef HAVE_divdi3
3048: if (HAVE_divdi3)
3049: sdiv_optab->handlers[(int) DImode].insn_code = CODE_FOR_divdi3;
3050: #endif
3051: #ifdef HAVE_divti3
3052: if (HAVE_divti3)
3053: sdiv_optab->handlers[(int) TImode].insn_code = CODE_FOR_divti3;
3054: #endif
3055:
3056: #ifdef DIVSI3_LIBCALL
3057: sdiv_optab->handlers[(int) SImode].libfunc
3058: = gen_rtx (SYMBOL_REF, Pmode, DIVSI3_LIBCALL);
3059: #else
3060: sdiv_optab->handlers[(int) SImode].libfunc
3061: = gen_rtx (SYMBOL_REF, Pmode, "__divsi3");
3062: #endif
3063: #ifdef DIVDI3_LIBCALL
3064: sdiv_optab->handlers[(int) DImode].libfunc
3065: = gen_rtx (SYMBOL_REF, Pmode, DIVDI3_LIBCALL);
3066: #else
3067: sdiv_optab->handlers[(int) DImode].libfunc
3068: = gen_rtx (SYMBOL_REF, Pmode, "__divdi3");
3069: #endif
3070:
3071: #ifdef HAVE_udivqi3
3072: if (HAVE_udivqi3)
3073: udiv_optab->handlers[(int) QImode].insn_code = CODE_FOR_udivqi3;
3074: #endif
3075: #ifdef HAVE_udivhi3
3076: if (HAVE_udivhi3)
3077: udiv_optab->handlers[(int) HImode].insn_code = CODE_FOR_udivhi3;
3078: #endif
3079: #ifdef HAVE_udivpsi3
3080: if (HAVE_udivpsi3)
3081: udiv_optab->handlers[(int) PSImode].insn_code = CODE_FOR_udivpsi3;
3082: #endif
3083: #ifdef HAVE_udivsi3
3084: if (HAVE_udivsi3)
3085: udiv_optab->handlers[(int) SImode].insn_code = CODE_FOR_udivsi3;
3086: #endif
3087: #ifdef HAVE_udivdi3
3088: if (HAVE_udivdi3)
3089: udiv_optab->handlers[(int) DImode].insn_code = CODE_FOR_udivdi3;
3090: #endif
3091: #ifdef HAVE_udivti3
3092: if (HAVE_udivti3)
3093: udiv_optab->handlers[(int) TImode].insn_code = CODE_FOR_udivti3;
3094: #endif
3095:
3096: #ifdef UDIVSI3_LIBCALL
3097: udiv_optab->handlers[(int) SImode].libfunc
3098: = gen_rtx (SYMBOL_REF, Pmode, UDIVSI3_LIBCALL);
3099: #else
3100: udiv_optab->handlers[(int) SImode].libfunc
3101: = gen_rtx (SYMBOL_REF, Pmode, "__udivsi3");
3102: #endif
3103: #ifdef UDIVDI3_LIBCALL
3104: udiv_optab->handlers[(int) DImode].libfunc
3105: = gen_rtx (SYMBOL_REF, Pmode, UDIVDI3_LIBCALL);
3106: #else
3107: udiv_optab->handlers[(int) DImode].libfunc
3108: = gen_rtx (SYMBOL_REF, Pmode, "__udivdi3");
3109: #endif
3110:
3111: #ifdef HAVE_divmodqi4
3112: if (HAVE_divmodqi4)
3113: sdivmod_optab->handlers[(int) QImode].insn_code = CODE_FOR_divmodqi4;
3114: #endif
3115: #ifdef HAVE_divmodhi4
3116: if (HAVE_divmodhi4)
3117: sdivmod_optab->handlers[(int) HImode].insn_code = CODE_FOR_divmodhi4;
3118: #endif
3119: #ifdef HAVE_divmodsi4
3120: if (HAVE_divmodsi4)
3121: sdivmod_optab->handlers[(int) SImode].insn_code = CODE_FOR_divmodsi4;
3122: #endif
3123: #ifdef HAVE_divmoddi4
3124: if (HAVE_divmoddi4)
3125: sdivmod_optab->handlers[(int) DImode].insn_code = CODE_FOR_divmoddi4;
3126: #endif
3127: #ifdef HAVE_divmodti4
3128: if (HAVE_divmodti4)
3129: sdivmod_optab->handlers[(int) TImode].insn_code = CODE_FOR_divmodti4;
3130: #endif
3131:
3132: #ifdef HAVE_udivmodqi4
3133: if (HAVE_udivmodqi4)
3134: udivmod_optab->handlers[(int) QImode].insn_code = CODE_FOR_udivmodqi4;
3135: #endif
3136: #ifdef HAVE_udivmodhi4
3137: if (HAVE_udivmodhi4)
3138: udivmod_optab->handlers[(int) HImode].insn_code = CODE_FOR_udivmodhi4;
3139: #endif
3140: #ifdef HAVE_udivmodsi4
3141: if (HAVE_udivmodsi4)
3142: udivmod_optab->handlers[(int) SImode].insn_code = CODE_FOR_udivmodsi4;
3143: #endif
3144: #ifdef HAVE_udivmoddi4
3145: if (HAVE_udivmoddi4)
3146: udivmod_optab->handlers[(int) DImode].insn_code = CODE_FOR_udivmoddi4;
3147: #endif
3148: #ifdef HAVE_udivmodti4
3149: if (HAVE_udivmodti4)
3150: udivmod_optab->handlers[(int) TImode].insn_code = CODE_FOR_udivmodti4;
3151: #endif
3152:
3153: #ifdef HAVE_modqi3
3154: if (HAVE_modqi3)
3155: smod_optab->handlers[(int) QImode].insn_code = CODE_FOR_modqi3;
3156: #endif
3157: #ifdef HAVE_modhi3
3158: if (HAVE_modhi3)
3159: smod_optab->handlers[(int) HImode].insn_code = CODE_FOR_modhi3;
3160: #endif
3161: #ifdef HAVE_modpsi3
3162: if (HAVE_modpsi3)
3163: smod_optab->handlers[(int) PSImode].insn_code = CODE_FOR_modpsi3;
3164: #endif
3165: #ifdef HAVE_modsi3
3166: if (HAVE_modsi3)
3167: smod_optab->handlers[(int) SImode].insn_code = CODE_FOR_modsi3;
3168: #endif
3169: #ifdef HAVE_moddi3
3170: if (HAVE_moddi3)
3171: smod_optab->handlers[(int) DImode].insn_code = CODE_FOR_moddi3;
3172: #endif
3173: #ifdef HAVE_modti3
3174: if (HAVE_modti3)
3175: smod_optab->handlers[(int) TImode].insn_code = CODE_FOR_modti3;
3176: #endif
3177:
3178: #ifdef MODSI3_LIBCALL
3179: smod_optab->handlers[(int) SImode].libfunc
3180: = gen_rtx (SYMBOL_REF, Pmode, MODSI3_LIBCALL);
3181: #else
3182: smod_optab->handlers[(int) SImode].libfunc
3183: = gen_rtx (SYMBOL_REF, Pmode, "__modsi3");
3184: #endif
3185: #ifdef MODDI3_LIBCALL
3186: smod_optab->handlers[(int) DImode].libfunc
3187: = gen_rtx (SYMBOL_REF, Pmode, MODDI3_LIBCALL);
3188: #else
3189: smod_optab->handlers[(int) DImode].libfunc
3190: = gen_rtx (SYMBOL_REF, Pmode, "__moddi3");
3191: #endif
3192:
3193: #ifdef HAVE_umodqi3
3194: if (HAVE_umodqi3)
3195: umod_optab->handlers[(int) QImode].insn_code = CODE_FOR_umodqi3;
3196: #endif
3197: #ifdef HAVE_umodhi3
3198: if (HAVE_umodhi3)
3199: umod_optab->handlers[(int) HImode].insn_code = CODE_FOR_umodhi3;
3200: #endif
3201: #ifdef HAVE_umodpsi3
3202: if (HAVE_umodpsi3)
3203: umod_optab->handlers[(int) PSImode].insn_code = CODE_FOR_umodpsi3;
3204: #endif
3205: #ifdef HAVE_umodsi3
3206: if (HAVE_umodsi3)
3207: umod_optab->handlers[(int) SImode].insn_code = CODE_FOR_umodsi3;
3208: #endif
3209: #ifdef HAVE_umoddi3
3210: if (HAVE_umoddi3)
3211: umod_optab->handlers[(int) DImode].insn_code = CODE_FOR_umoddi3;
3212: #endif
3213: #ifdef HAVE_umodti3
3214: if (HAVE_umodti3)
3215: umod_optab->handlers[(int) TImode].insn_code = CODE_FOR_umodti3;
3216: #endif
3217:
3218: #ifdef UMODSI3_LIBCALL
3219: umod_optab->handlers[(int) SImode].libfunc
3220: = gen_rtx (SYMBOL_REF, Pmode, UMODSI3_LIBCALL);
3221: #else
3222: umod_optab->handlers[(int) SImode].libfunc
3223: = gen_rtx (SYMBOL_REF, Pmode, "__umodsi3");
3224: #endif
3225: #ifdef UMODDI3_LIBCALL
3226: umod_optab->handlers[(int) DImode].libfunc
3227: = gen_rtx (SYMBOL_REF, Pmode, UMODDI3_LIBCALL);
3228: #else
3229: umod_optab->handlers[(int) DImode].libfunc
3230: = gen_rtx (SYMBOL_REF, Pmode, "__umoddi3");
3231: #endif
3232:
3233: #ifdef HAVE_divsf3
3234: if (HAVE_divsf3)
3235: flodiv_optab->handlers[(int) SFmode].insn_code = CODE_FOR_divsf3;
3236: #endif
3237: #ifdef HAVE_divdf3
3238: if (HAVE_divdf3)
3239: flodiv_optab->handlers[(int) DFmode].insn_code = CODE_FOR_divdf3;
3240: #endif
3241: #ifdef HAVE_divtf3
3242: if (HAVE_divtf3)
3243: flodiv_optab->handlers[(int) TFmode].insn_code = CODE_FOR_divtf3;
3244: #endif
3245: flodiv_optab->handlers[(int) SFmode].libfunc
3246: = gen_rtx (SYMBOL_REF, Pmode, "__divsf3");
3247: flodiv_optab->handlers[(int) DFmode].libfunc
3248: = gen_rtx (SYMBOL_REF, Pmode, "__divdf3");
3249:
3250: #ifdef HAVE_ftruncsf2
3251: if (HAVE_ftruncsf2)
3252: ftrunc_optab->handlers[(int) SFmode].insn_code = CODE_FOR_ftruncsf2;
3253: #endif
3254: #ifdef HAVE_ftruncdf2
3255: if (HAVE_ftruncdf2)
3256: ftrunc_optab->handlers[(int) DFmode].insn_code = CODE_FOR_ftruncdf2;
3257: #endif
3258: #ifdef HAVE_ftrunctf2
3259: if (HAVE_ftrunctf2)
3260: ftrunc_optab->handlers[(int) TFmode].insn_code = CODE_FOR_ftrunctf2;
3261: #endif
3262:
3263: #ifdef HAVE_andqi3
3264: if (HAVE_andqi3)
3265: and_optab->handlers[(int) QImode].insn_code = CODE_FOR_andqi3;
3266: #endif
3267: #ifdef HAVE_andhi3
3268: if (HAVE_andhi3)
3269: and_optab->handlers[(int) HImode].insn_code = CODE_FOR_andhi3;
3270: #endif
3271: #ifdef HAVE_andpsi3
3272: if (HAVE_andpsi3)
3273: and_optab->handlers[(int) PSImode].insn_code = CODE_FOR_andpsi3;
3274: #endif
3275: #ifdef HAVE_andsi3
3276: if (HAVE_andsi3)
3277: and_optab->handlers[(int) SImode].insn_code = CODE_FOR_andsi3;
3278: #endif
3279: #ifdef HAVE_anddi3
3280: if (HAVE_anddi3)
3281: and_optab->handlers[(int) DImode].insn_code = CODE_FOR_anddi3;
3282: #endif
3283: #ifdef HAVE_andti3
3284: if (HAVE_andti3)
3285: and_optab->handlers[(int) TImode].insn_code = CODE_FOR_andti3;
3286: #endif
3287:
3288: #ifdef HAVE_iorqi3
3289: if (HAVE_iorqi3)
3290: ior_optab->handlers[(int) QImode].insn_code = CODE_FOR_iorqi3;
3291: #endif
3292: #ifdef HAVE_iorhi3
3293: if (HAVE_iorhi3)
3294: ior_optab->handlers[(int) HImode].insn_code = CODE_FOR_iorhi3;
3295: #endif
3296: #ifdef HAVE_iorpsi3
3297: if (HAVE_iorpsi3)
3298: ior_optab->handlers[(int) PSImode].insn_code = CODE_FOR_iorpsi3;
3299: #endif
3300: #ifdef HAVE_iorsi3
3301: if (HAVE_iorsi3)
3302: ior_optab->handlers[(int) SImode].insn_code = CODE_FOR_iorsi3;
3303: #endif
3304: #ifdef HAVE_iordi3
3305: if (HAVE_iordi3)
3306: ior_optab->handlers[(int) DImode].insn_code = CODE_FOR_iordi3;
3307: #endif
3308: #ifdef HAVE_iorti3
3309: if (HAVE_iorti3)
3310: ior_optab->handlers[(int) TImode].insn_code = CODE_FOR_iorti3;
3311: #endif
3312:
3313: #ifdef HAVE_xorqi3
3314: if (HAVE_xorqi3)
3315: xor_optab->handlers[(int) QImode].insn_code = CODE_FOR_xorqi3;
3316: #endif
3317: #ifdef HAVE_xorhi3
3318: if (HAVE_xorhi3)
3319: xor_optab->handlers[(int) HImode].insn_code = CODE_FOR_xorhi3;
3320: #endif
3321: #ifdef HAVE_xorpsi3
3322: if (HAVE_xorpsi3)
3323: xor_optab->handlers[(int) PSImode].insn_code = CODE_FOR_xorpsi3;
3324: #endif
3325: #ifdef HAVE_xorsi3
3326: if (HAVE_xorsi3)
3327: xor_optab->handlers[(int) SImode].insn_code = CODE_FOR_xorsi3;
3328: #endif
3329: #ifdef HAVE_xordi3
3330: if (HAVE_xordi3)
3331: xor_optab->handlers[(int) DImode].insn_code = CODE_FOR_xordi3;
3332: #endif
3333: #ifdef HAVE_xorti3
3334: if (HAVE_xorti3)
3335: xor_optab->handlers[(int) TImode].insn_code = CODE_FOR_xorti3;
3336: #endif
3337:
3338: #ifdef HAVE_ashlqi3
3339: if (HAVE_ashlqi3)
3340: ashl_optab->handlers[(int) QImode].insn_code = CODE_FOR_ashlqi3;
3341: #endif
3342: #ifdef HAVE_ashlhi3
3343: if (HAVE_ashlhi3)
3344: ashl_optab->handlers[(int) HImode].insn_code = CODE_FOR_ashlhi3;
3345: #endif
3346: #ifdef HAVE_ashlpsi3
3347: if (HAVE_ashlpsi3)
3348: ashl_optab->handlers[(int) PSImode].insn_code = CODE_FOR_ashlpsi3;
3349: #endif
3350: #ifdef HAVE_ashlsi3
3351: if (HAVE_ashlsi3)
3352: ashl_optab->handlers[(int) SImode].insn_code = CODE_FOR_ashlsi3;
3353: #endif
3354: #ifdef HAVE_ashldi3
3355: if (HAVE_ashldi3)
3356: ashl_optab->handlers[(int) DImode].insn_code = CODE_FOR_ashldi3;
3357: #endif
3358: #ifdef HAVE_ashlti3
3359: if (HAVE_ashlti3)
3360: ashl_optab->handlers[(int) TImode].insn_code = CODE_FOR_ashlti3;
3361: #endif
3362: ashl_optab->handlers[(int) SImode].libfunc
3363: = gen_rtx (SYMBOL_REF, Pmode, "__ashlsi3");
3364: ashl_optab->handlers[(int) DImode].libfunc
3365: = gen_rtx (SYMBOL_REF, Pmode, "__ashldi3");
3366:
3367: #ifdef HAVE_ashrqi3
3368: if (HAVE_ashrqi3)
3369: ashr_optab->handlers[(int) QImode].insn_code = CODE_FOR_ashrqi3;
3370: #endif
3371: #ifdef HAVE_ashrhi3
3372: if (HAVE_ashrhi3)
3373: ashr_optab->handlers[(int) HImode].insn_code = CODE_FOR_ashrhi3;
3374: #endif
3375: #ifdef HAVE_ashrpsi3
3376: if (HAVE_ashrpsi3)
3377: ashr_optab->handlers[(int) PSImode].insn_code = CODE_FOR_ashrpsi3;
3378: #endif
3379: #ifdef HAVE_ashrsi3
3380: if (HAVE_ashrsi3)
3381: ashr_optab->handlers[(int) SImode].insn_code = CODE_FOR_ashrsi3;
3382: #endif
3383: #ifdef HAVE_ashrdi3
3384: if (HAVE_ashrdi3)
3385: ashr_optab->handlers[(int) DImode].insn_code = CODE_FOR_ashrdi3;
3386: #endif
3387: #ifdef HAVE_ashrti3
3388: if (HAVE_ashrti3)
3389: ashr_optab->handlers[(int) TImode].insn_code = CODE_FOR_ashrti3;
3390: #endif
3391: ashr_optab->handlers[(int) SImode].libfunc
3392: = gen_rtx (SYMBOL_REF, Pmode, "__ashrsi3");
3393: ashr_optab->handlers[(int) DImode].libfunc
3394: = gen_rtx (SYMBOL_REF, Pmode, "__ashrdi3");
3395:
3396: #ifdef HAVE_lshlqi3
3397: if (HAVE_lshlqi3)
3398: lshl_optab->handlers[(int) QImode].insn_code = CODE_FOR_lshlqi3;
3399: #endif
3400: #ifdef HAVE_lshlhi3
3401: if (HAVE_lshlhi3)
3402: lshl_optab->handlers[(int) HImode].insn_code = CODE_FOR_lshlhi3;
3403: #endif
3404: #ifdef HAVE_lshlpsi3
3405: if (HAVE_lshlpsi3)
3406: lshl_optab->handlers[(int) PSImode].insn_code = CODE_FOR_lshlpsi3;
3407: #endif
3408: #ifdef HAVE_lshlsi3
3409: if (HAVE_lshlsi3)
3410: lshl_optab->handlers[(int) SImode].insn_code = CODE_FOR_lshlsi3;
3411: #endif
3412: #ifdef HAVE_lshldi3
3413: if (HAVE_lshldi3)
3414: lshl_optab->handlers[(int) DImode].insn_code = CODE_FOR_lshldi3;
3415: #endif
3416: #ifdef HAVE_lshlti3
3417: if (HAVE_lshlti3)
3418: lshl_optab->handlers[(int) TImode].insn_code = CODE_FOR_lshlti3;
3419: #endif
3420: lshl_optab->handlers[(int) SImode].libfunc
3421: = gen_rtx (SYMBOL_REF, Pmode, "__lshlsi3");
3422: lshl_optab->handlers[(int) DImode].libfunc
3423: = gen_rtx (SYMBOL_REF, Pmode, "__lshldi3");
3424:
3425: #ifdef HAVE_lshrqi3
3426: if (HAVE_lshrqi3)
3427: lshr_optab->handlers[(int) QImode].insn_code = CODE_FOR_lshrqi3;
3428: #endif
3429: #ifdef HAVE_lshrhi3
3430: if (HAVE_lshrhi3)
3431: lshr_optab->handlers[(int) HImode].insn_code = CODE_FOR_lshrhi3;
3432: #endif
3433: #ifdef HAVE_lshrpsi3
3434: if (HAVE_lshrpsi3)
3435: lshr_optab->handlers[(int) PSImode].insn_code = CODE_FOR_lshrpsi3;
3436: #endif
3437: #ifdef HAVE_lshrsi3
3438: if (HAVE_lshrsi3)
3439: lshr_optab->handlers[(int) SImode].insn_code = CODE_FOR_lshrsi3;
3440: #endif
3441: #ifdef HAVE_lshrdi3
3442: if (HAVE_lshrdi3)
3443: lshr_optab->handlers[(int) DImode].insn_code = CODE_FOR_lshrdi3;
3444: #endif
3445: #ifdef HAVE_lshrti3
3446: if (HAVE_lshrti3)
3447: lshr_optab->handlers[(int) TImode].insn_code = CODE_FOR_lshrti3;
3448: #endif
3449: lshr_optab->handlers[(int) SImode].libfunc
3450: = gen_rtx (SYMBOL_REF, Pmode, "__lshrsi3");
3451: lshr_optab->handlers[(int) DImode].libfunc
3452: = gen_rtx (SYMBOL_REF, Pmode, "__lshrdi3");
3453:
3454: #ifdef HAVE_rotlqi3
3455: if (HAVE_rotlqi3)
3456: rotl_optab->handlers[(int) QImode].insn_code = CODE_FOR_rotlqi3;
3457: #endif
3458: #ifdef HAVE_rotlhi3
3459: if (HAVE_rotlhi3)
3460: rotl_optab->handlers[(int) HImode].insn_code = CODE_FOR_rotlhi3;
3461: #endif
3462: #ifdef HAVE_rotlpsi3
3463: if (HAVE_rotlpsi3)
3464: rotl_optab->handlers[(int) PSImode].insn_code = CODE_FOR_rotlpsi3;
3465: #endif
3466: #ifdef HAVE_rotlsi3
3467: if (HAVE_rotlsi3)
3468: rotl_optab->handlers[(int) SImode].insn_code = CODE_FOR_rotlsi3;
3469: #endif
3470: #ifdef HAVE_rotldi3
3471: if (HAVE_rotldi3)
3472: rotl_optab->handlers[(int) DImode].insn_code = CODE_FOR_rotldi3;
3473: #endif
3474: #ifdef HAVE_rotlti3
3475: if (HAVE_rotlti3)
3476: rotl_optab->handlers[(int) TImode].insn_code = CODE_FOR_rotlti3;
3477: #endif
3478: rotl_optab->handlers[(int) SImode].libfunc
3479: = gen_rtx (SYMBOL_REF, Pmode, "__rotlsi3");
3480: rotl_optab->handlers[(int) DImode].libfunc
3481: = gen_rtx (SYMBOL_REF, Pmode, "__rotldi3");
3482:
3483: #ifdef HAVE_rotrqi3
3484: if (HAVE_rotrqi3)
3485: rotr_optab->handlers[(int) QImode].insn_code = CODE_FOR_rotrqi3;
3486: #endif
3487: #ifdef HAVE_rotrhi3
3488: if (HAVE_rotrhi3)
3489: rotr_optab->handlers[(int) HImode].insn_code = CODE_FOR_rotrhi3;
3490: #endif
3491: #ifdef HAVE_rotrpsi3
3492: if (HAVE_rotrpsi3)
3493: rotr_optab->handlers[(int) PSImode].insn_code = CODE_FOR_rotrpsi3;
3494: #endif
3495: #ifdef HAVE_rotrsi3
3496: if (HAVE_rotrsi3)
3497: rotr_optab->handlers[(int) SImode].insn_code = CODE_FOR_rotrsi3;
3498: #endif
3499: #ifdef HAVE_rotrdi3
3500: if (HAVE_rotrdi3)
3501: rotr_optab->handlers[(int) DImode].insn_code = CODE_FOR_rotrdi3;
3502: #endif
3503: #ifdef HAVE_rotrti3
3504: if (HAVE_rotrti3)
3505: rotr_optab->handlers[(int) TImode].insn_code = CODE_FOR_rotrti3;
3506: #endif
3507: rotr_optab->handlers[(int) SImode].libfunc
3508: = gen_rtx (SYMBOL_REF, Pmode, "__rotrsi3");
3509: rotr_optab->handlers[(int) DImode].libfunc
3510: = gen_rtx (SYMBOL_REF, Pmode, "__rotrdi3");
3511:
3512: #ifdef HAVE_sminqi3
3513: if (HAVE_sminqi3)
3514: smin_optab->handlers[(int) QImode].insn_code = CODE_FOR_sminqi3;
3515: #endif
3516: #ifdef HAVE_sminhi3
3517: if (HAVE_sminhi3)
3518: smin_optab->handlers[(int) HImode].insn_code = CODE_FOR_sminhi3;
3519: #endif
3520: #ifdef HAVE_sminsi3
3521: if (HAVE_sminsi3)
3522: smin_optab->handlers[(int) SImode].insn_code = CODE_FOR_sminsi3;
3523: #endif
3524: #ifdef HAVE_smindi3
3525: if (HAVE_smindi3)
3526: smin_optab->handlers[(int) DImode].insn_code = CODE_FOR_smindi3;
3527: #endif
3528: #ifdef HAVE_sminti3
3529: if (HAVE_sminti3)
3530: smin_optab->handlers[(int) TImode].insn_code = CODE_FOR_sminti3;
3531: #endif
3532: #ifdef HAVE_sminsf3
3533: if (HAVE_sminsf3)
3534: smin_optab->handlers[(int) SFmode].insn_code = CODE_FOR_sminsf3;
3535: #endif
3536: #ifdef HAVE_smindf3
3537: if (HAVE_smindf3)
3538: smin_optab->handlers[(int) DFmode].insn_code = CODE_FOR_smindf3;
3539: #endif
3540: #ifdef HAVE_smintf3
3541: if (HAVE_smintf3)
3542: smin_optab->handlers[(int) TFmode].insn_code = CODE_FOR_smintf3;
3543: #endif
3544:
3545: #ifdef HAVE_smaxqi3
3546: if (HAVE_smaxqi3)
3547: smax_optab->handlers[(int) QImode].insn_code = CODE_FOR_smaxqi3;
3548: #endif
3549: #ifdef HAVE_smaxhi3
3550: if (HAVE_smaxhi3)
3551: smax_optab->handlers[(int) HImode].insn_code = CODE_FOR_smaxhi3;
3552: #endif
3553: #ifdef HAVE_smaxsi3
3554: if (HAVE_smaxsi3)
3555: smax_optab->handlers[(int) SImode].insn_code = CODE_FOR_smaxsi3;
3556: #endif
3557: #ifdef HAVE_smaxdi3
3558: if (HAVE_smaxdi3)
3559: smax_optab->handlers[(int) DImode].insn_code = CODE_FOR_smaxdi3;
3560: #endif
3561: #ifdef HAVE_smaxti3
3562: if (HAVE_smaxti3)
3563: smax_optab->handlers[(int) TImode].insn_code = CODE_FOR_smaxti3;
3564: #endif
3565: #ifdef HAVE_smaxsf3
3566: if (HAVE_smaxsf3)
3567: smax_optab->handlers[(int) SFmode].insn_code = CODE_FOR_smaxsf3;
3568: #endif
3569: #ifdef HAVE_smaxdf3
3570: if (HAVE_smaxdf3)
3571: smax_optab->handlers[(int) DFmode].insn_code = CODE_FOR_smaxdf3;
3572: #endif
3573: #ifdef HAVE_smaxtf3
3574: if (HAVE_smaxtf3)
3575: smax_optab->handlers[(int) TFmode].insn_code = CODE_FOR_smaxtf3;
3576: #endif
3577:
3578: #ifdef HAVE_uminqi3
3579: if (HAVE_uminqi3)
3580: umin_optab->handlers[(int) QImode].insn_code = CODE_FOR_uminqi3;
3581: #endif
3582: #ifdef HAVE_uminhi3
3583: if (HAVE_uminhi3)
3584: umin_optab->handlers[(int) HImode].insn_code = CODE_FOR_uminhi3;
3585: #endif
3586: #ifdef HAVE_uminsi3
3587: if (HAVE_uminsi3)
3588: umin_optab->handlers[(int) SImode].insn_code = CODE_FOR_uminsi3;
3589: #endif
3590: #ifdef HAVE_umindi3
3591: if (HAVE_umindi3)
3592: umin_optab->handlers[(int) DImode].insn_code = CODE_FOR_umindi3;
3593: #endif
3594: #ifdef HAVE_uminti3
3595: if (HAVE_uminti3)
3596: umin_optab->handlers[(int) TImode].insn_code = CODE_FOR_uminti3;
3597: #endif
3598:
3599: #ifdef HAVE_umaxqi3
3600: if (HAVE_umaxqi3)
3601: umax_optab->handlers[(int) QImode].insn_code = CODE_FOR_umaxqi3;
3602: #endif
3603: #ifdef HAVE_umaxhi3
3604: if (HAVE_umaxhi3)
3605: umax_optab->handlers[(int) HImode].insn_code = CODE_FOR_umaxhi3;
3606: #endif
3607: #ifdef HAVE_umaxsi3
3608: if (HAVE_umaxsi3)
3609: umax_optab->handlers[(int) SImode].insn_code = CODE_FOR_umaxsi3;
3610: #endif
3611: #ifdef HAVE_umaxdi3
3612: if (HAVE_umaxdi3)
3613: umax_optab->handlers[(int) DImode].insn_code = CODE_FOR_umaxdi3;
3614: #endif
3615: #ifdef HAVE_umaxti3
3616: if (HAVE_umaxti3)
3617: umax_optab->handlers[(int) TImode].insn_code = CODE_FOR_umaxti3;
3618: #endif
3619:
3620: #ifdef HAVE_negqi2
3621: if (HAVE_negqi2)
3622: neg_optab->handlers[(int) QImode].insn_code = CODE_FOR_negqi2;
3623: #endif
3624: #ifdef HAVE_neghi2
3625: if (HAVE_neghi2)
3626: neg_optab->handlers[(int) HImode].insn_code = CODE_FOR_neghi2;
3627: #endif
3628: #ifdef HAVE_negpsi2
3629: if (HAVE_negpsi2)
3630: neg_optab->handlers[(int) PSImode].insn_code = CODE_FOR_negpsi2;
3631: #endif
3632: #ifdef HAVE_negsi2
3633: if (HAVE_negsi2)
3634: neg_optab->handlers[(int) SImode].insn_code = CODE_FOR_negsi2;
3635: #endif
3636: #ifdef HAVE_negdi2
3637: if (HAVE_negdi2)
3638: neg_optab->handlers[(int) DImode].insn_code = CODE_FOR_negdi2;
3639: #endif
3640: #ifdef HAVE_negti2
3641: if (HAVE_negti2)
3642: neg_optab->handlers[(int) TImode].insn_code = CODE_FOR_negti2;
3643: #endif
3644: #ifdef HAVE_negsf2
3645: if (HAVE_negsf2)
3646: neg_optab->handlers[(int) SFmode].insn_code = CODE_FOR_negsf2;
3647: #endif
3648: #ifdef HAVE_negdf2
3649: if (HAVE_negdf2)
3650: neg_optab->handlers[(int) DFmode].insn_code = CODE_FOR_negdf2;
3651: #endif
3652: #ifdef HAVE_negtf2
3653: if (HAVE_negtf2)
3654: neg_optab->handlers[(int) TFmode].insn_code = CODE_FOR_negtf2;
3655: #endif
3656: neg_optab->handlers[(int) SImode].libfunc
3657: = gen_rtx (SYMBOL_REF, Pmode, "__negsi2");
3658: neg_optab->handlers[(int) DImode].libfunc
3659: = gen_rtx (SYMBOL_REF, Pmode, "__negdi2");
3660: neg_optab->handlers[(int) SFmode].libfunc
3661: = gen_rtx (SYMBOL_REF, Pmode, "__negsf2");
3662: neg_optab->handlers[(int) DFmode].libfunc
3663: = gen_rtx (SYMBOL_REF, Pmode, "__negdf2");
3664:
3665: #ifdef HAVE_absqi2
3666: if (HAVE_absqi2)
3667: abs_optab->handlers[(int) QImode].insn_code = CODE_FOR_absqi2;
3668: #endif
3669: #ifdef HAVE_abshi2
3670: if (HAVE_abshi2)
3671: abs_optab->handlers[(int) HImode].insn_code = CODE_FOR_abshi2;
3672: #endif
3673: #ifdef HAVE_abspsi2
3674: if (HAVE_abspsi2)
3675: abs_optab->handlers[(int) PSImode].insn_code = CODE_FOR_abspsi2;
3676: #endif
3677: #ifdef HAVE_abssi2
3678: if (HAVE_abssi2)
3679: abs_optab->handlers[(int) SImode].insn_code = CODE_FOR_abssi2;
3680: #endif
3681: #ifdef HAVE_absdi2
3682: if (HAVE_absdi2)
3683: abs_optab->handlers[(int) DImode].insn_code = CODE_FOR_absdi2;
3684: #endif
3685: #ifdef HAVE_absti2
3686: if (HAVE_absti2)
3687: abs_optab->handlers[(int) TImode].insn_code = CODE_FOR_absti2;
3688: #endif
3689: #ifdef HAVE_abssf2
3690: if (HAVE_abssf2)
3691: abs_optab->handlers[(int) SFmode].insn_code = CODE_FOR_abssf2;
3692: #endif
3693: #ifdef HAVE_absdf2
3694: if (HAVE_absdf2)
3695: abs_optab->handlers[(int) DFmode].insn_code = CODE_FOR_absdf2;
3696: #endif
3697: #ifdef HAVE_abstf2
3698: if (HAVE_abstf2)
3699: abs_optab->handlers[(int) TFmode].insn_code = CODE_FOR_abstf2;
3700: #endif
3701: /* No library calls here! If there is no abs instruction,
3702: expand_expr will generate a conditional negation. */
3703:
1.1.1.2 root 3704: #ifdef HAVE_sqrtqi2
3705: if (HAVE_sqrtqi2)
3706: sqrt_optab->handlers[(int) QImode].insn_code = CODE_FOR_sqrtqi2;
3707: #endif
3708: #ifdef HAVE_sqrthi2
3709: if (HAVE_sqrthi2)
3710: sqrt_optab->handlers[(int) HImode].insn_code = CODE_FOR_sqrthi2;
3711: #endif
3712: #ifdef HAVE_sqrtpsi2
3713: if (HAVE_sqrtpsi2)
3714: sqrt_optab->handlers[(int) PSImode].insn_code = CODE_FOR_sqrtpsi2;
3715: #endif
3716: #ifdef HAVE_sqrtsi2
3717: if (HAVE_sqrtsi2)
3718: sqrt_optab->handlers[(int) SImode].insn_code = CODE_FOR_sqrtsi2;
3719: #endif
3720: #ifdef HAVE_sqrtdi2
3721: if (HAVE_sqrtdi2)
3722: sqrt_optab->handlers[(int) DImode].insn_code = CODE_FOR_sqrtdi2;
3723: #endif
3724: #ifdef HAVE_sqrtti2
3725: if (HAVE_sqrtti2)
3726: sqrt_optab->handlers[(int) TImode].insn_code = CODE_FOR_sqrtti2;
3727: #endif
3728: #ifdef HAVE_sqrtsf2
3729: if (HAVE_sqrtsf2)
3730: sqrt_optab->handlers[(int) SFmode].insn_code = CODE_FOR_sqrtsf2;
3731: #endif
3732: #ifdef HAVE_sqrtdf2
3733: if (HAVE_sqrtdf2)
3734: sqrt_optab->handlers[(int) DFmode].insn_code = CODE_FOR_sqrtdf2;
3735: #endif
3736: #ifdef HAVE_sqrttf2
3737: if (HAVE_sqrttf2)
3738: sqrt_optab->handlers[(int) TFmode].insn_code = CODE_FOR_sqrttf2;
3739: #endif
3740: /* No library calls here! If there is no sqrt instruction expand_builtin
3741: should force the library call. */
3742:
1.1.1.3 ! root 3743: #ifdef HAVE_strlenqi
! 3744: if (HAVE_strlenqi)
! 3745: strlen_optab->handlers[(int) QImode].insn_code = CODE_FOR_strlenqi;
! 3746: #endif
! 3747: #ifdef HAVE_strlenhi
! 3748: if (HAVE_strlenhi)
! 3749: strlen_optab->handlers[(int) HImode].insn_code = CODE_FOR_strlenhi;
! 3750: #endif
! 3751: #ifdef HAVE_strlenpsi
! 3752: if (HAVE_strlenpsi)
! 3753: strlen_optab->handlers[(int) PSImode].insn_code = CODE_FOR_strlenpsi;
! 3754: #endif
! 3755: #ifdef HAVE_strlensi
! 3756: if (HAVE_strlensi)
! 3757: strlen_optab->handlers[(int) SImode].insn_code = CODE_FOR_strlensi;
! 3758: #endif
! 3759: #ifdef HAVE_strlendi
! 3760: if (HAVE_strlendi)
! 3761: strlen_optab->handlers[(int) DImode].insn_code = CODE_FOR_strlendi;
! 3762: #endif
! 3763: #ifdef HAVE_strlenti
! 3764: if (HAVE_strlenti)
! 3765: strlen_optab->handlers[(int) TImode].insn_code = CODE_FOR_strlenti;
! 3766: #endif
! 3767: /* No library calls here! If there is no strlen instruction expand_builtin
! 3768: should force the library call. */
! 3769:
1.1 root 3770: #ifdef HAVE_one_cmplqi2
3771: if (HAVE_one_cmplqi2)
3772: one_cmpl_optab->handlers[(int) QImode].insn_code = CODE_FOR_one_cmplqi2;
3773: #endif
3774: #ifdef HAVE_one_cmplhi2
3775: if (HAVE_one_cmplhi2)
3776: one_cmpl_optab->handlers[(int) HImode].insn_code = CODE_FOR_one_cmplhi2;
3777: #endif
3778: #ifdef HAVE_one_cmplpsi2
3779: if (HAVE_one_cmplpsi2)
3780: one_cmpl_optab->handlers[(int) PSImode].insn_code = CODE_FOR_one_cmplpsi2;
3781: #endif
3782: #ifdef HAVE_one_cmplsi2
3783: if (HAVE_one_cmplsi2)
3784: one_cmpl_optab->handlers[(int) SImode].insn_code = CODE_FOR_one_cmplsi2;
3785: #endif
3786: #ifdef HAVE_one_cmpldi2
3787: if (HAVE_one_cmpldi2)
3788: one_cmpl_optab->handlers[(int) DImode].insn_code = CODE_FOR_one_cmpldi2;
3789: #endif
3790: #ifdef HAVE_one_cmplti2
3791: if (HAVE_one_cmplti2)
3792: one_cmpl_optab->handlers[(int) TImode].insn_code = CODE_FOR_one_cmplti2;
3793: #endif
3794: one_cmpl_optab->handlers[(int) SImode].libfunc
3795: = gen_rtx (SYMBOL_REF, Pmode, "__one_cmplsi2");
3796:
3797: #ifdef HAVE_ffsqi2
3798: if (HAVE_ffsqi2)
3799: ffs_optab->handlers[(int) QImode].insn_code = CODE_FOR_ffsqi2;
3800: #endif
3801: #ifdef HAVE_ffshi2
3802: if (HAVE_ffshi2)
3803: ffs_optab->handlers[(int) HImode].insn_code = CODE_FOR_ffshi2;
3804: #endif
3805: #ifdef HAVE_ffspsi2
3806: if (HAVE_ffspsi2)
3807: ffs_optab->handlers[(int) PSImode].insn_code = CODE_FOR_ffspsi2;
3808: #endif
3809: #ifdef HAVE_ffssi2
3810: if (HAVE_ffssi2)
3811: ffs_optab->handlers[(int) SImode].insn_code = CODE_FOR_ffssi2;
3812: #endif
3813: #ifdef HAVE_ffsdi2
3814: if (HAVE_ffsdi2)
3815: ffs_optab->handlers[(int) DImode].insn_code = CODE_FOR_ffsdi2;
3816: #endif
3817: #ifdef HAVE_ffsti2
3818: if (HAVE_ffsti2)
3819: ffs_optab->handlers[(int) TImode].insn_code = CODE_FOR_ffsti2;
3820: #endif
3821: ffs_optab->handlers[(int) SImode].libfunc
3822: = gen_rtx (SYMBOL_REF, Pmode, "ffs");
3823:
3824: #ifdef HAVE_movqi
3825: if (HAVE_movqi)
3826: mov_optab->handlers[(int) QImode].insn_code = CODE_FOR_movqi;
3827: #endif
3828: #ifdef HAVE_movhi
3829: if (HAVE_movhi)
3830: mov_optab->handlers[(int) HImode].insn_code = CODE_FOR_movhi;
3831: #endif
3832: #ifdef HAVE_movpsi
3833: if (HAVE_movpsi)
3834: mov_optab->handlers[(int) PSImode].insn_code = CODE_FOR_movpsi;
3835: #endif
3836: #ifdef HAVE_movsi
3837: if (HAVE_movsi)
3838: mov_optab->handlers[(int) SImode].insn_code = CODE_FOR_movsi;
3839: #endif
3840: #ifdef HAVE_movdi
3841: if (HAVE_movdi)
3842: mov_optab->handlers[(int) DImode].insn_code = CODE_FOR_movdi;
3843: #endif
3844: #ifdef HAVE_movti
3845: if (HAVE_movti)
3846: mov_optab->handlers[(int) TImode].insn_code = CODE_FOR_movti;
3847: #endif
3848: #ifdef HAVE_movsf
3849: if (HAVE_movsf)
3850: mov_optab->handlers[(int) SFmode].insn_code = CODE_FOR_movsf;
3851: #endif
3852: #ifdef HAVE_movdf
3853: if (HAVE_movdf)
3854: mov_optab->handlers[(int) DFmode].insn_code = CODE_FOR_movdf;
3855: #endif
3856: #ifdef HAVE_movtf
3857: if (HAVE_movtf)
3858: mov_optab->handlers[(int) TFmode].insn_code = CODE_FOR_movtf;
3859: #endif
3860: #ifdef HAVE_movcc
3861: if (HAVE_movcc)
3862: mov_optab->handlers[(int) CCmode].insn_code = CODE_FOR_movcc;
3863: #endif
3864:
3865: #ifdef EXTRA_CC_MODES
3866: init_mov_optab ();
3867: #endif
3868:
3869: #ifdef HAVE_movstrictqi
3870: if (HAVE_movstrictqi)
3871: movstrict_optab->handlers[(int) QImode].insn_code = CODE_FOR_movstrictqi;
3872: #endif
3873: #ifdef HAVE_movstricthi
3874: if (HAVE_movstricthi)
3875: movstrict_optab->handlers[(int) HImode].insn_code = CODE_FOR_movstricthi;
3876: #endif
3877: #ifdef HAVE_movstrictpsi
3878: if (HAVE_movstrictpsi)
3879: movstrict_optab->handlers[(int) PSImode].insn_code = CODE_FOR_movstrictpsi;
3880: #endif
3881: #ifdef HAVE_movstrictsi
3882: if (HAVE_movstrictsi)
3883: movstrict_optab->handlers[(int) SImode].insn_code = CODE_FOR_movstrictsi;
3884: #endif
3885: #ifdef HAVE_movstrictdi
3886: if (HAVE_movstrictdi)
3887: movstrict_optab->handlers[(int) DImode].insn_code = CODE_FOR_movstrictdi;
3888: #endif
3889: #ifdef HAVE_movstrictti
3890: if (HAVE_movstrictti)
3891: movstrict_optab->handlers[(int) TImode].insn_code = CODE_FOR_movstrictti;
3892: #endif
3893:
3894: #ifdef HAVE_cmpqi
3895: if (HAVE_cmpqi)
3896: cmp_optab->handlers[(int) QImode].insn_code = CODE_FOR_cmpqi;
3897: #endif
3898: #ifdef HAVE_cmphi
3899: if (HAVE_cmphi)
3900: cmp_optab->handlers[(int) HImode].insn_code = CODE_FOR_cmphi;
3901: #endif
3902: #ifdef HAVE_cmppsi
3903: if (HAVE_cmppsi)
3904: cmp_optab->handlers[(int) PSImode].insn_code = CODE_FOR_cmppsi;
3905: #endif
3906: #ifdef HAVE_cmpsi
3907: if (HAVE_cmpsi)
3908: cmp_optab->handlers[(int) SImode].insn_code = CODE_FOR_cmpsi;
3909: #endif
3910: #ifdef HAVE_cmpdi
3911: if (HAVE_cmpdi)
3912: cmp_optab->handlers[(int) DImode].insn_code = CODE_FOR_cmpdi;
3913: #endif
3914: #ifdef HAVE_cmpti
3915: if (HAVE_cmpti)
3916: cmp_optab->handlers[(int) TImode].insn_code = CODE_FOR_cmpti;
3917: #endif
3918: #ifdef HAVE_cmpsf
3919: if (HAVE_cmpsf)
3920: cmp_optab->handlers[(int) SFmode].insn_code = CODE_FOR_cmpsf;
3921: #endif
3922: #ifdef HAVE_cmpdf
3923: if (HAVE_cmpdf)
3924: cmp_optab->handlers[(int) DFmode].insn_code = CODE_FOR_cmpdf;
3925: #endif
3926: #ifdef HAVE_cmptf
3927: if (HAVE_cmptf)
3928: cmp_optab->handlers[(int) TFmode].insn_code = CODE_FOR_cmptf;
3929: #endif
3930: #ifdef HAVE_tstqi
3931: if (HAVE_tstqi)
3932: tst_optab->handlers[(int) QImode].insn_code = CODE_FOR_tstqi;
3933: #endif
3934: #ifdef HAVE_tsthi
3935: if (HAVE_tsthi)
3936: tst_optab->handlers[(int) HImode].insn_code = CODE_FOR_tsthi;
3937: #endif
3938: #ifdef HAVE_tstpsi
3939: if (HAVE_tstpsi)
3940: tst_optab->handlers[(int) PSImode].insn_code = CODE_FOR_tstpsi;
3941: #endif
3942: #ifdef HAVE_tstsi
3943: if (HAVE_tstsi)
3944: tst_optab->handlers[(int) SImode].insn_code = CODE_FOR_tstsi;
3945: #endif
3946: #ifdef HAVE_tstdi
3947: if (HAVE_tstdi)
3948: tst_optab->handlers[(int) DImode].insn_code = CODE_FOR_tstdi;
3949: #endif
3950: #ifdef HAVE_tstti
3951: if (HAVE_tstti)
3952: tst_optab->handlers[(int) TImode].insn_code = CODE_FOR_tstti;
3953: #endif
3954: #ifdef HAVE_tstsf
3955: if (HAVE_tstsf)
3956: tst_optab->handlers[(int) SFmode].insn_code = CODE_FOR_tstsf;
3957: #endif
3958: #ifdef HAVE_tstdf
3959: if (HAVE_tstdf)
3960: tst_optab->handlers[(int) DFmode].insn_code = CODE_FOR_tstdf;
3961: #endif
3962: #ifdef HAVE_tsttf
3963: if (HAVE_tsttf)
3964: tst_optab->handlers[(int) TFmode].insn_code = CODE_FOR_tsttf;
3965: #endif
3966: /* Comparison libcalls for integers MUST come in pairs, signed/unsigned. */
3967: cmp_optab->handlers[(int) DImode].libfunc
3968: = gen_rtx (SYMBOL_REF, Pmode, "__cmpdi2");
3969: ucmp_optab->handlers[(int) DImode].libfunc
3970: = gen_rtx (SYMBOL_REF, Pmode, "__ucmpdi2");
3971:
3972: #ifdef HAVE_beq
3973: if (HAVE_beq)
3974: bcc_gen_fctn[(int) EQ] = gen_beq;
3975: #endif
3976: #ifdef HAVE_bne
3977: if (HAVE_bne)
3978: bcc_gen_fctn[(int) NE] = gen_bne;
3979: #endif
3980: #ifdef HAVE_bgt
3981: if (HAVE_bgt)
3982: bcc_gen_fctn[(int) GT] = gen_bgt;
3983: #endif
3984: #ifdef HAVE_bge
3985: if (HAVE_bge)
3986: bcc_gen_fctn[(int) GE] = gen_bge;
3987: #endif
3988: #ifdef HAVE_bgtu
3989: if (HAVE_bgtu)
3990: bcc_gen_fctn[(int) GTU] = gen_bgtu;
3991: #endif
3992: #ifdef HAVE_bgeu
3993: if (HAVE_bgeu)
3994: bcc_gen_fctn[(int) GEU] = gen_bgeu;
3995: #endif
3996: #ifdef HAVE_blt
3997: if (HAVE_blt)
3998: bcc_gen_fctn[(int) LT] = gen_blt;
3999: #endif
4000: #ifdef HAVE_ble
4001: if (HAVE_ble)
4002: bcc_gen_fctn[(int) LE] = gen_ble;
4003: #endif
4004: #ifdef HAVE_bltu
4005: if (HAVE_bltu)
4006: bcc_gen_fctn[(int) LTU] = gen_bltu;
4007: #endif
4008: #ifdef HAVE_bleu
4009: if (HAVE_bleu)
4010: bcc_gen_fctn[(int) LEU] = gen_bleu;
4011: #endif
4012:
4013: for (i = 0; i < NUM_RTX_CODE; i++)
4014: setcc_gen_code[i] = CODE_FOR_nothing;
4015:
4016: #ifdef HAVE_seq
4017: if (HAVE_seq)
4018: setcc_gen_code[(int) EQ] = CODE_FOR_seq;
4019: #endif
4020: #ifdef HAVE_sne
4021: if (HAVE_sne)
4022: setcc_gen_code[(int) NE] = CODE_FOR_sne;
4023: #endif
4024: #ifdef HAVE_sgt
4025: if (HAVE_sgt)
4026: setcc_gen_code[(int) GT] = CODE_FOR_sgt;
4027: #endif
4028: #ifdef HAVE_sge
4029: if (HAVE_sge)
4030: setcc_gen_code[(int) GE] = CODE_FOR_sge;
4031: #endif
4032: #ifdef HAVE_sgtu
4033: if (HAVE_sgtu)
4034: setcc_gen_code[(int) GTU] = CODE_FOR_sgtu;
4035: #endif
4036: #ifdef HAVE_sgeu
4037: if (HAVE_sgeu)
4038: setcc_gen_code[(int) GEU] = CODE_FOR_sgeu;
4039: #endif
4040: #ifdef HAVE_slt
4041: if (HAVE_slt)
4042: setcc_gen_code[(int) LT] = CODE_FOR_slt;
4043: #endif
4044: #ifdef HAVE_sle
4045: if (HAVE_sle)
4046: setcc_gen_code[(int) LE] = CODE_FOR_sle;
4047: #endif
4048: #ifdef HAVE_sltu
4049: if (HAVE_sltu)
4050: setcc_gen_code[(int) LTU] = CODE_FOR_sltu;
4051: #endif
4052: #ifdef HAVE_sleu
4053: if (HAVE_sleu)
4054: setcc_gen_code[(int) LEU] = CODE_FOR_sleu;
4055: #endif
4056:
4057: extendsfdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extendsfdf2");
4058: truncdfsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__truncdfsf2");
4059: memcpy_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memcpy");
4060: bcopy_libfunc = gen_rtx (SYMBOL_REF, Pmode, "bcopy");
4061: memcmp_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memcmp");
4062: bcmp_libfunc = gen_rtx (SYMBOL_REF, Pmode, "bcmp");
4063: memset_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memset");
4064: bzero_libfunc = gen_rtx (SYMBOL_REF, Pmode, "bzero");
4065: eqsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqsf2");
4066: nesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nesf2");
4067: gtsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gtsf2");
4068: gesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gesf2");
4069: ltsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ltsf2");
4070: lesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__lesf2");
4071: eqdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqdf2");
4072: nedf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nedf2");
4073: gtdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gtdf2");
4074: gedf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gedf2");
4075: ltdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ltdf2");
4076: ledf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ledf2");
4077: floatdisf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatdisf");
4078: floatsisf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsisf");
4079: floatdidf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatdidf");
4080: floatsidf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsidf");
4081: fixsfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixsfsi");
4082: fixsfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixsfdi");
4083: fixdfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixdfsi");
4084: fixdfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixdfdi");
4085: fixunssfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunssfsi");
4086: fixunssfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunssfdi");
4087: fixunsdfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsdfsi");
4088: fixunsdfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsdfdi");
4089: }
1.1.1.2 root 4090:
4091: #ifdef BROKEN_LDEXP
4092:
4093: /* SCO 3.2 apparently has a broken ldexp. */
4094:
4095: double
4096: ldexp(x,n)
4097: double x;
4098: int n;
4099: {
4100: if (n > 0)
4101: while (n--)
4102: x *= 2;
4103:
4104: return x;
4105: }
4106: #endif /* BROKEN_LDEXP */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.