|
|
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"
1.1.1.4 ! root 30: #include <ctype.h>
1.1 root 31:
32: /* Each optab contains info on how this target machine
33: can perform a particular operation
34: for all sizes and kinds of operands.
35:
36: The operation to be performed is often specified
37: by passing one of these optabs as an argument.
38:
39: See expr.h for documentation of these optabs. */
40:
41: optab add_optab;
42: optab sub_optab;
43: optab smul_optab;
44: optab smul_widen_optab;
45: optab umul_widen_optab;
46: optab sdiv_optab;
47: optab sdivmod_optab;
48: optab udiv_optab;
49: optab udivmod_optab;
50: optab smod_optab;
51: optab umod_optab;
52: optab flodiv_optab;
53: optab ftrunc_optab;
54: optab and_optab;
55: optab ior_optab;
56: optab xor_optab;
57: optab ashl_optab;
58: optab lshr_optab;
59: optab lshl_optab;
60: optab ashr_optab;
61: optab rotl_optab;
62: optab rotr_optab;
63: optab smin_optab;
64: optab smax_optab;
65: optab umin_optab;
66: optab umax_optab;
67:
68: optab mov_optab;
69: optab movstrict_optab;
70:
71: optab neg_optab;
72: optab abs_optab;
73: optab one_cmpl_optab;
74: optab ffs_optab;
1.1.1.2 root 75: optab sqrt_optab;
1.1.1.4 ! root 76: optab sin_optab;
! 77: optab cos_optab;
1.1 root 78:
79: optab cmp_optab;
80: optab ucmp_optab; /* Used only for libcalls for unsigned comparisons. */
81: optab tst_optab;
82:
1.1.1.3 root 83: optab strlen_optab;
84:
1.1 root 85: /* SYMBOL_REF rtx's for the library functions that are called
86: implicitly and not via optabs. */
87:
88: rtx extendsfdf2_libfunc;
1.1.1.4 ! root 89: rtx extendsfxf2_libfunc;
! 90: rtx extendsftf2_libfunc;
! 91: rtx extenddfxf2_libfunc;
! 92: rtx extenddftf2_libfunc;
! 93:
1.1 root 94: rtx truncdfsf2_libfunc;
1.1.1.4 ! root 95: rtx truncxfsf2_libfunc;
! 96: rtx trunctfsf2_libfunc;
! 97: rtx truncxfdf2_libfunc;
! 98: rtx trunctfdf2_libfunc;
! 99:
1.1 root 100: rtx memcpy_libfunc;
101: rtx bcopy_libfunc;
102: rtx memcmp_libfunc;
103: rtx bcmp_libfunc;
104: rtx memset_libfunc;
105: rtx bzero_libfunc;
1.1.1.4 ! root 106:
1.1 root 107: rtx eqsf2_libfunc;
108: rtx nesf2_libfunc;
109: rtx gtsf2_libfunc;
110: rtx gesf2_libfunc;
111: rtx ltsf2_libfunc;
112: rtx lesf2_libfunc;
1.1.1.4 ! root 113:
1.1 root 114: rtx eqdf2_libfunc;
115: rtx nedf2_libfunc;
116: rtx gtdf2_libfunc;
117: rtx gedf2_libfunc;
118: rtx ltdf2_libfunc;
119: rtx ledf2_libfunc;
1.1.1.4 ! root 120:
! 121: rtx eqxf2_libfunc;
! 122: rtx nexf2_libfunc;
! 123: rtx gtxf2_libfunc;
! 124: rtx gexf2_libfunc;
! 125: rtx ltxf2_libfunc;
! 126: rtx lexf2_libfunc;
! 127:
! 128: rtx eqtf2_libfunc;
! 129: rtx netf2_libfunc;
! 130: rtx gttf2_libfunc;
! 131: rtx getf2_libfunc;
! 132: rtx lttf2_libfunc;
! 133: rtx letf2_libfunc;
! 134:
1.1 root 135: rtx floatsisf_libfunc;
1.1.1.4 ! root 136: rtx floatdisf_libfunc;
! 137: rtx floattisf_libfunc;
! 138:
1.1 root 139: rtx floatsidf_libfunc;
1.1.1.4 ! root 140: rtx floatdidf_libfunc;
! 141: rtx floattidf_libfunc;
! 142:
! 143: rtx floatsixf_libfunc;
! 144: rtx floatdixf_libfunc;
! 145: rtx floattixf_libfunc;
! 146:
! 147: rtx floatsitf_libfunc;
! 148: rtx floatditf_libfunc;
! 149: rtx floattitf_libfunc;
! 150:
1.1 root 151: rtx fixsfsi_libfunc;
152: rtx fixsfdi_libfunc;
1.1.1.4 ! root 153: rtx fixsfti_libfunc;
! 154:
1.1 root 155: rtx fixdfsi_libfunc;
156: rtx fixdfdi_libfunc;
1.1.1.4 ! root 157: rtx fixdfti_libfunc;
! 158:
! 159: rtx fixxfsi_libfunc;
! 160: rtx fixxfdi_libfunc;
! 161: rtx fixxfti_libfunc;
! 162:
! 163: rtx fixtfsi_libfunc;
! 164: rtx fixtfdi_libfunc;
! 165: rtx fixtfti_libfunc;
! 166:
1.1 root 167: rtx fixunssfsi_libfunc;
168: rtx fixunssfdi_libfunc;
1.1.1.4 ! root 169: rtx fixunssfti_libfunc;
! 170:
1.1 root 171: rtx fixunsdfsi_libfunc;
172: rtx fixunsdfdi_libfunc;
1.1.1.4 ! root 173: rtx fixunsdfti_libfunc;
! 174:
! 175: rtx fixunsxfsi_libfunc;
! 176: rtx fixunsxfdi_libfunc;
! 177: rtx fixunsxfti_libfunc;
! 178:
! 179: rtx fixunstfsi_libfunc;
! 180: rtx fixunstfdi_libfunc;
! 181: rtx fixunstfti_libfunc;
! 182:
! 183: /* from emit-rtl.c */
! 184: extern rtx gen_highpart ();
1.1 root 185:
186: /* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
187: gives the gen_function to make a branch to test that condition. */
188:
189: rtxfun bcc_gen_fctn[NUM_RTX_CODE];
190:
191: /* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
192: gives the insn code to make a store-condition insn
193: to test that condition. */
194:
195: enum insn_code setcc_gen_code[NUM_RTX_CODE];
196:
197: static void emit_float_lib_cmp ();
198:
199: /* Add a REG_EQUAL note to the last insn in SEQ. TARGET is being set to
200: the result of operation CODE applied to OP0 (and OP1 if it is a binary
201: operation).
202:
203: If the last insn does not set TARGET, don't do anything, but return 1.
204:
205: If a previous insn sets TARGET and TARGET is one of OP0 or OP1,
206: don't add the REG_EQUAL note but return 0. Our caller can then try
207: again, ensuring that TARGET is not one of the operands. */
208:
209: static int
210: add_equal_note (seq, target, code, op0, op1)
211: rtx seq;
212: rtx target;
213: enum rtx_code code;
214: rtx op0, op1;
215: {
216: rtx set;
217: int i;
218: rtx note;
219:
220: if ((GET_RTX_CLASS (code) != '1' && GET_RTX_CLASS (code) != '2'
221: && GET_RTX_CLASS (code) != 'c' && GET_RTX_CLASS (code) != '<')
222: || GET_CODE (seq) != SEQUENCE
223: || (set = single_set (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1))) == 0
224: || GET_CODE (target) == ZERO_EXTRACT
225: || (! rtx_equal_p (SET_DEST (set), target)
226: /* For a STRICT_LOW_PART, the REG_NOTE applies to what is inside the
227: SUBREG. */
228: && (GET_CODE (SET_DEST (set)) != STRICT_LOW_PART
229: || ! rtx_equal_p (SUBREG_REG (XEXP (SET_DEST (set), 0)),
230: target))))
231: return 1;
232:
233: /* If TARGET is in OP0 or OP1, check if anything in SEQ sets TARGET
234: besides the last insn. */
235: if (reg_overlap_mentioned_p (target, op0)
236: || (op1 && reg_overlap_mentioned_p (target, op1)))
237: for (i = XVECLEN (seq, 0) - 2; i >= 0; i--)
238: if (reg_set_p (target, XVECEXP (seq, 0, i)))
239: return 0;
240:
241: if (GET_RTX_CLASS (code) == '1')
242: note = gen_rtx (code, GET_MODE (target), op0);
243: else
244: note = gen_rtx (code, GET_MODE (target), op0, op1);
245:
246: REG_NOTES (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1))
247: = gen_rtx (EXPR_LIST, REG_EQUAL, note,
248: REG_NOTES (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1)));
249:
250: return 1;
251: }
252:
253: /* Generate code to perform an operation specified by BINOPTAB
254: on operands OP0 and OP1, with result having machine-mode MODE.
255:
256: UNSIGNEDP is for the case where we have to widen the operands
257: to perform the operation. It says to use zero-extension.
258:
259: If TARGET is nonzero, the value
260: is generated there, if it is convenient to do so.
261: In all cases an rtx is returned for the locus of the value;
262: this may or may not be TARGET. */
263:
264: rtx
265: expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
266: enum machine_mode mode;
267: optab binoptab;
268: rtx op0, op1;
269: rtx target;
270: int unsignedp;
271: enum optab_methods methods;
272: {
273: enum mode_class class;
274: enum machine_mode wider_mode;
275: register rtx temp;
276: int commutative_op = 0;
277: int shift_op = (binoptab->code == ASHIFT
278: || binoptab->code == ASHIFTRT
279: || binoptab->code == LSHIFT
280: || binoptab->code == LSHIFTRT
281: || binoptab->code == ROTATE
282: || binoptab->code == ROTATERT);
1.1.1.4 ! root 283: rtx entry_last = get_last_insn ();
1.1 root 284: rtx last;
285:
286: class = GET_MODE_CLASS (mode);
287:
288: op0 = protect_from_queue (op0, 0);
289: op1 = protect_from_queue (op1, 0);
290: if (target)
291: target = protect_from_queue (target, 1);
292:
293: if (flag_force_mem)
294: {
295: op0 = force_not_mem (op0);
296: op1 = force_not_mem (op1);
297: }
298:
1.1.1.4 ! root 299: /* If subtracting an integer constant, convert this into an addition of
! 300: the negated constant. */
! 301:
! 302: if (binoptab == sub_optab && GET_CODE (op1) == CONST_INT)
! 303: {
! 304: op1 = negate_rtx (mode, op1);
! 305: binoptab = add_optab;
! 306: }
! 307:
1.1 root 308: /* If we are inside an appropriately-short loop and one operand is an
309: expensive constant, force it into a register. */
1.1.1.3 root 310: if (CONSTANT_P (op0) && preserve_subexpressions_p ()
311: && rtx_cost (op0, binoptab->code) > 2)
1.1 root 312: op0 = force_reg (mode, op0);
313:
1.1.1.3 root 314: if (CONSTANT_P (op1) && preserve_subexpressions_p ()
315: && rtx_cost (op1, binoptab->code) > 2)
1.1 root 316: op1 = force_reg (shift_op ? word_mode : mode, op1);
317:
318: /* Record where to delete back to if we backtrack. */
319: last = get_last_insn ();
320:
321: /* If operation is commutative,
322: try to make the first operand a register.
323: Even better, try to make it the same as the target.
324: Also try to make the last operand a constant. */
325: if (GET_RTX_CLASS (binoptab->code) == 'c'
326: || binoptab == smul_widen_optab
327: || binoptab == umul_widen_optab)
328: {
329: commutative_op = 1;
330:
331: if (((target == 0 || GET_CODE (target) == REG)
332: ? ((GET_CODE (op1) == REG
333: && GET_CODE (op0) != REG)
334: || target == op1)
335: : rtx_equal_p (op1, target))
336: || GET_CODE (op0) == CONST_INT)
337: {
338: temp = op1;
339: op1 = op0;
340: op0 = temp;
341: }
342: }
343:
344: /* If we can do it with a three-operand insn, do so. */
345:
346: if (methods != OPTAB_MUST_WIDEN
347: && binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
348: {
349: int icode = (int) binoptab->handlers[(int) mode].insn_code;
350: enum machine_mode mode0 = insn_operand_mode[icode][1];
351: enum machine_mode mode1 = insn_operand_mode[icode][2];
352: rtx pat;
353: rtx xop0 = op0, xop1 = op1;
354:
355: if (target)
356: temp = target;
357: else
358: temp = gen_reg_rtx (mode);
359:
360: /* If it is a commutative operator and the modes would match
361: if we would swap the operands, we can save the conversions. */
362: if (commutative_op)
363: {
364: if (GET_MODE (op0) != mode0 && GET_MODE (op1) != mode1
365: && GET_MODE (op0) == mode1 && GET_MODE (op1) == mode0)
366: {
367: register rtx tmp;
368:
369: tmp = op0; op0 = op1; op1 = tmp;
370: tmp = xop0; xop0 = xop1; xop1 = tmp;
371: }
372: }
373:
374: /* In case the insn wants input operands in modes different from
375: the result, convert the operands. */
376:
377: if (GET_MODE (op0) != VOIDmode
378: && GET_MODE (op0) != mode0)
379: xop0 = convert_to_mode (mode0, xop0, unsignedp);
380:
381: if (GET_MODE (xop1) != VOIDmode
382: && GET_MODE (xop1) != mode1)
383: xop1 = convert_to_mode (mode1, xop1, unsignedp);
384:
385: /* Now, if insn's predicates don't allow our operands, put them into
386: pseudo regs. */
387:
388: if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))
389: xop0 = copy_to_mode_reg (mode0, xop0);
390:
391: if (! (*insn_operand_predicate[icode][2]) (xop1, mode1))
392: xop1 = copy_to_mode_reg (mode1, xop1);
393:
394: if (! (*insn_operand_predicate[icode][0]) (temp, mode))
395: temp = gen_reg_rtx (mode);
396:
397: pat = GEN_FCN (icode) (temp, xop0, xop1);
398: if (pat)
399: {
400: /* If PAT is a multi-insn sequence, try to add an appropriate
401: REG_EQUAL note to it. If we can't because TEMP conflicts with an
402: operand, call ourselves again, this time without a target. */
403: if (GET_CODE (pat) == SEQUENCE
404: && ! add_equal_note (pat, temp, binoptab->code, xop0, xop1))
405: {
406: delete_insns_since (last);
1.1.1.4 ! root 407: return expand_binop (mode, binoptab, op0, op1, NULL_RTX,
! 408: unsignedp, methods);
1.1 root 409: }
410:
411: emit_insn (pat);
412: return temp;
413: }
414: else
415: delete_insns_since (last);
416: }
417:
1.1.1.4 ! root 418: /* If this is a multiply, see if we can do a widening operation that
! 419: takes operands of this mode and makes a wider mode. */
! 420:
! 421: if (binoptab == smul_optab && GET_MODE_WIDER_MODE (mode) != VOIDmode
! 422: && (((unsignedp ? umul_widen_optab : smul_widen_optab)
! 423: ->handlers[(int) GET_MODE_WIDER_MODE (mode)].insn_code)
! 424: != CODE_FOR_nothing))
! 425: {
! 426: temp = expand_binop (GET_MODE_WIDER_MODE (mode),
! 427: unsignedp ? umul_widen_optab : smul_widen_optab,
! 428: op0, op1, 0, unsignedp, OPTAB_DIRECT);
! 429:
! 430: if (GET_MODE_CLASS (mode) == MODE_INT)
! 431: return gen_lowpart (mode, temp);
! 432: else
! 433: return convert_to_mode (mode, temp, unsignedp);
! 434: }
! 435:
! 436: /* Look for a wider mode of the same class for which we think we
! 437: can open-code the operation. Check for a widening multiply at the
! 438: wider mode as well. */
! 439:
! 440: if ((class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
! 441: && methods != OPTAB_DIRECT && methods != OPTAB_LIB)
! 442: for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
! 443: wider_mode = GET_MODE_WIDER_MODE (wider_mode))
! 444: {
! 445: if (binoptab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing
! 446: || (binoptab == smul_optab
! 447: && GET_MODE_WIDER_MODE (wider_mode) != VOIDmode
! 448: && (((unsignedp ? umul_widen_optab : smul_widen_optab)
! 449: ->handlers[(int) GET_MODE_WIDER_MODE (wider_mode)].insn_code)
! 450: != CODE_FOR_nothing)))
! 451: {
! 452: rtx xop0 = op0, xop1 = op1;
! 453: int no_extend = 0;
! 454:
! 455: /* For certain integer operations, we need not actually extend
! 456: the narrow operands, as long as we will truncate
! 457: the results to the same narrowness. Don't do this when
! 458: WIDER_MODE is wider than a word since a paradoxical SUBREG
! 459: isn't valid for such modes. */
! 460:
! 461: if ((binoptab == ior_optab || binoptab == and_optab
! 462: || binoptab == xor_optab
! 463: || binoptab == add_optab || binoptab == sub_optab
! 464: || binoptab == smul_optab
! 465: || binoptab == ashl_optab || binoptab == lshl_optab)
! 466: && class == MODE_INT
! 467: && GET_MODE_SIZE (wider_mode) <= UNITS_PER_WORD)
! 468: no_extend = 1;
! 469:
! 470: /* If an operand is a constant integer, we might as well
! 471: convert it since that is more efficient than using a SUBREG,
! 472: unlike the case for other operands. Similarly for
! 473: SUBREGs that were made due to promoted objects. */
! 474:
! 475: if (no_extend && GET_MODE (xop0) != VOIDmode
! 476: && ! (GET_CODE (xop0) == SUBREG
! 477: && SUBREG_PROMOTED_VAR_P (xop0)))
! 478: xop0 = gen_rtx (SUBREG, wider_mode,
! 479: force_reg (GET_MODE (xop0), xop0), 0);
! 480: else
! 481: xop0 = convert_to_mode (wider_mode, xop0, unsignedp);
! 482:
! 483: if (no_extend && GET_MODE (xop1) != VOIDmode
! 484: && ! (GET_CODE (xop1) == SUBREG
! 485: && SUBREG_PROMOTED_VAR_P (xop1)))
! 486: xop1 = gen_rtx (SUBREG, wider_mode,
! 487: force_reg (GET_MODE (xop1), xop1), 0);
! 488: else
! 489: xop1 = convert_to_mode (wider_mode, xop1, unsignedp);
! 490:
! 491: temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX,
! 492: unsignedp, OPTAB_DIRECT);
! 493: if (temp)
! 494: {
! 495: if (class != MODE_INT)
! 496: {
! 497: if (target == 0)
! 498: target = gen_reg_rtx (mode);
! 499: convert_move (target, temp, 0);
! 500: return target;
! 501: }
! 502: else
! 503: return gen_lowpart (mode, temp);
! 504: }
! 505: else
! 506: delete_insns_since (last);
! 507: }
! 508: }
! 509:
1.1 root 510: /* These can be done a word at a time. */
511: if ((binoptab == and_optab || binoptab == ior_optab || binoptab == xor_optab)
512: && class == MODE_INT
513: && GET_MODE_SIZE (mode) > UNITS_PER_WORD
514: && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
515: {
516: int i;
517: rtx insns;
518: rtx equiv_value;
519:
520: /* If TARGET is the same as one of the operands, the REG_EQUAL note
521: won't be accurate, so use a new target. */
522: if (target == 0 || target == op0 || target == op1)
523: target = gen_reg_rtx (mode);
524:
525: start_sequence ();
526:
527: /* Do the actual arithmetic. */
528: for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)
529: {
530: rtx target_piece = operand_subword (target, i, 1, mode);
531: rtx x = expand_binop (word_mode, binoptab,
532: operand_subword_force (op0, i, mode),
533: operand_subword_force (op1, i, mode),
534: target_piece, unsignedp, methods);
535: if (target_piece != x)
536: emit_move_insn (target_piece, x);
537: }
538:
539: insns = get_insns ();
540: end_sequence ();
541:
542: if (binoptab->code != UNKNOWN)
543: equiv_value = gen_rtx (binoptab->code, mode, op0, op1);
544: else
545: equiv_value = 0;
546:
547: emit_no_conflict_block (insns, target, op0, op1, equiv_value);
548: return target;
549: }
550:
551: /* These can be done a word at a time by propagating carries. */
552: if ((binoptab == add_optab || binoptab == sub_optab)
553: && class == MODE_INT
554: && GET_MODE_SIZE (mode) >= 2 * UNITS_PER_WORD
555: && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
556: {
557: int i;
558: rtx carry_tmp = gen_reg_rtx (word_mode);
559: optab otheroptab = binoptab == add_optab ? sub_optab : add_optab;
560: int nwords = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
561: rtx carry_in, carry_out;
1.1.1.4 ! root 562: rtx xop0, xop1;
1.1 root 563:
564: /* We can handle either a 1 or -1 value for the carry. If STORE_FLAG
565: value is one of those, use it. Otherwise, use 1 since it is the
566: one easiest to get. */
567: #if STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1
568: int normalizep = STORE_FLAG_VALUE;
569: #else
570: int normalizep = 1;
571: #endif
572:
573: /* Prepare the operands. */
1.1.1.4 ! root 574: xop0 = force_reg (mode, op0);
! 575: xop1 = force_reg (mode, op1);
1.1 root 576:
577: if (target == 0 || GET_CODE (target) != REG
1.1.1.4 ! root 578: || target == xop0 || target == xop1)
1.1 root 579: target = gen_reg_rtx (mode);
580:
581: /* Do the actual arithmetic. */
582: for (i = 0; i < nwords; i++)
583: {
584: int index = (WORDS_BIG_ENDIAN ? nwords - i - 1 : i);
585: rtx target_piece = operand_subword (target, index, 1, mode);
1.1.1.4 ! root 586: rtx op0_piece = operand_subword_force (xop0, index, mode);
! 587: rtx op1_piece = operand_subword_force (xop1, index, mode);
1.1 root 588: rtx x;
589:
590: /* Main add/subtract of the input operands. */
591: x = expand_binop (word_mode, binoptab,
592: op0_piece, op1_piece,
593: target_piece, unsignedp, methods);
594: if (x == 0)
595: break;
596:
597: if (i + 1 < nwords)
598: {
599: /* Store carry from main add/subtract. */
600: carry_out = gen_reg_rtx (word_mode);
601: carry_out = emit_store_flag (carry_out,
602: binoptab == add_optab ? LTU : GTU,
603: x, op0_piece,
604: word_mode, 1, normalizep);
605: if (!carry_out)
606: break;
607: }
608:
609: if (i > 0)
610: {
611: /* Add/subtract previous carry to main result. */
612: x = expand_binop (word_mode,
613: normalizep == 1 ? binoptab : otheroptab,
614: x, carry_in,
615: target_piece, 1, methods);
616: if (target_piece != x)
617: emit_move_insn (target_piece, x);
618:
619: if (i + 1 < nwords)
620: {
621: /* THIS CODE HAS NOT BEEN TESTED. */
622: /* Get out carry from adding/subtracting carry in. */
623: carry_tmp = emit_store_flag (carry_tmp,
624: binoptab == add_optab
625: ? LTU : GTU,
626: x, carry_in,
627: word_mode, 1, normalizep);
628: /* Logical-ior the two poss. carry together. */
629: carry_out = expand_binop (word_mode, ior_optab,
630: carry_out, carry_tmp,
631: carry_out, 0, methods);
632: if (!carry_out)
633: break;
634: }
635: }
636:
637: carry_in = carry_out;
638: }
639:
640: if (i == GET_MODE_BITSIZE (mode) / BITS_PER_WORD)
641: {
642: rtx temp;
643:
644: temp = emit_move_insn (target, target);
645: REG_NOTES (temp) = gen_rtx (EXPR_LIST, REG_EQUAL,
1.1.1.4 ! root 646: gen_rtx (binoptab->code, mode, xop0, xop1),
1.1 root 647: REG_NOTES (temp));
648: return target;
649: }
650: else
651: delete_insns_since (last);
652: }
653:
654: /* If we want to multiply two two-word values and have normal and widening
655: multiplies of single-word values, we can do this with three smaller
656: multiplications. Note that we do not make a REG_NO_CONFLICT block here
657: because we are not operating on one word at a time.
658:
659: The multiplication proceeds as follows:
660: _______________________
661: [__op0_high_|__op0_low__]
662: _______________________
663: * [__op1_high_|__op1_low__]
664: _______________________________________________
665: _______________________
666: (1) [__op0_low__*__op1_low__]
667: _______________________
668: (2a) [__op0_low__*__op1_high_]
669: _______________________
670: (2b) [__op0_high_*__op1_low__]
671: _______________________
672: (3) [__op0_high_*__op1_high_]
673:
674:
675: This gives a 4-word result. Since we are only interested in the
676: lower 2 words, partial result (3) and the upper words of (2a) and
677: (2b) don't need to be calculated. Hence (2a) and (2b) can be
678: calculated using non-widening multiplication.
679:
680: (1), however, needs to be calculated with an unsigned widening
681: multiplication. If this operation is not directly supported we
682: try using a signed widening multiplication and adjust the result.
683: This adjustment works as follows:
684:
685: If both operands are positive then no adjustment is needed.
686:
687: If the operands have different signs, for example op0_low < 0 and
688: op1_low >= 0, the instruction treats the most significant bit of
689: op0_low as a sign bit instead of a bit with significance
690: 2**(BITS_PER_WORD-1), i.e. the instruction multiplies op1_low
691: with 2**BITS_PER_WORD - op0_low, and two's complements the
692: result. Conclusion: We need to add op1_low * 2**BITS_PER_WORD to
693: the result.
694:
695: Similarly, if both operands are negative, we need to add
696: (op0_low + op1_low) * 2**BITS_PER_WORD.
697:
698: We use a trick to adjust quickly. We logically shift op0_low right
699: (op1_low) BITS_PER_WORD-1 steps to get 0 or 1, and add this to
700: op0_high (op1_high) before it is used to calculate 2b (2a). If no
701: logical shift exists, we do an arithmetic right shift and subtract
702: the 0 or -1. */
703:
704: if (binoptab == smul_optab
705: && class == MODE_INT
706: && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
707: && smul_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
708: && add_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
709: && ((umul_widen_optab->handlers[(int) mode].insn_code
710: != CODE_FOR_nothing)
711: || (smul_widen_optab->handlers[(int) mode].insn_code
712: != CODE_FOR_nothing)))
713: {
714: int low = (WORDS_BIG_ENDIAN ? 1 : 0);
715: int high = (WORDS_BIG_ENDIAN ? 0 : 1);
716: rtx op0_high = operand_subword_force (op0, high, mode);
717: rtx op0_low = operand_subword_force (op0, low, mode);
718: rtx op1_high = operand_subword_force (op1, high, mode);
719: rtx op1_low = operand_subword_force (op1, low, mode);
720: rtx product = 0;
721: rtx op0_xhigh;
722: rtx op1_xhigh;
723:
724: /* If the target is the same as one of the inputs, don't use it. This
725: prevents problems with the REG_EQUAL note. */
726: if (target == op0 || target == op1)
727: target = 0;
728:
729: /* Multiply the two lower words to get a double-word product.
730: If unsigned widening multiplication is available, use that;
731: otherwise use the signed form and compensate. */
732:
733: if (umul_widen_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
734: {
735: product = expand_binop (mode, umul_widen_optab, op0_low, op1_low,
736: target, 1, OPTAB_DIRECT);
737:
738: /* If we didn't succeed, delete everything we did so far. */
739: if (product == 0)
740: delete_insns_since (last);
741: else
742: op0_xhigh = op0_high, op1_xhigh = op1_high;
743: }
744:
745: if (product == 0
746: && smul_widen_optab->handlers[(int) mode].insn_code
747: != CODE_FOR_nothing)
748: {
1.1.1.4 ! root 749: rtx wordm1 = GEN_INT (BITS_PER_WORD - 1);
1.1 root 750: product = expand_binop (mode, smul_widen_optab, op0_low, op1_low,
751: target, 1, OPTAB_DIRECT);
752: op0_xhigh = expand_binop (word_mode, lshr_optab, op0_low, wordm1,
1.1.1.4 ! root 753: NULL_RTX, 1, OPTAB_DIRECT);
1.1 root 754: if (op0_xhigh)
755: op0_xhigh = expand_binop (word_mode, add_optab, op0_high,
756: op0_xhigh, op0_xhigh, 0, OPTAB_DIRECT);
757: else
758: {
759: op0_xhigh = expand_binop (word_mode, ashr_optab, op0_low, wordm1,
1.1.1.4 ! root 760: NULL_RTX, 0, OPTAB_DIRECT);
1.1 root 761: if (op0_xhigh)
762: op0_xhigh = expand_binop (word_mode, sub_optab, op0_high,
763: op0_xhigh, op0_xhigh, 0,
764: OPTAB_DIRECT);
765: }
766:
767: op1_xhigh = expand_binop (word_mode, lshr_optab, op1_low, wordm1,
1.1.1.4 ! root 768: NULL_RTX, 1, OPTAB_DIRECT);
1.1 root 769: if (op1_xhigh)
770: op1_xhigh = expand_binop (word_mode, add_optab, op1_high,
771: op1_xhigh, op1_xhigh, 0, OPTAB_DIRECT);
772: else
773: {
774: op1_xhigh = expand_binop (word_mode, ashr_optab, op1_low, wordm1,
1.1.1.4 ! root 775: NULL_RTX, 0, OPTAB_DIRECT);
1.1 root 776: if (op1_xhigh)
777: op1_xhigh = expand_binop (word_mode, sub_optab, op1_high,
778: op1_xhigh, op1_xhigh, 0,
779: OPTAB_DIRECT);
780: }
781: }
782:
783: /* If we have been able to directly compute the product of the
784: low-order words of the operands and perform any required adjustments
785: of the operands, we proceed by trying two more multiplications
786: and then computing the appropriate sum.
787:
788: We have checked above that the required addition is provided.
789: Full-word addition will normally always succeed, especially if
790: it is provided at all, so we don't worry about its failure. The
791: multiplication may well fail, however, so we do handle that. */
792:
793: if (product && op0_xhigh && op1_xhigh)
794: {
795: rtx product_piece;
796: rtx product_high = operand_subword (product, high, 1, mode);
1.1.1.4 ! root 797: rtx temp = expand_binop (word_mode, binoptab, op0_low, op1_xhigh,
! 798: NULL_RTX, 0, OPTAB_DIRECT);
1.1 root 799:
800: if (temp)
801: {
802: product_piece = expand_binop (word_mode, add_optab, temp,
803: product_high, product_high,
804: 0, OPTAB_LIB_WIDEN);
805: if (product_piece != product_high)
806: emit_move_insn (product_high, product_piece);
807:
1.1.1.4 ! root 808: temp = expand_binop (word_mode, binoptab, op1_low, op0_xhigh,
! 809: NULL_RTX, 0, OPTAB_DIRECT);
1.1 root 810:
811: product_piece = expand_binop (word_mode, add_optab, temp,
812: product_high, product_high,
813: 0, OPTAB_LIB_WIDEN);
814: if (product_piece != product_high)
815: emit_move_insn (product_high, product_piece);
816:
817: temp = emit_move_insn (product, product);
818: REG_NOTES (temp) = gen_rtx (EXPR_LIST, REG_EQUAL,
819: gen_rtx (MULT, mode, op0, op1),
820: REG_NOTES (temp));
821:
822: return product;
823: }
824: }
825:
826: /* If we get here, we couldn't do it for some reason even though we
827: originally thought we could. Delete anything we've emitted in
828: trying to do it. */
829:
830: delete_insns_since (last);
831: }
832:
1.1.1.4 ! root 833: /* We need to open-code the complex type operations: '+, -, * and /' */
! 834:
! 835: /* At this point we allow operations between two similar complex
! 836: numbers, and also if one of the operands is not a complex number
! 837: but rather of MODE_FLOAT or MODE_INT. However, the caller
! 838: must make sure that the MODE of the non-complex operand matches
! 839: the SUBMODE of the complex operand. */
! 840:
! 841: if (class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT)
! 842: {
! 843: rtx real0 = (rtx) 0;
! 844: rtx imag0 = (rtx) 0;
! 845: rtx real1 = (rtx) 0;
! 846: rtx imag1 = (rtx) 0;
! 847: rtx realr;
! 848: rtx imagr;
! 849: rtx res;
! 850: rtx seq;
! 851: rtx equiv_value;
! 852:
! 853: /* Find the correct mode for the real and imaginary parts */
! 854: enum machine_mode submode
! 855: = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT,
! 856: class == MODE_COMPLEX_INT ? MODE_INT : MODE_FLOAT,
! 857: 0);
! 858:
! 859: if (submode == BLKmode)
! 860: abort ();
! 861:
! 862: if (! target)
! 863: target = gen_reg_rtx (mode);
! 864:
! 865: start_sequence ();
! 866:
! 867: realr = gen_realpart (submode, target);
! 868: imagr = gen_imagpart (submode, target);
! 869:
! 870: if (GET_MODE (op0) == mode)
! 871: {
! 872: real0 = gen_realpart (submode, op0);
! 873: imag0 = gen_imagpart (submode, op0);
! 874: }
! 875: else
! 876: real0 = op0;
! 877:
! 878: if (GET_MODE (op1) == mode)
! 879: {
! 880: real1 = gen_realpart (submode, op1);
! 881: imag1 = gen_imagpart (submode, op1);
! 882: }
! 883: else
! 884: real1 = op1;
! 885:
! 886: if (! real0 || ! real1 || ! (imag0 || imag1))
! 887: abort ();
! 888:
! 889: switch (binoptab->code)
! 890: {
! 891: case PLUS:
! 892: case MINUS:
! 893: res = expand_binop (submode, binoptab, real0, real1,
! 894: realr, unsignedp, methods);
! 895: if (res != realr)
! 896: emit_move_insn (realr, res);
! 897:
! 898: if (imag0 && imag1)
! 899: res = expand_binop (submode, binoptab, imag0, imag1,
! 900: imagr, unsignedp, methods);
! 901: else if (imag0)
! 902: res = imag0;
! 903: else if (binoptab->code == MINUS)
! 904: res = expand_unop (submode, neg_optab, imag1, imagr, unsignedp);
! 905: else
! 906: res = imag1;
! 907:
! 908: if (res != imagr)
! 909: emit_move_insn (imagr, res);
! 910: break;
! 911:
! 912: case MULT:
! 913: /* (a+ib) * (c+id) = (ac-bd) + i(ad+cb) */
! 914:
! 915: res = expand_binop (submode, binoptab, real0, real1,
! 916: realr, unsignedp, methods);
! 917:
! 918: if (imag0 && imag1)
! 919: {
! 920: rtx temp =
! 921: expand_binop (submode, sub_optab, res,
! 922: expand_binop (submode, binoptab, imag0, imag1,
! 923: 0, unsignedp, methods),
! 924: realr, unsignedp, methods);
! 925:
! 926: if (temp != realr)
! 927: emit_move_insn (realr, temp);
! 928:
! 929: res = expand_binop (submode, add_optab,
! 930: expand_binop (submode, binoptab,
! 931: real0, imag1,
! 932: 0, unsignedp, methods),
! 933: expand_binop (submode, binoptab,
! 934: real1, imag0,
! 935: 0, unsignedp, methods),
! 936: imagr, unsignedp, methods);
! 937: if (res != imagr)
! 938: emit_move_insn (imagr, res);
! 939: }
! 940: else
! 941: {
! 942: if (res != realr)
! 943: emit_move_insn (realr, res);
! 944:
! 945: if (imag0)
! 946: res = expand_binop (submode, binoptab,
! 947: real1, imag0, imagr, unsignedp, methods);
! 948: else
! 949: res = expand_binop (submode, binoptab,
! 950: real0, imag1, imagr, unsignedp, methods);
! 951: if (res != imagr)
! 952: emit_move_insn (imagr, res);
! 953: }
! 954: break;
! 955:
! 956: case DIV:
! 957: /* (c+id)/(a+ib) == ((c+id)*(a-ib))/(a*a+b*b) */
! 958:
! 959: if (! imag1)
! 960: {
! 961: /* Simply divide the real and imaginary parts by `a' */
! 962: res = expand_binop (submode, binoptab, real0, real1,
! 963: realr, unsignedp, methods);
! 964: if (res != realr)
! 965: emit_move_insn (realr, res);
! 966:
! 967: res = expand_binop (submode, binoptab, imag0, real1,
! 968: imagr, unsignedp, methods);
! 969: if (res != imagr)
! 970: emit_move_insn (imagr, res);
! 971: }
! 972: else /* Divisor is of complex type */
! 973: { /* X/(a+ib) */
! 974:
! 975: rtx divisor;
! 976: rtx real_t;
! 977: rtx imag_t;
! 978:
! 979: optab mulopt = unsignedp ? umul_widen_optab : smul_optab;
! 980:
! 981: /* Divisor: c*c + d*d */
! 982: divisor = expand_binop (submode, add_optab,
! 983: expand_binop (submode, mulopt,
! 984: real1, real1,
! 985: 0, unsignedp, methods),
! 986: expand_binop (submode, mulopt,
! 987: imag1, imag1,
! 988: 0, unsignedp, methods),
! 989: 0, unsignedp, methods);
! 990:
! 991: if (! imag0) /* ((a)(c-id))/divisor */
! 992: { /* (a+i0) / (c+id) = (ac/(cc+dd)) + i(-ad/(cc+dd)) */
! 993: /* Calculate the dividend */
! 994: real_t = expand_binop (submode, mulopt, real0, real1,
! 995: 0, unsignedp, methods);
! 996:
! 997: imag_t
! 998: = expand_unop (submode, neg_optab,
! 999: expand_binop (submode, mulopt, real0, imag1,
! 1000: 0, unsignedp, methods),
! 1001: 0, unsignedp);
! 1002: }
! 1003: else /* ((a+ib)(c-id))/divider */
! 1004: {
! 1005: /* Calculate the dividend */
! 1006: real_t = expand_binop (submode, add_optab,
! 1007: expand_binop (submode, mulopt,
! 1008: real0, real1,
! 1009: 0, unsignedp, methods),
! 1010: expand_binop (submode, mulopt,
! 1011: imag0, imag1,
! 1012: 0, unsignedp, methods),
! 1013: 0, unsignedp, methods);
! 1014:
! 1015: imag_t = expand_binop (submode, sub_optab,
! 1016: expand_binop (submode, mulopt,
! 1017: imag0, real1,
! 1018: 0, unsignedp, methods),
! 1019: expand_binop (submode, mulopt,
! 1020: real0, imag1,
! 1021: 0, unsignedp, methods),
! 1022: 0, unsignedp, methods);
! 1023:
! 1024: }
! 1025:
! 1026: res = expand_binop (submode, binoptab, real_t, divisor,
! 1027: realr, unsignedp, methods);
! 1028: if (res != realr)
! 1029: emit_move_insn (realr, res);
! 1030:
! 1031: res = expand_binop (submode, binoptab, imag_t, divisor,
! 1032: imagr, unsignedp, methods);
! 1033: if (res != imagr)
! 1034: emit_move_insn (imagr, res);
! 1035: }
! 1036: break;
! 1037:
! 1038: default:
! 1039: abort ();
! 1040: }
! 1041:
! 1042: seq = get_insns ();
! 1043: end_sequence ();
! 1044:
! 1045: if (binoptab->code != UNKNOWN)
! 1046: equiv_value = gen_rtx (binoptab->code, mode, op0, op1);
! 1047: else
! 1048: equiv_value = 0;
! 1049:
! 1050: emit_no_conflict_block (seq, target, op0, op1, equiv_value);
! 1051:
! 1052: return target;
! 1053: }
! 1054:
1.1 root 1055: /* It can't be open-coded in this mode.
1056: Use a library call if one is available and caller says that's ok. */
1057:
1058: if (binoptab->handlers[(int) mode].libfunc
1059: && (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN))
1060: {
1061: rtx insns;
1062: rtx funexp = binoptab->handlers[(int) mode].libfunc;
1.1.1.4 ! root 1063: rtx op1x = op1;
! 1064: enum machine_mode op1_mode = mode;
1.1 root 1065:
1066: start_sequence ();
1067:
1.1.1.4 ! root 1068: if (shift_op)
! 1069: {
! 1070: op1_mode = word_mode;
! 1071: /* Specify unsigned here,
! 1072: since negative shift counts are meaningless. */
! 1073: op1x = convert_to_mode (word_mode, op1, 1);
! 1074: }
! 1075:
1.1 root 1076: /* Pass 1 for NO_QUEUE so we don't lose any increments
1077: if the libcall is cse'd or moved. */
1078: emit_library_call (binoptab->handlers[(int) mode].libfunc,
1.1.1.4 ! root 1079: 1, mode, 2, op0, mode, op1x, op1_mode);
1.1 root 1080:
1081: insns = get_insns ();
1082: end_sequence ();
1083:
1084: target = gen_reg_rtx (mode);
1085: emit_libcall_block (insns, target, hard_libcall_value (mode),
1086: gen_rtx (binoptab->code, mode, op0, op1));
1087:
1088: return target;
1089: }
1090:
1091: delete_insns_since (last);
1092:
1093: /* It can't be done in this mode. Can we do it in a wider mode? */
1094:
1095: if (! (methods == OPTAB_WIDEN || methods == OPTAB_LIB_WIDEN
1096: || methods == OPTAB_MUST_WIDEN))
1.1.1.4 ! root 1097: {
! 1098: /* Caller says, don't even try. */
! 1099: delete_insns_since (entry_last);
! 1100: return 0;
! 1101: }
1.1 root 1102:
1103: /* Compute the value of METHODS to pass to recursive calls.
1104: Don't allow widening to be tried recursively. */
1105:
1106: methods = (methods == OPTAB_LIB_WIDEN ? OPTAB_LIB : OPTAB_DIRECT);
1107:
1108: /* Look for a wider mode of the same class for which it appears we can do
1109: the operation. */
1110:
1111: if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
1112: {
1113: for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
1114: wider_mode = GET_MODE_WIDER_MODE (wider_mode))
1115: {
1116: if ((binoptab->handlers[(int) wider_mode].insn_code
1117: != CODE_FOR_nothing)
1118: || (methods == OPTAB_LIB
1119: && binoptab->handlers[(int) wider_mode].libfunc))
1120: {
1121: rtx xop0 = op0, xop1 = op1;
1122: int no_extend = 0;
1123:
1124: /* For certain integer operations, we need not actually extend
1125: the narrow operands, as long as we will truncate
1.1.1.4 ! root 1126: the results to the same narrowness. Don't do this when
! 1127: WIDER_MODE is wider than a word since a paradoxical SUBREG
! 1128: isn't valid for such modes. */
1.1 root 1129:
1130: if ((binoptab == ior_optab || binoptab == and_optab
1131: || binoptab == xor_optab
1132: || binoptab == add_optab || binoptab == sub_optab
1133: || binoptab == smul_optab
1134: || binoptab == ashl_optab || binoptab == lshl_optab)
1.1.1.4 ! root 1135: && class == MODE_INT
! 1136: && GET_MODE_SIZE (wider_mode) <= UNITS_PER_WORD)
1.1 root 1137: no_extend = 1;
1138:
1139: /* If an operand is a constant integer, we might as well
1140: convert it since that is more efficient than using a SUBREG,
1.1.1.4 ! root 1141: unlike the case for other operands. Similarly for
! 1142: SUBREGs that were made due to promoted objects.*/
1.1 root 1143:
1.1.1.4 ! root 1144: if (no_extend && GET_MODE (xop0) != VOIDmode
! 1145: && ! (GET_CODE (xop0) == SUBREG
! 1146: && SUBREG_PROMOTED_VAR_P (xop0)))
1.1 root 1147: xop0 = gen_rtx (SUBREG, wider_mode,
1148: force_reg (GET_MODE (xop0), xop0), 0);
1149: else
1150: xop0 = convert_to_mode (wider_mode, xop0, unsignedp);
1151:
1.1.1.4 ! root 1152: if (no_extend && GET_MODE (xop1) != VOIDmode
! 1153: && ! (GET_CODE (xop1) == SUBREG
! 1154: && SUBREG_PROMOTED_VAR_P (xop1)))
1.1 root 1155: xop1 = gen_rtx (SUBREG, wider_mode,
1156: force_reg (GET_MODE (xop1), xop1), 0);
1157: else
1158: xop1 = convert_to_mode (wider_mode, xop1, unsignedp);
1159:
1.1.1.4 ! root 1160: temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX,
1.1 root 1161: unsignedp, methods);
1162: if (temp)
1163: {
1164: if (class != MODE_INT)
1165: {
1166: if (target == 0)
1167: target = gen_reg_rtx (mode);
1168: convert_move (target, temp, 0);
1169: return target;
1170: }
1171: else
1172: return gen_lowpart (mode, temp);
1173: }
1174: else
1175: delete_insns_since (last);
1176: }
1177: }
1178: }
1179:
1.1.1.4 ! root 1180: delete_insns_since (entry_last);
1.1 root 1181: return 0;
1182: }
1183:
1184: /* Expand a binary operator which has both signed and unsigned forms.
1185: UOPTAB is the optab for unsigned operations, and SOPTAB is for
1186: signed operations.
1187:
1188: If we widen unsigned operands, we may use a signed wider operation instead
1189: of an unsigned wider operation, since the result would be the same. */
1190:
1191: rtx
1192: sign_expand_binop (mode, uoptab, soptab, op0, op1, target, unsignedp, methods)
1193: enum machine_mode mode;
1194: optab uoptab, soptab;
1195: rtx op0, op1, target;
1196: int unsignedp;
1197: enum optab_methods methods;
1198: {
1199: register rtx temp;
1200: optab direct_optab = unsignedp ? uoptab : soptab;
1201: struct optab wide_soptab;
1202:
1203: /* Do it without widening, if possible. */
1204: temp = expand_binop (mode, direct_optab, op0, op1, target,
1205: unsignedp, OPTAB_DIRECT);
1206: if (temp || methods == OPTAB_DIRECT)
1207: return temp;
1208:
1209: /* Try widening to a signed int. Make a fake signed optab that
1210: hides any signed insn for direct use. */
1211: wide_soptab = *soptab;
1212: wide_soptab.handlers[(int) mode].insn_code = CODE_FOR_nothing;
1213: wide_soptab.handlers[(int) mode].libfunc = 0;
1214:
1215: temp = expand_binop (mode, &wide_soptab, op0, op1, target,
1216: unsignedp, OPTAB_WIDEN);
1217:
1218: /* For unsigned operands, try widening to an unsigned int. */
1219: if (temp == 0 && unsignedp)
1220: temp = expand_binop (mode, uoptab, op0, op1, target,
1221: unsignedp, OPTAB_WIDEN);
1222: if (temp || methods == OPTAB_WIDEN)
1223: return temp;
1224:
1225: /* Use the right width lib call if that exists. */
1226: temp = expand_binop (mode, direct_optab, op0, op1, target, unsignedp, OPTAB_LIB);
1227: if (temp || methods == OPTAB_LIB)
1228: return temp;
1229:
1230: /* Must widen and use a lib call, use either signed or unsigned. */
1231: temp = expand_binop (mode, &wide_soptab, op0, op1, target,
1232: unsignedp, methods);
1233: if (temp != 0)
1234: return temp;
1235: if (unsignedp)
1236: return expand_binop (mode, uoptab, op0, op1, target,
1237: unsignedp, methods);
1238: return 0;
1239: }
1240:
1241: /* Generate code to perform an operation specified by BINOPTAB
1242: on operands OP0 and OP1, with two results to TARG1 and TARG2.
1243: We assume that the order of the operands for the instruction
1244: is TARG0, OP0, OP1, TARG1, which would fit a pattern like
1245: [(set TARG0 (operate OP0 OP1)) (set TARG1 (operate ...))].
1246:
1247: Either TARG0 or TARG1 may be zero, but what that means is that
1248: that result is not actually wanted. We will generate it into
1249: a dummy pseudo-reg and discard it. They may not both be zero.
1250:
1251: Returns 1 if this operation can be performed; 0 if not. */
1252:
1253: int
1254: expand_twoval_binop (binoptab, op0, op1, targ0, targ1, unsignedp)
1255: optab binoptab;
1256: rtx op0, op1;
1257: rtx targ0, targ1;
1258: int unsignedp;
1259: {
1260: enum machine_mode mode = GET_MODE (targ0 ? targ0 : targ1);
1261: enum mode_class class;
1262: enum machine_mode wider_mode;
1.1.1.4 ! root 1263: rtx entry_last = get_last_insn ();
1.1 root 1264: rtx last;
1265:
1266: class = GET_MODE_CLASS (mode);
1267:
1268: op0 = protect_from_queue (op0, 0);
1269: op1 = protect_from_queue (op1, 0);
1270:
1271: if (flag_force_mem)
1272: {
1273: op0 = force_not_mem (op0);
1274: op1 = force_not_mem (op1);
1275: }
1276:
1277: /* If we are inside an appropriately-short loop and one operand is an
1278: expensive constant, force it into a register. */
1.1.1.3 root 1279: if (CONSTANT_P (op0) && preserve_subexpressions_p ()
1280: && rtx_cost (op0, binoptab->code) > 2)
1.1 root 1281: op0 = force_reg (mode, op0);
1282:
1.1.1.3 root 1283: if (CONSTANT_P (op1) && preserve_subexpressions_p ()
1284: && rtx_cost (op1, binoptab->code) > 2)
1.1 root 1285: op1 = force_reg (mode, op1);
1286:
1287: if (targ0)
1288: targ0 = protect_from_queue (targ0, 1);
1289: else
1290: targ0 = gen_reg_rtx (mode);
1291: if (targ1)
1292: targ1 = protect_from_queue (targ1, 1);
1293: else
1294: targ1 = gen_reg_rtx (mode);
1295:
1296: /* Record where to go back to if we fail. */
1297: last = get_last_insn ();
1298:
1299: if (binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1300: {
1301: int icode = (int) binoptab->handlers[(int) mode].insn_code;
1302: enum machine_mode mode0 = insn_operand_mode[icode][1];
1303: enum machine_mode mode1 = insn_operand_mode[icode][2];
1304: rtx pat;
1305: rtx xop0 = op0, xop1 = op1;
1306:
1307: /* In case this insn wants input operands in modes different from the
1308: result, convert the operands. */
1309: if (GET_MODE (op0) != VOIDmode && GET_MODE (op0) != mode0)
1310: xop0 = convert_to_mode (mode0, xop0, unsignedp);
1311:
1312: if (GET_MODE (op1) != VOIDmode && GET_MODE (op1) != mode1)
1313: xop1 = convert_to_mode (mode1, xop1, unsignedp);
1314:
1315: /* Now, if insn doesn't accept these operands, put them into pseudos. */
1316: if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))
1317: xop0 = copy_to_mode_reg (mode0, xop0);
1318:
1319: if (! (*insn_operand_predicate[icode][2]) (xop1, mode1))
1320: xop1 = copy_to_mode_reg (mode1, xop1);
1321:
1322: /* We could handle this, but we should always be called with a pseudo
1323: for our targets and all insns should take them as outputs. */
1324: if (! (*insn_operand_predicate[icode][0]) (targ0, mode)
1325: || ! (*insn_operand_predicate[icode][3]) (targ1, mode))
1326: abort ();
1327:
1328: pat = GEN_FCN (icode) (targ0, xop0, xop1, targ1);
1329: if (pat)
1330: {
1331: emit_insn (pat);
1332: return 1;
1333: }
1334: else
1335: delete_insns_since (last);
1336: }
1337:
1338: /* It can't be done in this mode. Can we do it in a wider mode? */
1339:
1340: if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
1341: {
1342: for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
1343: wider_mode = GET_MODE_WIDER_MODE (wider_mode))
1344: {
1345: if (binoptab->handlers[(int) wider_mode].insn_code
1346: != CODE_FOR_nothing)
1347: {
1348: register rtx t0 = gen_reg_rtx (wider_mode);
1349: register rtx t1 = gen_reg_rtx (wider_mode);
1350:
1351: if (expand_twoval_binop (binoptab,
1352: convert_to_mode (wider_mode, op0,
1353: unsignedp),
1354: convert_to_mode (wider_mode, op1,
1355: unsignedp),
1356: t0, t1, unsignedp))
1357: {
1358: convert_move (targ0, t0, unsignedp);
1359: convert_move (targ1, t1, unsignedp);
1360: return 1;
1361: }
1362: else
1363: delete_insns_since (last);
1364: }
1365: }
1366: }
1367:
1.1.1.4 ! root 1368: delete_insns_since (entry_last);
1.1 root 1369: return 0;
1370: }
1371:
1372: /* Generate code to perform an operation specified by UNOPTAB
1373: on operand OP0, with result having machine-mode MODE.
1374:
1375: UNSIGNEDP is for the case where we have to widen the operands
1376: to perform the operation. It says to use zero-extension.
1377:
1378: If TARGET is nonzero, the value
1379: is generated there, if it is convenient to do so.
1380: In all cases an rtx is returned for the locus of the value;
1381: this may or may not be TARGET. */
1382:
1383: rtx
1384: expand_unop (mode, unoptab, op0, target, unsignedp)
1385: enum machine_mode mode;
1386: optab unoptab;
1387: rtx op0;
1388: rtx target;
1389: int unsignedp;
1390: {
1391: enum mode_class class;
1392: enum machine_mode wider_mode;
1393: register rtx temp;
1394: rtx last = get_last_insn ();
1395: rtx pat;
1396:
1397: class = GET_MODE_CLASS (mode);
1398:
1399: op0 = protect_from_queue (op0, 0);
1400:
1401: if (flag_force_mem)
1402: {
1403: op0 = force_not_mem (op0);
1404: }
1405:
1406: if (target)
1407: target = protect_from_queue (target, 1);
1408:
1409: if (unoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1410: {
1411: int icode = (int) unoptab->handlers[(int) mode].insn_code;
1412: enum machine_mode mode0 = insn_operand_mode[icode][1];
1413: rtx xop0 = op0;
1414:
1415: if (target)
1416: temp = target;
1417: else
1418: temp = gen_reg_rtx (mode);
1419:
1420: if (GET_MODE (xop0) != VOIDmode
1421: && GET_MODE (xop0) != mode0)
1422: xop0 = convert_to_mode (mode0, xop0, unsignedp);
1423:
1424: /* Now, if insn doesn't accept our operand, put it into a pseudo. */
1425:
1426: if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))
1427: xop0 = copy_to_mode_reg (mode0, xop0);
1428:
1429: if (! (*insn_operand_predicate[icode][0]) (temp, mode))
1430: temp = gen_reg_rtx (mode);
1431:
1432: pat = GEN_FCN (icode) (temp, xop0);
1433: if (pat)
1434: {
1435: if (GET_CODE (pat) == SEQUENCE
1.1.1.4 ! root 1436: && ! add_equal_note (pat, temp, unoptab->code, xop0, NULL_RTX))
1.1 root 1437: {
1438: delete_insns_since (last);
1.1.1.4 ! root 1439: return expand_unop (mode, unoptab, op0, NULL_RTX, unsignedp);
1.1 root 1440: }
1441:
1442: emit_insn (pat);
1443:
1444: return temp;
1445: }
1446: else
1447: delete_insns_since (last);
1448: }
1449:
1.1.1.4 ! root 1450: /* It can't be done in this mode. Can we open-code it in a wider mode? */
! 1451:
! 1452: if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
! 1453: for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
! 1454: wider_mode = GET_MODE_WIDER_MODE (wider_mode))
! 1455: {
! 1456: if (unoptab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing)
! 1457: {
! 1458: rtx xop0 = op0;
! 1459:
! 1460: /* For certain operations, we need not actually extend
! 1461: the narrow operand, as long as we will truncate the
! 1462: results to the same narrowness. But it is faster to
! 1463: convert a SUBREG due to mode promotion. */
! 1464:
! 1465: if ((unoptab == neg_optab || unoptab == one_cmpl_optab)
! 1466: && GET_MODE_SIZE (wider_mode) <= UNITS_PER_WORD
! 1467: && class == MODE_INT
! 1468: && ! (GET_CODE (xop0) == SUBREG
! 1469: && SUBREG_PROMOTED_VAR_P (xop0)))
! 1470: xop0 = gen_rtx (SUBREG, wider_mode, force_reg (mode, xop0), 0);
! 1471: else
! 1472: xop0 = convert_to_mode (wider_mode, xop0, unsignedp);
! 1473:
! 1474: temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
! 1475: unsignedp);
! 1476:
! 1477: if (temp)
! 1478: {
! 1479: if (class != MODE_INT)
! 1480: {
! 1481: if (target == 0)
! 1482: target = gen_reg_rtx (mode);
! 1483: convert_move (target, temp, 0);
! 1484: return target;
! 1485: }
! 1486: else
! 1487: return gen_lowpart (mode, temp);
! 1488: }
! 1489: else
! 1490: delete_insns_since (last);
! 1491: }
! 1492: }
! 1493:
1.1 root 1494: /* These can be done a word at a time. */
1495: if (unoptab == one_cmpl_optab
1496: && class == MODE_INT
1497: && GET_MODE_SIZE (mode) > UNITS_PER_WORD
1498: && unoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
1499: {
1500: int i;
1501: rtx insns;
1502:
1503: if (target == 0 || target == op0)
1504: target = gen_reg_rtx (mode);
1505:
1506: start_sequence ();
1507:
1508: /* Do the actual arithmetic. */
1509: for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)
1510: {
1511: rtx target_piece = operand_subword (target, i, 1, mode);
1512: rtx x = expand_unop (word_mode, unoptab,
1513: operand_subword_force (op0, i, mode),
1514: target_piece, unsignedp);
1515: if (target_piece != x)
1516: emit_move_insn (target_piece, x);
1517: }
1518:
1519: insns = get_insns ();
1520: end_sequence ();
1521:
1.1.1.4 ! root 1522: emit_no_conflict_block (insns, target, op0, NULL_RTX,
1.1 root 1523: gen_rtx (unoptab->code, mode, op0));
1524: return target;
1525: }
1526:
1.1.1.4 ! root 1527: /* Open-code the complex negation operation. */
! 1528: else if (unoptab == neg_optab
! 1529: && (class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT))
! 1530: {
! 1531: rtx target_piece;
! 1532: rtx x;
! 1533: rtx seq;
! 1534:
! 1535: /* Find the correct mode for the real and imaginary parts */
! 1536: enum machine_mode submode
! 1537: = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT,
! 1538: class == MODE_COMPLEX_INT ? MODE_INT : MODE_FLOAT,
! 1539: 0);
! 1540:
! 1541: if (submode == BLKmode)
! 1542: abort ();
! 1543:
! 1544: if (target == 0)
! 1545: target = gen_reg_rtx (mode);
! 1546:
! 1547: start_sequence ();
! 1548:
! 1549: target_piece = gen_imagpart (submode, target);
! 1550: x = expand_unop (submode, unoptab,
! 1551: gen_imagpart (submode, op0),
! 1552: target_piece, unsignedp);
! 1553: if (target_piece != x)
! 1554: emit_move_insn (target_piece, x);
! 1555:
! 1556: target_piece = gen_realpart (submode, target);
! 1557: x = expand_unop (submode, unoptab,
! 1558: gen_realpart (submode, op0),
! 1559: target_piece, unsignedp);
! 1560: if (target_piece != x)
! 1561: emit_move_insn (target_piece, x);
! 1562:
! 1563: seq = get_insns ();
! 1564: end_sequence ();
! 1565:
! 1566: emit_no_conflict_block (seq, target, op0, 0,
! 1567: gen_rtx (unoptab->code, mode, op0));
! 1568: return target;
! 1569: }
! 1570:
! 1571: /* Now try a library call in this mode. */
1.1 root 1572: if (unoptab->handlers[(int) mode].libfunc)
1573: {
1574: rtx insns;
1575: rtx funexp = unoptab->handlers[(int) mode].libfunc;
1576:
1577: start_sequence ();
1578:
1579: /* Pass 1 for NO_QUEUE so we don't lose any increments
1580: if the libcall is cse'd or moved. */
1581: emit_library_call (unoptab->handlers[(int) mode].libfunc,
1582: 1, mode, 1, op0, mode);
1583: insns = get_insns ();
1584: end_sequence ();
1585:
1586: target = gen_reg_rtx (mode);
1587: emit_libcall_block (insns, target, hard_libcall_value (mode),
1588: gen_rtx (unoptab->code, mode, op0));
1589:
1590: return target;
1591: }
1592:
1593: /* It can't be done in this mode. Can we do it in a wider mode? */
1594:
1595: if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
1596: {
1597: for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
1598: wider_mode = GET_MODE_WIDER_MODE (wider_mode))
1599: {
1600: if ((unoptab->handlers[(int) wider_mode].insn_code
1601: != CODE_FOR_nothing)
1602: || unoptab->handlers[(int) wider_mode].libfunc)
1603: {
1604: rtx xop0 = op0;
1605:
1606: /* For certain operations, we need not actually extend
1607: the narrow operand, as long as we will truncate the
1608: results to the same narrowness. */
1609:
1610: if ((unoptab == neg_optab || unoptab == one_cmpl_optab)
1.1.1.4 ! root 1611: && GET_MODE_SIZE (wider_mode) <= UNITS_PER_WORD
! 1612: && class == MODE_INT
! 1613: && ! (GET_CODE (xop0) == SUBREG
! 1614: && SUBREG_PROMOTED_VAR_P (xop0)))
1.1 root 1615: xop0 = gen_rtx (SUBREG, wider_mode, force_reg (mode, xop0), 0);
1616: else
1617: xop0 = convert_to_mode (wider_mode, xop0, unsignedp);
1618:
1.1.1.4 ! root 1619: temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
! 1620: unsignedp);
1.1 root 1621:
1622: if (temp)
1623: {
1624: if (class != MODE_INT)
1625: {
1626: if (target == 0)
1627: target = gen_reg_rtx (mode);
1628: convert_move (target, temp, 0);
1629: return target;
1630: }
1631: else
1632: return gen_lowpart (mode, temp);
1633: }
1634: else
1635: delete_insns_since (last);
1636: }
1637: }
1638: }
1639:
1640: return 0;
1641: }
1642:
1.1.1.4 ! root 1643: /* Emit code to compute the absolute value of OP0, with result to
! 1644: TARGET if convenient. (TARGET may be 0.) The return value says
! 1645: where the result actually is to be found.
! 1646:
! 1647: MODE is the mode of the operand; the mode of the result is
! 1648: different but can be deduced from MODE.
! 1649:
! 1650: UNSIGNEDP is relevant for complex integer modes. */
! 1651:
! 1652: rtx
! 1653: expand_complex_abs (mode, op0, target, unsignedp)
! 1654: enum machine_mode mode;
! 1655: rtx op0;
! 1656: rtx target;
! 1657: int unsignedp;
! 1658: {
! 1659: enum mode_class class = GET_MODE_CLASS (mode);
! 1660: enum machine_mode wider_mode;
! 1661: register rtx temp;
! 1662: rtx entry_last = get_last_insn ();
! 1663: rtx last;
! 1664: rtx pat;
! 1665:
! 1666: /* Find the correct mode for the real and imaginary parts. */
! 1667: enum machine_mode submode
! 1668: = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT,
! 1669: class == MODE_COMPLEX_INT ? MODE_INT : MODE_FLOAT,
! 1670: 0);
! 1671:
! 1672: if (submode == BLKmode)
! 1673: abort ();
! 1674:
! 1675: op0 = protect_from_queue (op0, 0);
! 1676:
! 1677: if (flag_force_mem)
! 1678: {
! 1679: op0 = force_not_mem (op0);
! 1680: }
! 1681:
! 1682: last = get_last_insn ();
! 1683:
! 1684: if (target)
! 1685: target = protect_from_queue (target, 1);
! 1686:
! 1687: if (abs_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
! 1688: {
! 1689: int icode = (int) abs_optab->handlers[(int) mode].insn_code;
! 1690: enum machine_mode mode0 = insn_operand_mode[icode][1];
! 1691: rtx xop0 = op0;
! 1692:
! 1693: if (target)
! 1694: temp = target;
! 1695: else
! 1696: temp = gen_reg_rtx (submode);
! 1697:
! 1698: if (GET_MODE (xop0) != VOIDmode
! 1699: && GET_MODE (xop0) != mode0)
! 1700: xop0 = convert_to_mode (mode0, xop0, unsignedp);
! 1701:
! 1702: /* Now, if insn doesn't accept our operand, put it into a pseudo. */
! 1703:
! 1704: if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))
! 1705: xop0 = copy_to_mode_reg (mode0, xop0);
! 1706:
! 1707: if (! (*insn_operand_predicate[icode][0]) (temp, submode))
! 1708: temp = gen_reg_rtx (submode);
! 1709:
! 1710: pat = GEN_FCN (icode) (temp, xop0);
! 1711: if (pat)
! 1712: {
! 1713: if (GET_CODE (pat) == SEQUENCE
! 1714: && ! add_equal_note (pat, temp, abs_optab->code, xop0, NULL_RTX))
! 1715: {
! 1716: delete_insns_since (last);
! 1717: return expand_unop (mode, abs_optab, op0, NULL_RTX, unsignedp);
! 1718: }
! 1719:
! 1720: emit_insn (pat);
! 1721:
! 1722: return temp;
! 1723: }
! 1724: else
! 1725: delete_insns_since (last);
! 1726: }
! 1727:
! 1728: /* It can't be done in this mode. Can we open-code it in a wider mode? */
! 1729:
! 1730: for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
! 1731: wider_mode = GET_MODE_WIDER_MODE (wider_mode))
! 1732: {
! 1733: if (abs_optab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing)
! 1734: {
! 1735: rtx xop0 = op0;
! 1736:
! 1737: xop0 = convert_to_mode (wider_mode, xop0, unsignedp);
! 1738: temp = expand_complex_abs (wider_mode, xop0, NULL_RTX, unsignedp);
! 1739:
! 1740: if (temp)
! 1741: {
! 1742: if (class != MODE_COMPLEX_INT)
! 1743: {
! 1744: if (target == 0)
! 1745: target = gen_reg_rtx (submode);
! 1746: convert_move (target, temp, 0);
! 1747: return target;
! 1748: }
! 1749: else
! 1750: return gen_lowpart (submode, temp);
! 1751: }
! 1752: else
! 1753: delete_insns_since (last);
! 1754: }
! 1755: }
! 1756:
! 1757: /* Open-code the complex absolute-value operation
! 1758: if we can open-code sqrt. Otherwise it's not worth while. */
! 1759: if (sqrt_optab->handlers[(int) submode].insn_code != CODE_FOR_nothing)
! 1760: {
! 1761: rtx real, imag, total;
! 1762:
! 1763: real = gen_realpart (submode, op0);
! 1764: imag = gen_imagpart (submode, op0);
! 1765: /* Square both parts. */
! 1766: real = expand_mult (mode, real, real, NULL_RTX, 0);
! 1767: imag = expand_mult (mode, imag, imag, NULL_RTX, 0);
! 1768: /* Sum the parts. */
! 1769: total = expand_binop (submode, add_optab, real, imag, 0,
! 1770: 0, OPTAB_LIB_WIDEN);
! 1771: /* Get sqrt in TARGET. Set TARGET to where the result is. */
! 1772: target = expand_unop (submode, sqrt_optab, total, target, 0);
! 1773: if (target == 0)
! 1774: delete_insns_since (last);
! 1775: else
! 1776: return target;
! 1777: }
! 1778:
! 1779: /* Now try a library call in this mode. */
! 1780: if (abs_optab->handlers[(int) mode].libfunc)
! 1781: {
! 1782: rtx insns;
! 1783: rtx funexp = abs_optab->handlers[(int) mode].libfunc;
! 1784:
! 1785: start_sequence ();
! 1786:
! 1787: /* Pass 1 for NO_QUEUE so we don't lose any increments
! 1788: if the libcall is cse'd or moved. */
! 1789: emit_library_call (abs_optab->handlers[(int) mode].libfunc,
! 1790: 1, mode, 1, op0, mode);
! 1791: insns = get_insns ();
! 1792: end_sequence ();
! 1793:
! 1794: target = gen_reg_rtx (submode);
! 1795: emit_libcall_block (insns, target, hard_libcall_value (submode),
! 1796: gen_rtx (abs_optab->code, mode, op0));
! 1797:
! 1798: return target;
! 1799: }
! 1800:
! 1801: /* It can't be done in this mode. Can we do it in a wider mode? */
! 1802:
! 1803: for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
! 1804: wider_mode = GET_MODE_WIDER_MODE (wider_mode))
! 1805: {
! 1806: if ((abs_optab->handlers[(int) wider_mode].insn_code
! 1807: != CODE_FOR_nothing)
! 1808: || abs_optab->handlers[(int) wider_mode].libfunc)
! 1809: {
! 1810: rtx xop0 = op0;
! 1811:
! 1812: xop0 = convert_to_mode (wider_mode, xop0, unsignedp);
! 1813:
! 1814: temp = expand_complex_abs (wider_mode, xop0, NULL_RTX, unsignedp);
! 1815:
! 1816: if (temp)
! 1817: {
! 1818: if (class != MODE_COMPLEX_INT)
! 1819: {
! 1820: if (target == 0)
! 1821: target = gen_reg_rtx (submode);
! 1822: convert_move (target, temp, 0);
! 1823: return target;
! 1824: }
! 1825: else
! 1826: return gen_lowpart (submode, temp);
! 1827: }
! 1828: else
! 1829: delete_insns_since (last);
! 1830: }
! 1831: }
! 1832:
! 1833: delete_insns_since (entry_last);
! 1834: return 0;
! 1835: }
! 1836:
1.1 root 1837: /* Generate an instruction whose insn-code is INSN_CODE,
1838: with two operands: an output TARGET and an input OP0.
1839: TARGET *must* be nonzero, and the output is always stored there.
1840: CODE is an rtx code such that (CODE OP0) is an rtx that describes
1841: the value that is stored into TARGET. */
1842:
1843: void
1844: emit_unop_insn (icode, target, op0, code)
1845: int icode;
1846: rtx target;
1847: rtx op0;
1848: enum rtx_code code;
1849: {
1850: register rtx temp;
1851: enum machine_mode mode0 = insn_operand_mode[icode][1];
1852: rtx pat;
1853:
1854: temp = target = protect_from_queue (target, 1);
1855:
1856: op0 = protect_from_queue (op0, 0);
1857:
1858: if (flag_force_mem)
1859: op0 = force_not_mem (op0);
1860:
1861: /* Now, if insn does not accept our operands, put them into pseudos. */
1862:
1863: if (! (*insn_operand_predicate[icode][1]) (op0, mode0))
1864: op0 = copy_to_mode_reg (mode0, op0);
1865:
1866: if (! (*insn_operand_predicate[icode][0]) (temp, GET_MODE (temp))
1867: || (flag_force_mem && GET_CODE (temp) == MEM))
1868: temp = gen_reg_rtx (GET_MODE (temp));
1869:
1870: pat = GEN_FCN (icode) (temp, op0);
1871:
1872: if (GET_CODE (pat) == SEQUENCE && code != UNKNOWN)
1.1.1.4 ! root 1873: add_equal_note (pat, temp, code, op0, NULL_RTX);
1.1 root 1874:
1875: emit_insn (pat);
1876:
1877: if (temp != target)
1878: emit_move_insn (target, temp);
1879: }
1880:
1881: /* Emit code to perform a series of operations on a multi-word quantity, one
1882: word at a time.
1883:
1.1.1.2 root 1884: Such a block is preceded by a CLOBBER of the output, consists of multiple
1.1 root 1885: insns, each setting one word of the output, and followed by a SET copying
1886: the output to itself.
1887:
1888: Each of the insns setting words of the output receives a REG_NO_CONFLICT
1889: note indicating that it doesn't conflict with the (also multi-word)
1890: inputs. The entire block is surrounded by REG_LIBCALL and REG_RETVAL
1891: notes.
1892:
1893: INSNS is a block of code generated to perform the operation, not including
1894: the CLOBBER and final copy. All insns that compute intermediate values
1895: are first emitted, followed by the block as described above. Only
1896: INSNs are allowed in the block; no library calls or jumps may be
1897: present.
1898:
1899: TARGET, OP0, and OP1 are the output and inputs of the operations,
1900: respectively. OP1 may be zero for a unary operation.
1901:
1902: EQUIV, if non-zero, is an expression to be placed into a REG_EQUAL note
1903: on the last insn.
1904:
1905: If TARGET is not a register, INSNS is simply emitted with no special
1906: processing.
1907:
1908: The final insn emitted is returned. */
1909:
1910: rtx
1911: emit_no_conflict_block (insns, target, op0, op1, equiv)
1912: rtx insns;
1913: rtx target;
1914: rtx op0, op1;
1915: rtx equiv;
1916: {
1917: rtx prev, next, first, last, insn;
1918:
1919: if (GET_CODE (target) != REG || reload_in_progress)
1920: return emit_insns (insns);
1921:
1922: /* First emit all insns that do not store into words of the output and remove
1923: these from the list. */
1924: for (insn = insns; insn; insn = next)
1925: {
1926: rtx set = 0;
1927: int i;
1928:
1929: next = NEXT_INSN (insn);
1930:
1931: if (GET_CODE (insn) != INSN)
1932: abort ();
1933:
1934: if (GET_CODE (PATTERN (insn)) == SET)
1935: set = PATTERN (insn);
1936: else if (GET_CODE (PATTERN (insn)) == PARALLEL)
1937: {
1938: for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
1939: if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET)
1940: {
1941: set = XVECEXP (PATTERN (insn), 0, i);
1942: break;
1943: }
1944: }
1945:
1946: if (set == 0)
1947: abort ();
1948:
1949: if (! reg_overlap_mentioned_p (target, SET_DEST (set)))
1950: {
1951: if (PREV_INSN (insn))
1952: NEXT_INSN (PREV_INSN (insn)) = next;
1953: else
1954: insns = next;
1955:
1956: if (next)
1957: PREV_INSN (next) = PREV_INSN (insn);
1958:
1959: add_insn (insn);
1960: }
1961: }
1962:
1963: prev = get_last_insn ();
1964:
1965: /* Now write the CLOBBER of the output, followed by the setting of each
1966: of the words, followed by the final copy. */
1967: if (target != op0 && target != op1)
1968: emit_insn (gen_rtx (CLOBBER, VOIDmode, target));
1969:
1970: for (insn = insns; insn; insn = next)
1971: {
1972: next = NEXT_INSN (insn);
1973: add_insn (insn);
1974:
1975: if (op1 && GET_CODE (op1) == REG)
1976: REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_NO_CONFLICT, op1,
1977: REG_NOTES (insn));
1978:
1979: if (op0 && GET_CODE (op0) == REG)
1980: REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_NO_CONFLICT, op0,
1981: REG_NOTES (insn));
1982: }
1983:
1984: last = emit_move_insn (target, target);
1985: if (equiv)
1986: REG_NOTES (last) = gen_rtx (EXPR_LIST, REG_EQUAL, equiv, REG_NOTES (last));
1987:
1988: if (prev == 0)
1989: first = get_insns ();
1990: else
1991: first = NEXT_INSN (prev);
1992:
1993: /* Encapsulate the block so it gets manipulated as a unit. */
1994: REG_NOTES (first) = gen_rtx (INSN_LIST, REG_LIBCALL, last,
1995: REG_NOTES (first));
1996: REG_NOTES (last) = gen_rtx (INSN_LIST, REG_RETVAL, first, REG_NOTES (last));
1997:
1998: return last;
1999: }
2000:
2001: /* Emit code to make a call to a constant function or a library call.
2002:
2003: INSNS is a list containing all insns emitted in the call.
2004: These insns leave the result in RESULT. Our block is to copy RESULT
2005: to TARGET, which is logically equivalent to EQUIV.
2006:
2007: We first emit any insns that set a pseudo on the assumption that these are
2008: loading constants into registers; doing so allows them to be safely cse'ed
2009: between blocks. Then we emit all the other insns in the block, followed by
2010: an insn to move RESULT to TARGET. This last insn will have a REQ_EQUAL
2011: note with an operand of EQUIV.
2012:
1.1.1.3 root 2013: Moving assignments to pseudos outside of the block is done to improve
2014: the generated code, but is not required to generate correct code,
2015: hence being unable to move an assignment is not grounds for not making
2016: a libcall block. There are two reasons why it is safe to leave these
2017: insns inside the block: First, we know that these pseudos cannot be
2018: used in generated RTL outside the block since they are created for
2019: temporary purposes within the block. Second, CSE will not record the
2020: values of anything set inside a libcall block, so we know they must
2021: be dead at the end of the block.
2022:
1.1 root 2023: Except for the first group of insns (the ones setting pseudos), the
2024: block is delimited by REG_RETVAL and REG_LIBCALL notes. */
2025:
2026: void
2027: emit_libcall_block (insns, target, result, equiv)
2028: rtx insns;
2029: rtx target;
2030: rtx result;
2031: rtx equiv;
2032: {
2033: rtx prev, next, first, last, insn;
2034:
2035: /* First emit all insns that set pseudos. Remove them from the list as
1.1.1.3 root 2036: we go. Avoid insns that set pseudo which were referenced in previous
2037: insns. These can be generated by move_by_pieces, for example,
2038: to update an address. */
1.1 root 2039:
2040: for (insn = insns; insn; insn = next)
2041: {
2042: rtx set = single_set (insn);
2043:
2044: next = NEXT_INSN (insn);
2045:
2046: if (set != 0 && GET_CODE (SET_DEST (set)) == REG
1.1.1.3 root 2047: && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER
2048: && (insn == insns
2049: || (! reg_mentioned_p (SET_DEST (set), PATTERN (insns))
2050: && ! reg_used_between_p (SET_DEST (set), insns, insn))))
1.1 root 2051: {
2052: if (PREV_INSN (insn))
2053: NEXT_INSN (PREV_INSN (insn)) = next;
2054: else
2055: insns = next;
2056:
2057: if (next)
2058: PREV_INSN (next) = PREV_INSN (insn);
2059:
2060: add_insn (insn);
2061: }
2062: }
2063:
2064: prev = get_last_insn ();
2065:
2066: /* Write the remaining insns followed by the final copy. */
2067:
2068: for (insn = insns; insn; insn = next)
2069: {
2070: next = NEXT_INSN (insn);
2071:
2072: add_insn (insn);
2073: }
2074:
2075: last = emit_move_insn (target, result);
2076: REG_NOTES (last) = gen_rtx (EXPR_LIST, REG_EQUAL, equiv, REG_NOTES (last));
2077:
2078: if (prev == 0)
2079: first = get_insns ();
2080: else
2081: first = NEXT_INSN (prev);
2082:
2083: /* Encapsulate the block so it gets manipulated as a unit. */
2084: REG_NOTES (first) = gen_rtx (INSN_LIST, REG_LIBCALL, last,
2085: REG_NOTES (first));
2086: REG_NOTES (last) = gen_rtx (INSN_LIST, REG_RETVAL, first, REG_NOTES (last));
2087: }
2088:
2089: /* Generate code to store zero in X. */
2090:
2091: void
2092: emit_clr_insn (x)
2093: rtx x;
2094: {
2095: emit_move_insn (x, const0_rtx);
2096: }
2097:
2098: /* Generate code to store 1 in X
2099: assuming it contains zero beforehand. */
2100:
2101: void
2102: emit_0_to_1_insn (x)
2103: rtx x;
2104: {
2105: emit_move_insn (x, const1_rtx);
2106: }
2107:
2108: /* Generate code to compare X with Y
2109: so that the condition codes are set.
2110:
2111: MODE is the mode of the inputs (in case they are const_int).
2112: UNSIGNEDP nonzero says that X and Y are unsigned;
2113: this matters if they need to be widened.
2114:
2115: If they have mode BLKmode, then SIZE specifies the size of both X and Y,
2116: and ALIGN specifies the known shared alignment of X and Y.
2117:
2118: COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).
2119: It is ignored for fixed-point and block comparisons;
2120: it is used only for floating-point comparisons. */
2121:
2122: void
2123: emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align)
2124: rtx x, y;
2125: enum rtx_code comparison;
2126: rtx size;
1.1.1.3 root 2127: enum machine_mode mode;
1.1 root 2128: int unsignedp;
2129: int align;
2130: {
2131: enum mode_class class;
2132: enum machine_mode wider_mode;
2133:
2134: class = GET_MODE_CLASS (mode);
2135:
2136: /* They could both be VOIDmode if both args are immediate constants,
2137: but we should fold that at an earlier stage.
2138: With no special code here, this will call abort,
2139: reminding the programmer to implement such folding. */
2140:
2141: if (mode != BLKmode && flag_force_mem)
2142: {
2143: x = force_not_mem (x);
2144: y = force_not_mem (y);
2145: }
2146:
2147: /* If we are inside an appropriately-short loop and one operand is an
2148: expensive constant, force it into a register. */
1.1.1.3 root 2149: if (CONSTANT_P (x) && preserve_subexpressions_p () && rtx_cost (x, COMPARE) > 2)
1.1 root 2150: x = force_reg (mode, x);
2151:
1.1.1.3 root 2152: if (CONSTANT_P (y) && preserve_subexpressions_p () && rtx_cost (y, COMPARE) > 2)
1.1 root 2153: y = force_reg (mode, y);
2154:
2155: /* Don't let both operands fail to indicate the mode. */
2156: if (GET_MODE (x) == VOIDmode && GET_MODE (y) == VOIDmode)
2157: x = force_reg (mode, x);
2158:
2159: /* Handle all BLKmode compares. */
2160:
2161: if (mode == BLKmode)
2162: {
2163: emit_queue ();
2164: x = protect_from_queue (x, 0);
2165: y = protect_from_queue (y, 0);
2166:
2167: if (size == 0)
2168: abort ();
2169: #ifdef HAVE_cmpstrqi
2170: if (HAVE_cmpstrqi
2171: && GET_CODE (size) == CONST_INT
2172: && INTVAL (size) < (1 << GET_MODE_BITSIZE (QImode)))
2173: {
2174: enum machine_mode result_mode
2175: = insn_operand_mode[(int) CODE_FOR_cmpstrqi][0];
2176: rtx result = gen_reg_rtx (result_mode);
1.1.1.4 ! root 2177: emit_insn (gen_cmpstrqi (result, x, y, size, GEN_INT (align)));
! 2178: emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX,
! 2179: result_mode, 0, 0);
1.1 root 2180: }
2181: else
2182: #endif
2183: #ifdef HAVE_cmpstrhi
2184: if (HAVE_cmpstrhi
2185: && GET_CODE (size) == CONST_INT
2186: && INTVAL (size) < (1 << GET_MODE_BITSIZE (HImode)))
2187: {
2188: enum machine_mode result_mode
2189: = insn_operand_mode[(int) CODE_FOR_cmpstrhi][0];
2190: rtx result = gen_reg_rtx (result_mode);
1.1.1.4 ! root 2191: emit_insn (gen_cmpstrhi (result, x, y, size, GEN_INT (align)));
! 2192: emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX,
! 2193: result_mode, 0, 0);
1.1 root 2194: }
2195: else
2196: #endif
2197: #ifdef HAVE_cmpstrsi
2198: if (HAVE_cmpstrsi)
2199: {
2200: enum machine_mode result_mode
2201: = insn_operand_mode[(int) CODE_FOR_cmpstrsi][0];
2202: rtx result = gen_reg_rtx (result_mode);
1.1.1.4 ! root 2203: size = protect_from_queue (size, 0);
1.1 root 2204: emit_insn (gen_cmpstrsi (result, x, y,
2205: convert_to_mode (SImode, size, 1),
1.1.1.4 ! root 2206: GEN_INT (align)));
! 2207: emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX,
! 2208: result_mode, 0, 0);
1.1 root 2209: }
2210: else
2211: #endif
2212: {
2213: #ifdef TARGET_MEM_FUNCTIONS
1.1.1.4 ! root 2214: emit_library_call (memcmp_libfunc, 0,
1.1 root 2215: TYPE_MODE (integer_type_node), 3,
2216: XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
2217: size, Pmode);
2218: #else
1.1.1.4 ! root 2219: emit_library_call (bcmp_libfunc, 0,
1.1 root 2220: TYPE_MODE (integer_type_node), 3,
2221: XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
2222: size, Pmode);
2223: #endif
2224: emit_cmp_insn (hard_libcall_value (TYPE_MODE (integer_type_node)),
1.1.1.4 ! root 2225: const0_rtx, comparison, NULL_RTX,
1.1 root 2226: TYPE_MODE (integer_type_node), 0, 0);
2227: }
2228: return;
2229: }
2230:
2231: /* Handle some compares against zero. */
2232:
2233: if (y == CONST0_RTX (mode)
2234: && tst_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
2235: {
2236: int icode = (int) tst_optab->handlers[(int) mode].insn_code;
2237:
2238: emit_queue ();
2239: x = protect_from_queue (x, 0);
2240: y = protect_from_queue (y, 0);
2241:
2242: /* Now, if insn does accept these operands, put them into pseudos. */
2243: if (! (*insn_operand_predicate[icode][0])
2244: (x, insn_operand_mode[icode][0]))
2245: x = copy_to_mode_reg (insn_operand_mode[icode][0], x);
2246:
2247: emit_insn (GEN_FCN (icode) (x));
2248: return;
2249: }
2250:
2251: /* Handle compares for which there is a directly suitable insn. */
2252:
2253: if (cmp_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
2254: {
2255: int icode = (int) cmp_optab->handlers[(int) mode].insn_code;
2256:
2257: emit_queue ();
2258: x = protect_from_queue (x, 0);
2259: y = protect_from_queue (y, 0);
2260:
2261: /* Now, if insn doesn't accept these operands, put them into pseudos. */
2262: if (! (*insn_operand_predicate[icode][0])
2263: (x, insn_operand_mode[icode][0]))
2264: x = copy_to_mode_reg (insn_operand_mode[icode][0], x);
2265:
2266: if (! (*insn_operand_predicate[icode][1])
2267: (y, insn_operand_mode[icode][1]))
2268: y = copy_to_mode_reg (insn_operand_mode[icode][1], y);
2269:
2270: emit_insn (GEN_FCN (icode) (x, y));
2271: return;
2272: }
2273:
2274: /* Try widening if we can find a direct insn that way. */
2275:
2276: if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
2277: {
2278: for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
2279: wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2280: {
2281: if (cmp_optab->handlers[(int) wider_mode].insn_code
2282: != CODE_FOR_nothing)
2283: {
1.1.1.4 ! root 2284: x = protect_from_queue (x, 0);
! 2285: y = protect_from_queue (y, 0);
1.1 root 2286: x = convert_to_mode (wider_mode, x, unsignedp);
2287: y = convert_to_mode (wider_mode, y, unsignedp);
1.1.1.4 ! root 2288: emit_cmp_insn (x, y, comparison, NULL_RTX,
1.1 root 2289: wider_mode, unsignedp, align);
2290: return;
2291: }
2292: }
2293: }
2294:
2295: /* Handle a lib call just for the mode we are using. */
2296:
2297: if (cmp_optab->handlers[(int) mode].libfunc
2298: && class != MODE_FLOAT)
2299: {
2300: rtx libfunc = cmp_optab->handlers[(int) mode].libfunc;
2301: /* If we want unsigned, and this mode has a distinct unsigned
2302: comparison routine, use that. */
2303: if (unsignedp && ucmp_optab->handlers[(int) mode].libfunc)
2304: libfunc = ucmp_optab->handlers[(int) mode].libfunc;
2305:
1.1.1.2 root 2306: emit_library_call (libfunc, 1,
1.1 root 2307: SImode, 2, x, mode, y, mode);
2308:
2309: /* Integer comparison returns a result that must be compared against 1,
2310: so that even if we do an unsigned compare afterward,
2311: there is still a value that can represent the result "less than". */
2312:
2313: emit_cmp_insn (hard_libcall_value (SImode), const1_rtx,
1.1.1.4 ! root 2314: comparison, NULL_RTX, SImode, unsignedp, 0);
1.1 root 2315: return;
2316: }
2317:
2318: if (class == MODE_FLOAT)
2319: emit_float_lib_cmp (x, y, comparison);
2320:
2321: else
2322: abort ();
2323: }
2324:
2325: /* Nonzero if a compare of mode MODE can be done straightforwardly
2326: (without splitting it into pieces). */
2327:
2328: int
2329: can_compare_p (mode)
2330: enum machine_mode mode;
2331: {
2332: do
2333: {
2334: if (cmp_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)
2335: return 1;
2336: mode = GET_MODE_WIDER_MODE (mode);
2337: } while (mode != VOIDmode);
2338:
2339: return 0;
2340: }
2341:
2342: /* Emit a library call comparison between floating point X and Y.
2343: COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). */
2344:
2345: static void
2346: emit_float_lib_cmp (x, y, comparison)
2347: rtx x, y;
2348: enum rtx_code comparison;
2349: {
2350: enum machine_mode mode = GET_MODE (x);
2351: rtx libfunc;
2352:
2353: if (mode == SFmode)
2354: switch (comparison)
2355: {
2356: case EQ:
2357: libfunc = eqsf2_libfunc;
2358: break;
2359:
2360: case NE:
2361: libfunc = nesf2_libfunc;
2362: break;
2363:
2364: case GT:
2365: libfunc = gtsf2_libfunc;
2366: break;
2367:
2368: case GE:
2369: libfunc = gesf2_libfunc;
2370: break;
2371:
2372: case LT:
2373: libfunc = ltsf2_libfunc;
2374: break;
2375:
2376: case LE:
2377: libfunc = lesf2_libfunc;
2378: break;
2379: }
2380: else if (mode == DFmode)
2381: switch (comparison)
2382: {
2383: case EQ:
2384: libfunc = eqdf2_libfunc;
2385: break;
2386:
2387: case NE:
2388: libfunc = nedf2_libfunc;
2389: break;
2390:
2391: case GT:
2392: libfunc = gtdf2_libfunc;
2393: break;
2394:
2395: case GE:
2396: libfunc = gedf2_libfunc;
2397: break;
2398:
2399: case LT:
2400: libfunc = ltdf2_libfunc;
2401: break;
2402:
2403: case LE:
2404: libfunc = ledf2_libfunc;
2405: break;
2406: }
1.1.1.4 ! root 2407: else if (mode == XFmode)
! 2408: switch (comparison)
! 2409: {
! 2410: case EQ:
! 2411: libfunc = eqxf2_libfunc;
! 2412: break;
! 2413:
! 2414: case NE:
! 2415: libfunc = nexf2_libfunc;
! 2416: break;
! 2417:
! 2418: case GT:
! 2419: libfunc = gtxf2_libfunc;
! 2420: break;
! 2421:
! 2422: case GE:
! 2423: libfunc = gexf2_libfunc;
! 2424: break;
! 2425:
! 2426: case LT:
! 2427: libfunc = ltxf2_libfunc;
! 2428: break;
! 2429:
! 2430: case LE:
! 2431: libfunc = lexf2_libfunc;
! 2432: break;
! 2433: }
! 2434: else if (mode == TFmode)
! 2435: switch (comparison)
! 2436: {
! 2437: case EQ:
! 2438: libfunc = eqtf2_libfunc;
! 2439: break;
! 2440:
! 2441: case NE:
! 2442: libfunc = netf2_libfunc;
! 2443: break;
! 2444:
! 2445: case GT:
! 2446: libfunc = gttf2_libfunc;
! 2447: break;
! 2448:
! 2449: case GE:
! 2450: libfunc = getf2_libfunc;
! 2451: break;
! 2452:
! 2453: case LT:
! 2454: libfunc = lttf2_libfunc;
! 2455: break;
! 2456:
! 2457: case LE:
! 2458: libfunc = letf2_libfunc;
! 2459: break;
! 2460: }
1.1 root 2461: else
2462: {
2463: enum machine_mode wider_mode;
2464:
2465: for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
2466: wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2467: {
2468: if ((cmp_optab->handlers[(int) wider_mode].insn_code
2469: != CODE_FOR_nothing)
2470: || (cmp_optab->handlers[(int) wider_mode].libfunc != 0))
2471: {
1.1.1.4 ! root 2472: x = protect_from_queue (x, 0);
! 2473: y = protect_from_queue (y, 0);
1.1 root 2474: x = convert_to_mode (wider_mode, x, 0);
2475: y = convert_to_mode (wider_mode, y, 0);
2476: emit_float_lib_cmp (x, y, comparison);
2477: return;
2478: }
2479: }
2480: abort ();
2481: }
2482:
1.1.1.2 root 2483: emit_library_call (libfunc, 1,
1.1 root 2484: SImode, 2, x, mode, y, mode);
2485:
2486: emit_cmp_insn (hard_libcall_value (SImode), const0_rtx, comparison,
1.1.1.4 ! root 2487: NULL_RTX, SImode, 0, 0);
1.1 root 2488: }
2489:
2490: /* Generate code to indirectly jump to a location given in the rtx LOC. */
2491:
2492: void
2493: emit_indirect_jump (loc)
2494: rtx loc;
2495: {
2496: if (! ((*insn_operand_predicate[(int)CODE_FOR_indirect_jump][0])
2497: (loc, VOIDmode)))
2498: loc = copy_to_mode_reg (insn_operand_mode[(int)CODE_FOR_indirect_jump][0],
2499: loc);
2500:
2501: emit_jump_insn (gen_indirect_jump (loc));
1.1.1.3 root 2502: emit_barrier ();
1.1 root 2503: }
2504:
2505: /* These three functions generate an insn body and return it
2506: rather than emitting the insn.
2507:
2508: They do not protect from queued increments,
2509: because they may be used 1) in protect_from_queue itself
2510: and 2) in other passes where there is no queue. */
2511:
2512: /* Generate and return an insn body to add Y to X. */
2513:
2514: rtx
2515: gen_add2_insn (x, y)
2516: rtx x, y;
2517: {
2518: int icode = (int) add_optab->handlers[(int) GET_MODE (x)].insn_code;
2519:
2520: if (! (*insn_operand_predicate[icode][0]) (x, insn_operand_mode[icode][0])
2521: || ! (*insn_operand_predicate[icode][1]) (x, insn_operand_mode[icode][1])
2522: || ! (*insn_operand_predicate[icode][2]) (y, insn_operand_mode[icode][2]))
2523: abort ();
2524:
2525: return (GEN_FCN (icode) (x, x, y));
2526: }
2527:
2528: int
2529: have_add2_insn (mode)
2530: enum machine_mode mode;
2531: {
2532: return add_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing;
2533: }
2534:
2535: /* Generate and return an insn body to subtract Y from X. */
2536:
2537: rtx
2538: gen_sub2_insn (x, y)
2539: rtx x, y;
2540: {
2541: int icode = (int) sub_optab->handlers[(int) GET_MODE (x)].insn_code;
2542:
2543: if (! (*insn_operand_predicate[icode][0]) (x, insn_operand_mode[icode][0])
2544: || ! (*insn_operand_predicate[icode][1]) (x, insn_operand_mode[icode][1])
2545: || ! (*insn_operand_predicate[icode][2]) (y, insn_operand_mode[icode][2]))
2546: abort ();
2547:
2548: return (GEN_FCN (icode) (x, x, y));
2549: }
2550:
2551: int
2552: have_sub2_insn (mode)
2553: enum machine_mode mode;
2554: {
2555: return sub_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing;
2556: }
2557:
2558: /* Generate the body of an instruction to copy Y into X. */
2559:
2560: rtx
2561: gen_move_insn (x, y)
2562: rtx x, y;
2563: {
2564: register enum machine_mode mode = GET_MODE (x);
2565: enum insn_code insn_code;
2566:
2567: if (mode == VOIDmode)
2568: mode = GET_MODE (y);
2569:
2570: insn_code = mov_optab->handlers[(int) mode].insn_code;
2571:
2572: /* Handle MODE_CC modes: If we don't have a special move insn for this mode,
2573: find a mode to do it in. If we have a movcc, use it. Otherwise,
2574: find the MODE_INT mode of the same width. */
2575:
2576: if (insn_code == CODE_FOR_nothing)
2577: {
2578: enum machine_mode tmode = VOIDmode;
2579: rtx x1 = x, y1 = y;
2580:
2581: if (GET_MODE_CLASS (mode) == MODE_CC && mode != CCmode
2582: && mov_optab->handlers[(int) CCmode].insn_code != CODE_FOR_nothing)
2583: tmode = CCmode;
2584: else if (GET_MODE_CLASS (mode) == MODE_CC)
2585: for (tmode = QImode; tmode != VOIDmode;
2586: tmode = GET_MODE_WIDER_MODE (tmode))
2587: if (GET_MODE_SIZE (tmode) == GET_MODE_SIZE (mode))
2588: break;
2589:
2590: if (tmode == VOIDmode)
2591: abort ();
2592:
2593: /* Get X and Y in TMODE. We can't use gen_lowpart here because it
2594: may call change_address which is not appropriate if we were
2595: called when a reload was in progress. We don't have to worry
2596: about changing the address since the size in bytes is supposed to
2597: be the same. Copy the MEM to change the mode and move any
2598: substitutions from the old MEM to the new one. */
2599:
2600: if (reload_in_progress)
2601: {
2602: x = gen_lowpart_common (tmode, x1);
2603: if (x == 0 && GET_CODE (x1) == MEM)
2604: {
2605: x = gen_rtx (MEM, tmode, XEXP (x1, 0));
2606: RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (x1);
2607: MEM_IN_STRUCT_P (x) = MEM_IN_STRUCT_P (x1);
2608: MEM_VOLATILE_P (x) = MEM_VOLATILE_P (x1);
2609: copy_replacements (x1, x);
2610: }
2611:
2612: y = gen_lowpart_common (tmode, y1);
2613: if (y == 0 && GET_CODE (y1) == MEM)
2614: {
2615: y = gen_rtx (MEM, tmode, XEXP (y1, 0));
2616: RTX_UNCHANGING_P (y) = RTX_UNCHANGING_P (y1);
2617: MEM_IN_STRUCT_P (y) = MEM_IN_STRUCT_P (y1);
2618: MEM_VOLATILE_P (y) = MEM_VOLATILE_P (y1);
2619: copy_replacements (y1, y);
2620: }
2621: }
2622: else
2623: {
2624: x = gen_lowpart (tmode, x);
2625: y = gen_lowpart (tmode, y);
2626: }
2627:
2628: insn_code = mov_optab->handlers[(int) tmode].insn_code;
2629: }
2630:
2631: return (GEN_FCN (insn_code) (x, y));
2632: }
2633:
2634: /* Tables of patterns for extending one integer mode to another. */
2635: static enum insn_code extendtab[MAX_MACHINE_MODE][MAX_MACHINE_MODE][2];
2636:
2637: /* Return the insn code used to extend FROM_MODE to TO_MODE.
2638: UNSIGNEDP specifies zero-extension instead of sign-extension. If
2639: no such operation exists, CODE_FOR_nothing will be returned. */
2640:
2641: enum insn_code
2642: can_extend_p (to_mode, from_mode, unsignedp)
2643: enum machine_mode to_mode, from_mode;
2644: int unsignedp;
2645: {
2646: return extendtab[(int) to_mode][(int) from_mode][unsignedp];
2647: }
2648:
2649: /* Generate the body of an insn to extend Y (with mode MFROM)
2650: into X (with mode MTO). Do zero-extension if UNSIGNEDP is nonzero. */
2651:
2652: rtx
2653: gen_extend_insn (x, y, mto, mfrom, unsignedp)
2654: rtx x, y;
2655: enum machine_mode mto, mfrom;
2656: int unsignedp;
2657: {
2658: return (GEN_FCN (extendtab[(int) mto][(int) mfrom][unsignedp]) (x, y));
2659: }
2660:
2661: static void
2662: init_extends ()
2663: {
2664: enum insn_code *p;
2665:
2666: for (p = extendtab[0][0];
2667: p < extendtab[0][0] + sizeof extendtab / sizeof extendtab[0][0][0];
2668: p++)
2669: *p = CODE_FOR_nothing;
2670:
2671: #ifdef HAVE_extendditi2
2672: if (HAVE_extendditi2)
2673: extendtab[(int) TImode][(int) DImode][0] = CODE_FOR_extendditi2;
2674: #endif
2675: #ifdef HAVE_extendsiti2
2676: if (HAVE_extendsiti2)
2677: extendtab[(int) TImode][(int) SImode][0] = CODE_FOR_extendsiti2;
2678: #endif
2679: #ifdef HAVE_extendhiti2
2680: if (HAVE_extendhiti2)
2681: extendtab[(int) TImode][(int) HImode][0] = CODE_FOR_extendhiti2;
2682: #endif
2683: #ifdef HAVE_extendqiti2
2684: if (HAVE_extendqiti2)
2685: extendtab[(int) TImode][(int) QImode][0] = CODE_FOR_extendqiti2;
2686: #endif
2687: #ifdef HAVE_extendsidi2
2688: if (HAVE_extendsidi2)
2689: extendtab[(int) DImode][(int) SImode][0] = CODE_FOR_extendsidi2;
2690: #endif
2691: #ifdef HAVE_extendhidi2
2692: if (HAVE_extendhidi2)
2693: extendtab[(int) DImode][(int) HImode][0] = CODE_FOR_extendhidi2;
2694: #endif
2695: #ifdef HAVE_extendqidi2
2696: if (HAVE_extendqidi2)
2697: extendtab[(int) DImode][(int) QImode][0] = CODE_FOR_extendqidi2;
2698: #endif
2699: #ifdef HAVE_extendhisi2
2700: if (HAVE_extendhisi2)
2701: extendtab[(int) SImode][(int) HImode][0] = CODE_FOR_extendhisi2;
2702: #endif
2703: #ifdef HAVE_extendqisi2
2704: if (HAVE_extendqisi2)
2705: extendtab[(int) SImode][(int) QImode][0] = CODE_FOR_extendqisi2;
2706: #endif
2707: #ifdef HAVE_extendqihi2
2708: if (HAVE_extendqihi2)
2709: extendtab[(int) HImode][(int) QImode][0] = CODE_FOR_extendqihi2;
2710: #endif
2711:
2712: #ifdef HAVE_zero_extendditi2
2713: if (HAVE_zero_extendsiti2)
2714: extendtab[(int) TImode][(int) DImode][1] = CODE_FOR_zero_extendditi2;
2715: #endif
2716: #ifdef HAVE_zero_extendsiti2
2717: if (HAVE_zero_extendsiti2)
2718: extendtab[(int) TImode][(int) SImode][1] = CODE_FOR_zero_extendsiti2;
2719: #endif
2720: #ifdef HAVE_zero_extendhiti2
2721: if (HAVE_zero_extendhiti2)
2722: extendtab[(int) TImode][(int) HImode][1] = CODE_FOR_zero_extendhiti2;
2723: #endif
2724: #ifdef HAVE_zero_extendqiti2
2725: if (HAVE_zero_extendqiti2)
2726: extendtab[(int) TImode][(int) QImode][1] = CODE_FOR_zero_extendqiti2;
2727: #endif
2728: #ifdef HAVE_zero_extendsidi2
2729: if (HAVE_zero_extendsidi2)
2730: extendtab[(int) DImode][(int) SImode][1] = CODE_FOR_zero_extendsidi2;
2731: #endif
2732: #ifdef HAVE_zero_extendhidi2
2733: if (HAVE_zero_extendhidi2)
2734: extendtab[(int) DImode][(int) HImode][1] = CODE_FOR_zero_extendhidi2;
2735: #endif
2736: #ifdef HAVE_zero_extendqidi2
2737: if (HAVE_zero_extendqidi2)
2738: extendtab[(int) DImode][(int) QImode][1] = CODE_FOR_zero_extendqidi2;
2739: #endif
2740: #ifdef HAVE_zero_extendhisi2
2741: if (HAVE_zero_extendhisi2)
2742: extendtab[(int) SImode][(int) HImode][1] = CODE_FOR_zero_extendhisi2;
2743: #endif
2744: #ifdef HAVE_zero_extendqisi2
2745: if (HAVE_zero_extendqisi2)
2746: extendtab[(int) SImode][(int) QImode][1] = CODE_FOR_zero_extendqisi2;
2747: #endif
2748: #ifdef HAVE_zero_extendqihi2
2749: if (HAVE_zero_extendqihi2)
2750: extendtab[(int) HImode][(int) QImode][1] = CODE_FOR_zero_extendqihi2;
2751: #endif
2752: }
2753:
2754: /* can_fix_p and can_float_p say whether the target machine
2755: can directly convert a given fixed point type to
2756: a given floating point type, or vice versa.
2757: The returned value is the CODE_FOR_... value to use,
2758: or CODE_FOR_nothing if these modes cannot be directly converted. */
2759:
2760: static enum insn_code fixtab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
2761: static enum insn_code fixtrunctab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
2762: static enum insn_code floattab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
2763:
2764: /* *TRUNCP_PTR is set to 1 if it is necessary to output
2765: an explicit FTRUNC insn before the fix insn; otherwise 0. */
2766:
2767: static enum insn_code
2768: can_fix_p (fixmode, fltmode, unsignedp, truncp_ptr)
2769: enum machine_mode fltmode, fixmode;
2770: int unsignedp;
2771: int *truncp_ptr;
2772: {
2773: *truncp_ptr = 0;
2774: if (fixtrunctab[(int) fltmode][(int) fixmode][unsignedp] != CODE_FOR_nothing)
2775: return fixtrunctab[(int) fltmode][(int) fixmode][unsignedp];
2776:
2777: if (ftrunc_optab->handlers[(int) fltmode].insn_code != CODE_FOR_nothing)
2778: {
2779: *truncp_ptr = 1;
2780: return fixtab[(int) fltmode][(int) fixmode][unsignedp];
2781: }
2782: return CODE_FOR_nothing;
2783: }
2784:
2785: static enum insn_code
2786: can_float_p (fltmode, fixmode, unsignedp)
2787: enum machine_mode fixmode, fltmode;
2788: int unsignedp;
2789: {
2790: return floattab[(int) fltmode][(int) fixmode][unsignedp];
2791: }
2792:
2793: void
2794: init_fixtab ()
2795: {
2796: enum insn_code *p;
2797: for (p = fixtab[0][0];
2798: p < fixtab[0][0] + sizeof fixtab / sizeof (fixtab[0][0][0]);
2799: p++)
2800: *p = CODE_FOR_nothing;
2801: for (p = fixtrunctab[0][0];
2802: p < fixtrunctab[0][0] + sizeof fixtrunctab / sizeof (fixtrunctab[0][0][0]);
2803: p++)
2804: *p = CODE_FOR_nothing;
2805:
2806: #ifdef HAVE_fixsfqi2
2807: if (HAVE_fixsfqi2)
2808: fixtab[(int) SFmode][(int) QImode][0] = CODE_FOR_fixsfqi2;
2809: #endif
2810: #ifdef HAVE_fixsfhi2
2811: if (HAVE_fixsfhi2)
2812: fixtab[(int) SFmode][(int) HImode][0] = CODE_FOR_fixsfhi2;
2813: #endif
2814: #ifdef HAVE_fixsfsi2
2815: if (HAVE_fixsfsi2)
2816: fixtab[(int) SFmode][(int) SImode][0] = CODE_FOR_fixsfsi2;
2817: #endif
2818: #ifdef HAVE_fixsfdi2
2819: if (HAVE_fixsfdi2)
2820: fixtab[(int) SFmode][(int) DImode][0] = CODE_FOR_fixsfdi2;
2821: #endif
2822:
2823: #ifdef HAVE_fixdfqi2
2824: if (HAVE_fixdfqi2)
2825: fixtab[(int) DFmode][(int) QImode][0] = CODE_FOR_fixdfqi2;
2826: #endif
2827: #ifdef HAVE_fixdfhi2
2828: if (HAVE_fixdfhi2)
2829: fixtab[(int) DFmode][(int) HImode][0] = CODE_FOR_fixdfhi2;
2830: #endif
2831: #ifdef HAVE_fixdfsi2
2832: if (HAVE_fixdfsi2)
2833: fixtab[(int) DFmode][(int) SImode][0] = CODE_FOR_fixdfsi2;
2834: #endif
2835: #ifdef HAVE_fixdfdi2
2836: if (HAVE_fixdfdi2)
2837: fixtab[(int) DFmode][(int) DImode][0] = CODE_FOR_fixdfdi2;
2838: #endif
2839: #ifdef HAVE_fixdfti2
2840: if (HAVE_fixdfti2)
2841: fixtab[(int) DFmode][(int) TImode][0] = CODE_FOR_fixdfti2;
2842: #endif
2843:
1.1.1.4 ! root 2844: #ifdef HAVE_fixxfqi2
! 2845: if (HAVE_fixxfqi2)
! 2846: fixtab[(int) XFmode][(int) QImode][0] = CODE_FOR_fixxfqi2;
! 2847: #endif
! 2848: #ifdef HAVE_fixxfhi2
! 2849: if (HAVE_fixxfhi2)
! 2850: fixtab[(int) XFmode][(int) HImode][0] = CODE_FOR_fixxfhi2;
! 2851: #endif
! 2852: #ifdef HAVE_fixxfsi2
! 2853: if (HAVE_fixxfsi2)
! 2854: fixtab[(int) XFmode][(int) SImode][0] = CODE_FOR_fixxfsi2;
! 2855: #endif
! 2856: #ifdef HAVE_fixxfdi2
! 2857: if (HAVE_fixxfdi2)
! 2858: fixtab[(int) XFmode][(int) DImode][0] = CODE_FOR_fixxfdi2;
! 2859: #endif
! 2860: #ifdef HAVE_fixxfti2
! 2861: if (HAVE_fixxfti2)
! 2862: fixtab[(int) XFmode][(int) TImode][0] = CODE_FOR_fixxfti2;
! 2863: #endif
! 2864:
1.1 root 2865: #ifdef HAVE_fixtfqi2
2866: if (HAVE_fixtfqi2)
2867: fixtab[(int) TFmode][(int) QImode][0] = CODE_FOR_fixtfqi2;
2868: #endif
2869: #ifdef HAVE_fixtfhi2
2870: if (HAVE_fixtfhi2)
2871: fixtab[(int) TFmode][(int) HImode][0] = CODE_FOR_fixtfhi2;
2872: #endif
2873: #ifdef HAVE_fixtfsi2
2874: if (HAVE_fixtfsi2)
2875: fixtab[(int) TFmode][(int) SImode][0] = CODE_FOR_fixtfsi2;
2876: #endif
2877: #ifdef HAVE_fixtfdi2
2878: if (HAVE_fixtfdi2)
2879: fixtab[(int) TFmode][(int) DImode][0] = CODE_FOR_fixtfdi2;
2880: #endif
2881: #ifdef HAVE_fixtfti2
2882: if (HAVE_fixtfti2)
2883: fixtab[(int) TFmode][(int) TImode][0] = CODE_FOR_fixtfti2;
2884: #endif
2885:
2886: #ifdef HAVE_fixunssfqi2
2887: if (HAVE_fixunssfqi2)
2888: fixtab[(int) SFmode][(int) QImode][1] = CODE_FOR_fixunssfqi2;
2889: #endif
2890: #ifdef HAVE_fixunssfhi2
2891: if (HAVE_fixunssfhi2)
2892: fixtab[(int) SFmode][(int) HImode][1] = CODE_FOR_fixunssfhi2;
2893: #endif
2894: #ifdef HAVE_fixunssfsi2
2895: if (HAVE_fixunssfsi2)
2896: fixtab[(int) SFmode][(int) SImode][1] = CODE_FOR_fixunssfsi2;
2897: #endif
2898: #ifdef HAVE_fixunssfdi2
2899: if (HAVE_fixunssfdi2)
2900: fixtab[(int) SFmode][(int) DImode][1] = CODE_FOR_fixunssfdi2;
2901: #endif
2902:
2903: #ifdef HAVE_fixunsdfqi2
2904: if (HAVE_fixunsdfqi2)
2905: fixtab[(int) DFmode][(int) QImode][1] = CODE_FOR_fixunsdfqi2;
2906: #endif
2907: #ifdef HAVE_fixunsdfhi2
2908: if (HAVE_fixunsdfhi2)
2909: fixtab[(int) DFmode][(int) HImode][1] = CODE_FOR_fixunsdfhi2;
2910: #endif
2911: #ifdef HAVE_fixunsdfsi2
2912: if (HAVE_fixunsdfsi2)
2913: fixtab[(int) DFmode][(int) SImode][1] = CODE_FOR_fixunsdfsi2;
2914: #endif
2915: #ifdef HAVE_fixunsdfdi2
2916: if (HAVE_fixunsdfdi2)
2917: fixtab[(int) DFmode][(int) DImode][1] = CODE_FOR_fixunsdfdi2;
2918: #endif
2919: #ifdef HAVE_fixunsdfti2
2920: if (HAVE_fixunsdfti2)
2921: fixtab[(int) DFmode][(int) TImode][1] = CODE_FOR_fixunsdfti2;
2922: #endif
2923:
1.1.1.4 ! root 2924: #ifdef HAVE_fixunsxfqi2
! 2925: if (HAVE_fixunsxfqi2)
! 2926: fixtab[(int) XFmode][(int) QImode][1] = CODE_FOR_fixunsxfqi2;
! 2927: #endif
! 2928: #ifdef HAVE_fixunsxfhi2
! 2929: if (HAVE_fixunsxfhi2)
! 2930: fixtab[(int) XFmode][(int) HImode][1] = CODE_FOR_fixunsxfhi2;
! 2931: #endif
! 2932: #ifdef HAVE_fixunsxfsi2
! 2933: if (HAVE_fixunsxfsi2)
! 2934: fixtab[(int) XFmode][(int) SImode][1] = CODE_FOR_fixunsxfsi2;
! 2935: #endif
! 2936: #ifdef HAVE_fixunsxfdi2
! 2937: if (HAVE_fixunsxfdi2)
! 2938: fixtab[(int) XFmode][(int) DImode][1] = CODE_FOR_fixunsxfdi2;
! 2939: #endif
! 2940: #ifdef HAVE_fixunsxfti2
! 2941: if (HAVE_fixunsxfti2)
! 2942: fixtab[(int) XFmode][(int) TImode][1] = CODE_FOR_fixunsxfti2;
! 2943: #endif
! 2944:
1.1 root 2945: #ifdef HAVE_fixunstfqi2
2946: if (HAVE_fixunstfqi2)
2947: fixtab[(int) TFmode][(int) QImode][1] = CODE_FOR_fixunstfqi2;
2948: #endif
2949: #ifdef HAVE_fixunstfhi2
2950: if (HAVE_fixunstfhi2)
2951: fixtab[(int) TFmode][(int) HImode][1] = CODE_FOR_fixunstfhi2;
2952: #endif
2953: #ifdef HAVE_fixunstfsi2
2954: if (HAVE_fixunstfsi2)
2955: fixtab[(int) TFmode][(int) SImode][1] = CODE_FOR_fixunstfsi2;
2956: #endif
2957: #ifdef HAVE_fixunstfdi2
2958: if (HAVE_fixunstfdi2)
2959: fixtab[(int) TFmode][(int) DImode][1] = CODE_FOR_fixunstfdi2;
2960: #endif
2961: #ifdef HAVE_fixunstfti2
2962: if (HAVE_fixunstfti2)
2963: fixtab[(int) TFmode][(int) TImode][1] = CODE_FOR_fixunstfti2;
2964: #endif
2965:
2966: #ifdef HAVE_fix_truncsfqi2
2967: if (HAVE_fix_truncsfqi2)
2968: fixtrunctab[(int) SFmode][(int) QImode][0] = CODE_FOR_fix_truncsfqi2;
2969: #endif
2970: #ifdef HAVE_fix_truncsfhi2
2971: if (HAVE_fix_truncsfhi2)
2972: fixtrunctab[(int) SFmode][(int) HImode][0] = CODE_FOR_fix_truncsfhi2;
2973: #endif
2974: #ifdef HAVE_fix_truncsfsi2
2975: if (HAVE_fix_truncsfsi2)
2976: fixtrunctab[(int) SFmode][(int) SImode][0] = CODE_FOR_fix_truncsfsi2;
2977: #endif
2978: #ifdef HAVE_fix_truncsfdi2
2979: if (HAVE_fix_truncsfdi2)
2980: fixtrunctab[(int) SFmode][(int) DImode][0] = CODE_FOR_fix_truncsfdi2;
2981: #endif
2982:
2983: #ifdef HAVE_fix_truncdfqi2
1.1.1.4 ! root 2984: if (HAVE_fix_truncdfqi2)
1.1 root 2985: fixtrunctab[(int) DFmode][(int) QImode][0] = CODE_FOR_fix_truncdfqi2;
2986: #endif
2987: #ifdef HAVE_fix_truncdfhi2
2988: if (HAVE_fix_truncdfhi2)
2989: fixtrunctab[(int) DFmode][(int) HImode][0] = CODE_FOR_fix_truncdfhi2;
2990: #endif
2991: #ifdef HAVE_fix_truncdfsi2
2992: if (HAVE_fix_truncdfsi2)
2993: fixtrunctab[(int) DFmode][(int) SImode][0] = CODE_FOR_fix_truncdfsi2;
2994: #endif
2995: #ifdef HAVE_fix_truncdfdi2
2996: if (HAVE_fix_truncdfdi2)
2997: fixtrunctab[(int) DFmode][(int) DImode][0] = CODE_FOR_fix_truncdfdi2;
2998: #endif
2999: #ifdef HAVE_fix_truncdfti2
3000: if (HAVE_fix_truncdfti2)
3001: fixtrunctab[(int) DFmode][(int) TImode][0] = CODE_FOR_fix_truncdfti2;
3002: #endif
3003:
1.1.1.4 ! root 3004: #ifdef HAVE_fix_truncxfqi2
! 3005: if (HAVE_fix_truncxfqi2)
! 3006: fixtrunctab[(int) XFmode][(int) QImode][0] = CODE_FOR_fix_truncxfqi2;
! 3007: #endif
! 3008: #ifdef HAVE_fix_truncxfhi2
! 3009: if (HAVE_fix_truncxfhi2)
! 3010: fixtrunctab[(int) XFmode][(int) HImode][0] = CODE_FOR_fix_truncxfhi2;
! 3011: #endif
! 3012: #ifdef HAVE_fix_truncxfsi2
! 3013: if (HAVE_fix_truncxfsi2)
! 3014: fixtrunctab[(int) XFmode][(int) SImode][0] = CODE_FOR_fix_truncxfsi2;
! 3015: #endif
! 3016: #ifdef HAVE_fix_truncxfdi2
! 3017: if (HAVE_fix_truncxfdi2)
! 3018: fixtrunctab[(int) XFmode][(int) DImode][0] = CODE_FOR_fix_truncxfdi2;
! 3019: #endif
! 3020: #ifdef HAVE_fix_truncxfti2
! 3021: if (HAVE_fix_truncxfti2)
! 3022: fixtrunctab[(int) XFmode][(int) TImode][0] = CODE_FOR_fix_truncxfti2;
! 3023: #endif
! 3024:
1.1 root 3025: #ifdef HAVE_fix_trunctfqi2
3026: if (HAVE_fix_trunctfqi2)
3027: fixtrunctab[(int) TFmode][(int) QImode][0] = CODE_FOR_fix_trunctfqi2;
3028: #endif
3029: #ifdef HAVE_fix_trunctfhi2
3030: if (HAVE_fix_trunctfhi2)
3031: fixtrunctab[(int) TFmode][(int) HImode][0] = CODE_FOR_fix_trunctfhi2;
3032: #endif
3033: #ifdef HAVE_fix_trunctfsi2
3034: if (HAVE_fix_trunctfsi2)
3035: fixtrunctab[(int) TFmode][(int) SImode][0] = CODE_FOR_fix_trunctfsi2;
3036: #endif
3037: #ifdef HAVE_fix_trunctfdi2
3038: if (HAVE_fix_trunctfdi2)
3039: fixtrunctab[(int) TFmode][(int) DImode][0] = CODE_FOR_fix_trunctfdi2;
3040: #endif
3041: #ifdef HAVE_fix_trunctfti2
3042: if (HAVE_fix_trunctfti2)
3043: fixtrunctab[(int) TFmode][(int) TImode][0] = CODE_FOR_fix_trunctfti2;
3044: #endif
3045:
3046: #ifdef HAVE_fixuns_truncsfqi2
3047: if (HAVE_fixuns_truncsfqi2)
3048: fixtrunctab[(int) SFmode][(int) QImode][1] = CODE_FOR_fixuns_truncsfqi2;
3049: #endif
3050: #ifdef HAVE_fixuns_truncsfhi2
3051: if (HAVE_fixuns_truncsfhi2)
3052: fixtrunctab[(int) SFmode][(int) HImode][1] = CODE_FOR_fixuns_truncsfhi2;
3053: #endif
3054: #ifdef HAVE_fixuns_truncsfsi2
3055: if (HAVE_fixuns_truncsfsi2)
3056: fixtrunctab[(int) SFmode][(int) SImode][1] = CODE_FOR_fixuns_truncsfsi2;
3057: #endif
3058: #ifdef HAVE_fixuns_truncsfdi2
3059: if (HAVE_fixuns_truncsfdi2)
3060: fixtrunctab[(int) SFmode][(int) DImode][1] = CODE_FOR_fixuns_truncsfdi2;
3061: #endif
3062:
3063: #ifdef HAVE_fixuns_truncdfqi2
3064: if (HAVE_fixuns_truncdfqi2)
3065: fixtrunctab[(int) DFmode][(int) QImode][1] = CODE_FOR_fixuns_truncdfqi2;
3066: #endif
3067: #ifdef HAVE_fixuns_truncdfhi2
3068: if (HAVE_fixuns_truncdfhi2)
3069: fixtrunctab[(int) DFmode][(int) HImode][1] = CODE_FOR_fixuns_truncdfhi2;
3070: #endif
3071: #ifdef HAVE_fixuns_truncdfsi2
3072: if (HAVE_fixuns_truncdfsi2)
3073: fixtrunctab[(int) DFmode][(int) SImode][1] = CODE_FOR_fixuns_truncdfsi2;
3074: #endif
3075: #ifdef HAVE_fixuns_truncdfdi2
3076: if (HAVE_fixuns_truncdfdi2)
3077: fixtrunctab[(int) DFmode][(int) DImode][1] = CODE_FOR_fixuns_truncdfdi2;
3078: #endif
3079: #ifdef HAVE_fixuns_truncdfti2
3080: if (HAVE_fixuns_truncdfti2)
3081: fixtrunctab[(int) DFmode][(int) TImode][1] = CODE_FOR_fixuns_truncdfti2;
3082: #endif
3083:
1.1.1.4 ! root 3084: #ifdef HAVE_fixuns_truncxfqi2
! 3085: if (HAVE_fixuns_truncxfqi2)
! 3086: fixtrunctab[(int) XFmode][(int) QImode][1] = CODE_FOR_fixuns_truncxfqi2;
! 3087: #endif
! 3088: #ifdef HAVE_fixuns_truncxfhi2
! 3089: if (HAVE_fixuns_truncxfhi2)
! 3090: fixtrunctab[(int) XFmode][(int) HImode][1] = CODE_FOR_fixuns_truncxfhi2;
! 3091: #endif
! 3092: #ifdef HAVE_fixuns_truncxfsi2
! 3093: if (HAVE_fixuns_truncxfsi2)
! 3094: fixtrunctab[(int) XFmode][(int) SImode][1] = CODE_FOR_fixuns_truncxfsi2;
! 3095: #endif
! 3096: #ifdef HAVE_fixuns_truncxfdi2
! 3097: if (HAVE_fixuns_truncxfdi2)
! 3098: fixtrunctab[(int) XFmode][(int) DImode][1] = CODE_FOR_fixuns_truncxfdi2;
! 3099: #endif
! 3100: #ifdef HAVE_fixuns_truncxfti2
! 3101: if (HAVE_fixuns_truncxfti2)
! 3102: fixtrunctab[(int) XFmode][(int) TImode][1] = CODE_FOR_fixuns_truncxfti2;
! 3103: #endif
! 3104:
1.1 root 3105: #ifdef HAVE_fixuns_trunctfqi2
3106: if (HAVE_fixuns_trunctfqi2)
3107: fixtrunctab[(int) TFmode][(int) QImode][1] = CODE_FOR_fixuns_trunctfqi2;
3108: #endif
3109: #ifdef HAVE_fixuns_trunctfhi2
3110: if (HAVE_fixuns_trunctfhi2)
3111: fixtrunctab[(int) TFmode][(int) HImode][1] = CODE_FOR_fixuns_trunctfhi2;
3112: #endif
3113: #ifdef HAVE_fixuns_trunctfsi2
3114: if (HAVE_fixuns_trunctfsi2)
3115: fixtrunctab[(int) TFmode][(int) SImode][1] = CODE_FOR_fixuns_trunctfsi2;
3116: #endif
3117: #ifdef HAVE_fixuns_trunctfdi2
3118: if (HAVE_fixuns_trunctfdi2)
3119: fixtrunctab[(int) TFmode][(int) DImode][1] = CODE_FOR_fixuns_trunctfdi2;
3120: #endif
3121: #ifdef HAVE_fixuns_trunctfti2
3122: if (HAVE_fixuns_trunctfti2)
3123: fixtrunctab[(int) TFmode][(int) TImode][1] = CODE_FOR_fixuns_trunctfti2;
3124: #endif
3125:
3126: #ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC
3127: /* This flag says the same insns that convert to a signed fixnum
3128: also convert validly to an unsigned one. */
3129: {
3130: int i;
3131: int j;
3132: for (i = 0; i < NUM_MACHINE_MODES; i++)
3133: for (j = 0; j < NUM_MACHINE_MODES; j++)
3134: fixtrunctab[i][j][1] = fixtrunctab[i][j][0];
3135: }
3136: #endif
3137: }
3138:
3139: void
3140: init_floattab ()
3141: {
3142: enum insn_code *p;
3143: for (p = floattab[0][0];
3144: p < floattab[0][0] + sizeof floattab / sizeof (floattab[0][0][0]);
3145: p++)
3146: *p = CODE_FOR_nothing;
3147:
3148: #ifdef HAVE_floatqisf2
3149: if (HAVE_floatqisf2)
3150: floattab[(int) SFmode][(int) QImode][0] = CODE_FOR_floatqisf2;
3151: #endif
3152: #ifdef HAVE_floathisf2
3153: if (HAVE_floathisf2)
3154: floattab[(int) SFmode][(int) HImode][0] = CODE_FOR_floathisf2;
3155: #endif
3156: #ifdef HAVE_floatsisf2
3157: if (HAVE_floatsisf2)
3158: floattab[(int) SFmode][(int) SImode][0] = CODE_FOR_floatsisf2;
3159: #endif
3160: #ifdef HAVE_floatdisf2
3161: if (HAVE_floatdisf2)
3162: floattab[(int) SFmode][(int) DImode][0] = CODE_FOR_floatdisf2;
3163: #endif
3164: #ifdef HAVE_floattisf2
3165: if (HAVE_floattisf2)
3166: floattab[(int) SFmode][(int) TImode][0] = CODE_FOR_floattisf2;
3167: #endif
3168:
3169: #ifdef HAVE_floatqidf2
3170: if (HAVE_floatqidf2)
3171: floattab[(int) DFmode][(int) QImode][0] = CODE_FOR_floatqidf2;
3172: #endif
3173: #ifdef HAVE_floathidf2
3174: if (HAVE_floathidf2)
3175: floattab[(int) DFmode][(int) HImode][0] = CODE_FOR_floathidf2;
3176: #endif
3177: #ifdef HAVE_floatsidf2
3178: if (HAVE_floatsidf2)
3179: floattab[(int) DFmode][(int) SImode][0] = CODE_FOR_floatsidf2;
3180: #endif
3181: #ifdef HAVE_floatdidf2
3182: if (HAVE_floatdidf2)
3183: floattab[(int) DFmode][(int) DImode][0] = CODE_FOR_floatdidf2;
3184: #endif
3185: #ifdef HAVE_floattidf2
3186: if (HAVE_floattidf2)
3187: floattab[(int) DFmode][(int) TImode][0] = CODE_FOR_floattidf2;
3188: #endif
3189:
1.1.1.4 ! root 3190: #ifdef HAVE_floatqixf2
! 3191: if (HAVE_floatqixf2)
! 3192: floattab[(int) XFmode][(int) QImode][0] = CODE_FOR_floatqixf2;
! 3193: #endif
! 3194: #ifdef HAVE_floathixf2
! 3195: if (HAVE_floathixf2)
! 3196: floattab[(int) XFmode][(int) HImode][0] = CODE_FOR_floathixf2;
! 3197: #endif
! 3198: #ifdef HAVE_floatsixf2
! 3199: if (HAVE_floatsixf2)
! 3200: floattab[(int) XFmode][(int) SImode][0] = CODE_FOR_floatsixf2;
! 3201: #endif
! 3202: #ifdef HAVE_floatdixf2
! 3203: if (HAVE_floatdixf2)
! 3204: floattab[(int) XFmode][(int) DImode][0] = CODE_FOR_floatdixf2;
! 3205: #endif
! 3206: #ifdef HAVE_floattixf2
! 3207: if (HAVE_floattixf2)
! 3208: floattab[(int) XFmode][(int) TImode][0] = CODE_FOR_floattixf2;
! 3209: #endif
! 3210:
1.1 root 3211: #ifdef HAVE_floatqitf2
3212: if (HAVE_floatqitf2)
3213: floattab[(int) TFmode][(int) QImode][0] = CODE_FOR_floatqitf2;
3214: #endif
3215: #ifdef HAVE_floathitf2
3216: if (HAVE_floathitf2)
3217: floattab[(int) TFmode][(int) HImode][0] = CODE_FOR_floathitf2;
3218: #endif
3219: #ifdef HAVE_floatsitf2
3220: if (HAVE_floatsitf2)
3221: floattab[(int) TFmode][(int) SImode][0] = CODE_FOR_floatsitf2;
3222: #endif
3223: #ifdef HAVE_floatditf2
3224: if (HAVE_floatditf2)
3225: floattab[(int) TFmode][(int) DImode][0] = CODE_FOR_floatditf2;
3226: #endif
3227: #ifdef HAVE_floattitf2
3228: if (HAVE_floattitf2)
3229: floattab[(int) TFmode][(int) TImode][0] = CODE_FOR_floattitf2;
3230: #endif
3231:
3232: #ifdef HAVE_floatunsqisf2
3233: if (HAVE_floatunsqisf2)
3234: floattab[(int) SFmode][(int) QImode][1] = CODE_FOR_floatunsqisf2;
3235: #endif
3236: #ifdef HAVE_floatunshisf2
3237: if (HAVE_floatunshisf2)
3238: floattab[(int) SFmode][(int) HImode][1] = CODE_FOR_floatunshisf2;
3239: #endif
3240: #ifdef HAVE_floatunssisf2
3241: if (HAVE_floatunssisf2)
3242: floattab[(int) SFmode][(int) SImode][1] = CODE_FOR_floatunssisf2;
3243: #endif
3244: #ifdef HAVE_floatunsdisf2
3245: if (HAVE_floatunsdisf2)
3246: floattab[(int) SFmode][(int) DImode][1] = CODE_FOR_floatunsdisf2;
3247: #endif
3248: #ifdef HAVE_floatunstisf2
3249: if (HAVE_floatunstisf2)
3250: floattab[(int) SFmode][(int) TImode][1] = CODE_FOR_floatunstisf2;
3251: #endif
3252:
3253: #ifdef HAVE_floatunsqidf2
3254: if (HAVE_floatunsqidf2)
3255: floattab[(int) DFmode][(int) QImode][1] = CODE_FOR_floatunsqidf2;
3256: #endif
3257: #ifdef HAVE_floatunshidf2
3258: if (HAVE_floatunshidf2)
3259: floattab[(int) DFmode][(int) HImode][1] = CODE_FOR_floatunshidf2;
3260: #endif
3261: #ifdef HAVE_floatunssidf2
3262: if (HAVE_floatunssidf2)
3263: floattab[(int) DFmode][(int) SImode][1] = CODE_FOR_floatunssidf2;
3264: #endif
3265: #ifdef HAVE_floatunsdidf2
3266: if (HAVE_floatunsdidf2)
3267: floattab[(int) DFmode][(int) DImode][1] = CODE_FOR_floatunsdidf2;
3268: #endif
3269: #ifdef HAVE_floatunstidf2
3270: if (HAVE_floatunstidf2)
3271: floattab[(int) DFmode][(int) TImode][1] = CODE_FOR_floatunstidf2;
3272: #endif
3273:
1.1.1.4 ! root 3274: #ifdef HAVE_floatunsqixf2
! 3275: if (HAVE_floatunsqixf2)
! 3276: floattab[(int) XFmode][(int) QImode][1] = CODE_FOR_floatunsqixf2;
! 3277: #endif
! 3278: #ifdef HAVE_floatunshixf2
! 3279: if (HAVE_floatunshixf2)
! 3280: floattab[(int) XFmode][(int) HImode][1] = CODE_FOR_floatunshixf2;
! 3281: #endif
! 3282: #ifdef HAVE_floatunssixf2
! 3283: if (HAVE_floatunssixf2)
! 3284: floattab[(int) XFmode][(int) SImode][1] = CODE_FOR_floatunssixf2;
! 3285: #endif
! 3286: #ifdef HAVE_floatunsdixf2
! 3287: if (HAVE_floatunsdixf2)
! 3288: floattab[(int) XFmode][(int) DImode][1] = CODE_FOR_floatunsdixf2;
! 3289: #endif
! 3290: #ifdef HAVE_floatunstixf2
! 3291: if (HAVE_floatunstixf2)
! 3292: floattab[(int) XFmode][(int) TImode][1] = CODE_FOR_floatunstixf2;
! 3293: #endif
! 3294:
1.1 root 3295: #ifdef HAVE_floatunsqitf2
3296: if (HAVE_floatunsqitf2)
3297: floattab[(int) TFmode][(int) QImode][1] = CODE_FOR_floatunsqitf2;
3298: #endif
3299: #ifdef HAVE_floatunshitf2
3300: if (HAVE_floatunshitf2)
3301: floattab[(int) TFmode][(int) HImode][1] = CODE_FOR_floatunshitf2;
3302: #endif
3303: #ifdef HAVE_floatunssitf2
3304: if (HAVE_floatunssitf2)
3305: floattab[(int) TFmode][(int) SImode][1] = CODE_FOR_floatunssitf2;
3306: #endif
3307: #ifdef HAVE_floatunsditf2
3308: if (HAVE_floatunsditf2)
3309: floattab[(int) TFmode][(int) DImode][1] = CODE_FOR_floatunsditf2;
3310: #endif
3311: #ifdef HAVE_floatunstitf2
3312: if (HAVE_floatunstitf2)
3313: floattab[(int) TFmode][(int) TImode][1] = CODE_FOR_floatunstitf2;
3314: #endif
3315: }
3316:
3317: /* Generate code to convert FROM to floating point
3318: and store in TO. FROM must be fixed point and not VOIDmode.
3319: UNSIGNEDP nonzero means regard FROM as unsigned.
3320: Normally this is done by correcting the final value
3321: if it is negative. */
3322:
3323: void
3324: expand_float (to, from, unsignedp)
3325: rtx to, from;
3326: int unsignedp;
3327: {
3328: enum insn_code icode;
3329: register rtx target = to;
3330: enum machine_mode fmode, imode;
3331:
3332: /* Crash now, because we won't be able to decide which mode to use. */
3333: if (GET_MODE (from) == VOIDmode)
3334: abort ();
3335:
3336: /* Look for an insn to do the conversion. Do it in the specified
3337: modes if possible; otherwise convert either input, output or both to
3338: wider mode. If the integer mode is wider than the mode of FROM,
3339: we can do the conversion signed even if the input is unsigned. */
3340:
3341: for (imode = GET_MODE (from); imode != VOIDmode;
3342: imode = GET_MODE_WIDER_MODE (imode))
3343: for (fmode = GET_MODE (to); fmode != VOIDmode;
3344: fmode = GET_MODE_WIDER_MODE (fmode))
3345: {
3346: int doing_unsigned = unsignedp;
3347:
3348: icode = can_float_p (fmode, imode, unsignedp);
3349: if (icode == CODE_FOR_nothing && imode != GET_MODE (from) && unsignedp)
3350: icode = can_float_p (fmode, imode, 0), doing_unsigned = 0;
3351:
3352: if (icode != CODE_FOR_nothing)
3353: {
3354: to = protect_from_queue (to, 1);
1.1.1.4 ! root 3355: from = protect_from_queue (from, 0);
1.1 root 3356:
3357: if (imode != GET_MODE (from))
3358: from = convert_to_mode (imode, from, unsignedp);
3359:
3360: if (fmode != GET_MODE (to))
3361: target = gen_reg_rtx (fmode);
3362:
3363: emit_unop_insn (icode, target, from,
3364: doing_unsigned ? UNSIGNED_FLOAT : FLOAT);
3365:
3366: if (target != to)
3367: convert_move (to, target, 0);
3368: return;
3369: }
3370: }
3371:
3372: #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
3373:
3374: /* Unsigned integer, and no way to convert directly.
3375: Convert as signed, then conditionally adjust the result. */
3376: if (unsignedp)
3377: {
3378: rtx label = gen_label_rtx ();
3379: rtx temp;
3380: REAL_VALUE_TYPE offset;
3381:
3382: emit_queue ();
3383:
3384: to = protect_from_queue (to, 1);
3385: from = protect_from_queue (from, 0);
3386:
3387: if (flag_force_mem)
3388: from = force_not_mem (from);
3389:
3390: /* If we are about to do some arithmetic to correct for an
3391: unsigned operand, do it in a pseudo-register. */
3392:
3393: if (GET_CODE (to) != REG || REGNO (to) <= LAST_VIRTUAL_REGISTER)
3394: target = gen_reg_rtx (GET_MODE (to));
3395:
3396: /* Convert as signed integer to floating. */
3397: expand_float (target, from, 0);
3398:
3399: /* If FROM is negative (and therefore TO is negative),
3400: correct its value by 2**bitwidth. */
3401:
3402: do_pending_stack_adjust ();
1.1.1.4 ! root 3403: emit_cmp_insn (from, const0_rtx, GE, NULL_RTX, GET_MODE (from), 0, 0);
1.1 root 3404: emit_jump_insn (gen_bge (label));
3405: /* On SCO 3.2.1, ldexp rejects values outside [0.5, 1).
3406: Rather than setting up a dconst_dot_5, let's hope SCO
3407: fixes the bug. */
3408: offset = REAL_VALUE_LDEXP (dconst1, GET_MODE_BITSIZE (GET_MODE (from)));
3409: temp = expand_binop (GET_MODE (to), add_optab, target,
3410: immed_real_const_1 (offset, GET_MODE (to)),
3411: target, 0, OPTAB_LIB_WIDEN);
3412: if (temp != target)
3413: emit_move_insn (target, temp);
3414: do_pending_stack_adjust ();
3415: emit_label (label);
3416: }
3417: else
3418: #endif
3419:
1.1.1.4 ! root 3420: /* No hardware instruction available; call a library rotine to convert from
! 3421: SImode, DImode, or TImode into SFmode, DFmode, XFmode, or TFmode. */
1.1 root 3422: {
3423: rtx libfcn;
3424: rtx insns;
3425:
3426: to = protect_from_queue (to, 1);
1.1.1.4 ! root 3427: from = protect_from_queue (from, 0);
1.1 root 3428:
3429: if (GET_MODE_SIZE (GET_MODE (from)) < GET_MODE_SIZE (SImode))
3430: from = convert_to_mode (SImode, from, unsignedp);
3431:
3432: if (flag_force_mem)
3433: from = force_not_mem (from);
3434:
3435: if (GET_MODE (to) == SFmode)
3436: {
3437: if (GET_MODE (from) == SImode)
3438: libfcn = floatsisf_libfunc;
3439: else if (GET_MODE (from) == DImode)
3440: libfcn = floatdisf_libfunc;
1.1.1.4 ! root 3441: else if (GET_MODE (from) == TImode)
! 3442: libfcn = floattisf_libfunc;
1.1 root 3443: else
3444: abort ();
3445: }
3446: else if (GET_MODE (to) == DFmode)
3447: {
3448: if (GET_MODE (from) == SImode)
3449: libfcn = floatsidf_libfunc;
3450: else if (GET_MODE (from) == DImode)
3451: libfcn = floatdidf_libfunc;
1.1.1.4 ! root 3452: else if (GET_MODE (from) == TImode)
! 3453: libfcn = floattidf_libfunc;
! 3454: else
! 3455: abort ();
! 3456: }
! 3457: else if (GET_MODE (to) == XFmode)
! 3458: {
! 3459: if (GET_MODE (from) == SImode)
! 3460: libfcn = floatsixf_libfunc;
! 3461: else if (GET_MODE (from) == DImode)
! 3462: libfcn = floatdixf_libfunc;
! 3463: else if (GET_MODE (from) == TImode)
! 3464: libfcn = floattixf_libfunc;
! 3465: else
! 3466: abort ();
! 3467: }
! 3468: else if (GET_MODE (to) == TFmode)
! 3469: {
! 3470: if (GET_MODE (from) == SImode)
! 3471: libfcn = floatsitf_libfunc;
! 3472: else if (GET_MODE (from) == DImode)
! 3473: libfcn = floatditf_libfunc;
! 3474: else if (GET_MODE (from) == TImode)
! 3475: libfcn = floattitf_libfunc;
1.1 root 3476: else
3477: abort ();
3478: }
3479: else
3480: abort ();
3481:
3482: start_sequence ();
3483:
1.1.1.2 root 3484: emit_library_call (libfcn, 1, GET_MODE (to), 1, from, GET_MODE (from));
1.1 root 3485: insns = get_insns ();
3486: end_sequence ();
3487:
3488: emit_libcall_block (insns, target, hard_libcall_value (GET_MODE (to)),
3489: gen_rtx (FLOAT, GET_MODE (to), from));
3490: }
3491:
3492: /* Copy result to requested destination
3493: if we have been computing in a temp location. */
3494:
3495: if (target != to)
3496: {
3497: if (GET_MODE (target) == GET_MODE (to))
3498: emit_move_insn (to, target);
3499: else
3500: convert_move (to, target, 0);
3501: }
3502: }
3503:
3504: /* expand_fix: generate code to convert FROM to fixed point
3505: and store in TO. FROM must be floating point. */
3506:
3507: static rtx
3508: ftruncify (x)
3509: rtx x;
3510: {
3511: rtx temp = gen_reg_rtx (GET_MODE (x));
3512: return expand_unop (GET_MODE (x), ftrunc_optab, x, temp, 0);
3513: }
3514:
3515: void
3516: expand_fix (to, from, unsignedp)
3517: register rtx to, from;
3518: int unsignedp;
3519: {
3520: enum insn_code icode;
3521: register rtx target = to;
3522: enum machine_mode fmode, imode;
3523: int must_trunc = 0;
3524: rtx libfcn = 0;
3525:
3526: /* We first try to find a pair of modes, one real and one integer, at
3527: least as wide as FROM and TO, respectively, in which we can open-code
3528: this conversion. If the integer mode is wider than the mode of TO,
3529: we can do the conversion either signed or unsigned. */
3530:
3531: for (imode = GET_MODE (to); imode != VOIDmode;
3532: imode = GET_MODE_WIDER_MODE (imode))
3533: for (fmode = GET_MODE (from); fmode != VOIDmode;
3534: fmode = GET_MODE_WIDER_MODE (fmode))
3535: {
3536: int doing_unsigned = unsignedp;
3537:
3538: icode = can_fix_p (imode, fmode, unsignedp, &must_trunc);
3539: if (icode == CODE_FOR_nothing && imode != GET_MODE (to) && unsignedp)
3540: icode = can_fix_p (imode, fmode, 0, &must_trunc), doing_unsigned = 0;
3541:
3542: if (icode != CODE_FOR_nothing)
3543: {
3544: to = protect_from_queue (to, 1);
1.1.1.4 ! root 3545: from = protect_from_queue (from, 0);
1.1 root 3546:
3547: if (fmode != GET_MODE (from))
3548: from = convert_to_mode (fmode, from, 0);
3549:
3550: if (must_trunc)
3551: from = ftruncify (from);
3552:
3553: if (imode != GET_MODE (to))
3554: target = gen_reg_rtx (imode);
3555:
3556: emit_unop_insn (icode, target, from,
3557: doing_unsigned ? UNSIGNED_FIX : FIX);
3558: if (target != to)
3559: convert_move (to, target, unsignedp);
3560: return;
3561: }
3562: }
3563:
3564: #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
3565: /* For an unsigned conversion, there is one more way to do it.
3566: If we have a signed conversion, we generate code that compares
3567: the real value to the largest representable positive number. If if
3568: is smaller, the conversion is done normally. Otherwise, subtract
3569: one plus the highest signed number, convert, and add it back.
3570:
3571: We only need to check all real modes, since we know we didn't find
1.1.1.3 root 3572: anything with a wider integer mode. */
1.1 root 3573:
1.1.1.4 ! root 3574: if (unsignedp && GET_MODE_BITSIZE (GET_MODE (to)) <= HOST_BITS_PER_WIDE_INT)
1.1 root 3575: for (fmode = GET_MODE (from); fmode != VOIDmode;
3576: fmode = GET_MODE_WIDER_MODE (fmode))
3577: /* Make sure we won't lose significant bits doing this. */
3578: if (GET_MODE_BITSIZE (fmode) > GET_MODE_BITSIZE (GET_MODE (to))
3579: && CODE_FOR_nothing != can_fix_p (GET_MODE (to), fmode, 0,
3580: &must_trunc))
3581: {
3582: int bitsize = GET_MODE_BITSIZE (GET_MODE (to));
3583: REAL_VALUE_TYPE offset = REAL_VALUE_LDEXP (dconst1, bitsize - 1);
3584: rtx limit = immed_real_const_1 (offset, fmode);
3585: rtx lab1 = gen_label_rtx ();
3586: rtx lab2 = gen_label_rtx ();
3587: rtx insn;
3588:
3589: emit_queue ();
3590: to = protect_from_queue (to, 1);
3591: from = protect_from_queue (from, 0);
3592:
3593: if (flag_force_mem)
3594: from = force_not_mem (from);
3595:
3596: if (fmode != GET_MODE (from))
3597: from = convert_to_mode (fmode, from, 0);
3598:
3599: /* See if we need to do the subtraction. */
3600: do_pending_stack_adjust ();
1.1.1.4 ! root 3601: emit_cmp_insn (from, limit, GE, NULL_RTX, GET_MODE (from), 0, 0);
1.1 root 3602: emit_jump_insn (gen_bge (lab1));
3603:
3604: /* If not, do the signed "fix" and branch around fixup code. */
3605: expand_fix (to, from, 0);
3606: emit_jump_insn (gen_jump (lab2));
3607: emit_barrier ();
3608:
3609: /* Otherwise, subtract 2**(N-1), convert to signed number,
3610: then add 2**(N-1). Do the addition using XOR since this
3611: will often generate better code. */
3612: emit_label (lab1);
3613: target = expand_binop (GET_MODE (from), sub_optab, from, limit,
1.1.1.4 ! root 3614: NULL_RTX, 0, OPTAB_LIB_WIDEN);
1.1 root 3615: expand_fix (to, target, 0);
3616: target = expand_binop (GET_MODE (to), xor_optab, to,
1.1.1.4 ! root 3617: GEN_INT ((HOST_WIDE_INT) 1 << (bitsize - 1)),
1.1 root 3618: to, 1, OPTAB_LIB_WIDEN);
3619:
3620: if (target != to)
3621: emit_move_insn (to, target);
3622:
3623: emit_label (lab2);
3624:
3625: /* Make a place for a REG_NOTE and add it. */
3626: insn = emit_move_insn (to, to);
3627: REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL,
3628: gen_rtx (UNSIGNED_FIX, GET_MODE (to),
3629: from), REG_NOTES (insn));
3630:
3631: return;
3632: }
3633: #endif
3634:
3635: /* We can't do it with an insn, so use a library call. But first ensure
3636: that the mode of TO is at least as wide as SImode, since those are the
3637: only library calls we know about. */
3638:
3639: if (GET_MODE_SIZE (GET_MODE (to)) < GET_MODE_SIZE (SImode))
3640: {
3641: target = gen_reg_rtx (SImode);
3642:
3643: expand_fix (target, from, unsignedp);
3644: }
3645: else if (GET_MODE (from) == SFmode)
3646: {
3647: if (GET_MODE (to) == SImode)
3648: libfcn = unsignedp ? fixunssfsi_libfunc : fixsfsi_libfunc;
3649: else if (GET_MODE (to) == DImode)
3650: libfcn = unsignedp ? fixunssfdi_libfunc : fixsfdi_libfunc;
1.1.1.4 ! root 3651: else if (GET_MODE (to) == TImode)
! 3652: libfcn = unsignedp ? fixunssfti_libfunc : fixsfti_libfunc;
1.1 root 3653: else
3654: abort ();
3655: }
3656: else if (GET_MODE (from) == DFmode)
3657: {
3658: if (GET_MODE (to) == SImode)
3659: libfcn = unsignedp ? fixunsdfsi_libfunc : fixdfsi_libfunc;
3660: else if (GET_MODE (to) == DImode)
3661: libfcn = unsignedp ? fixunsdfdi_libfunc : fixdfdi_libfunc;
1.1.1.4 ! root 3662: else if (GET_MODE (to) == TImode)
! 3663: libfcn = unsignedp ? fixunsdfti_libfunc : fixdfti_libfunc;
! 3664: else
! 3665: abort ();
! 3666: }
! 3667: else if (GET_MODE (from) == XFmode)
! 3668: {
! 3669: if (GET_MODE (to) == SImode)
! 3670: libfcn = unsignedp ? fixunsxfsi_libfunc : fixxfsi_libfunc;
! 3671: else if (GET_MODE (to) == DImode)
! 3672: libfcn = unsignedp ? fixunsxfdi_libfunc : fixxfdi_libfunc;
! 3673: else if (GET_MODE (to) == TImode)
! 3674: libfcn = unsignedp ? fixunsxfti_libfunc : fixxfti_libfunc;
! 3675: else
! 3676: abort ();
! 3677: }
! 3678: else if (GET_MODE (from) == TFmode)
! 3679: {
! 3680: if (GET_MODE (to) == SImode)
! 3681: libfcn = unsignedp ? fixunstfsi_libfunc : fixtfsi_libfunc;
! 3682: else if (GET_MODE (to) == DImode)
! 3683: libfcn = unsignedp ? fixunstfdi_libfunc : fixtfdi_libfunc;
! 3684: else if (GET_MODE (to) == TImode)
! 3685: libfcn = unsignedp ? fixunstfti_libfunc : fixtfti_libfunc;
1.1 root 3686: else
3687: abort ();
3688: }
3689: else
3690: abort ();
3691:
3692: if (libfcn)
3693: {
3694: rtx insns;
3695:
3696: to = protect_from_queue (to, 1);
3697: from = protect_from_queue (from, 0);
3698:
3699: if (flag_force_mem)
3700: from = force_not_mem (from);
3701:
3702: start_sequence ();
3703:
1.1.1.2 root 3704: emit_library_call (libfcn, 1, GET_MODE (to), 1, from, GET_MODE (from));
1.1 root 3705: insns = get_insns ();
3706: end_sequence ();
3707:
3708: emit_libcall_block (insns, target, hard_libcall_value (GET_MODE (to)),
3709: gen_rtx (unsignedp ? FIX : UNSIGNED_FIX,
3710: GET_MODE (to), from));
3711: }
3712:
3713: if (GET_MODE (to) == GET_MODE (target))
3714: emit_move_insn (to, target);
3715: else
3716: convert_move (to, target, 0);
3717: }
3718:
3719: static optab
3720: init_optab (code)
3721: enum rtx_code code;
3722: {
3723: int i;
3724: optab op = (optab) xmalloc (sizeof (struct optab));
3725: op->code = code;
3726: for (i = 0; i < NUM_MACHINE_MODES; i++)
3727: {
3728: op->handlers[i].insn_code = CODE_FOR_nothing;
3729: op->handlers[i].libfunc = 0;
3730: }
3731: return op;
3732: }
3733:
1.1.1.4 ! root 3734: /* Initialize the libfunc fields of an entire group of entries in some
! 3735: optab. Each entry is set equal to a string consisting of a leading
! 3736: pair of underscores followed by a generic operation name followed by
! 3737: a mode name (downshifted to lower case) followed by a single character
! 3738: representing the number of operands for the given operation (which is
! 3739: usually one of the characters '2', '3', or '4').
! 3740:
! 3741: OPTABLE is the table in which libfunc fields are to be initialized.
! 3742: FIRST_MODE is the first machine mode index in the given optab to
! 3743: initialize.
! 3744: LAST_MODE is the last machine mode index in the given optab to
! 3745: initialize.
! 3746: OPNAME is the generic (string) name of the operation.
! 3747: SUFFIX is the character which specifies the number of operands for
! 3748: the given generic operation.
! 3749: */
! 3750:
! 3751: static void
! 3752: init_libfuncs (optable, first_mode, last_mode, opname, suffix)
! 3753: register optab optable;
! 3754: register char *opname;
! 3755: register enum machine_mode first_mode;
! 3756: register enum machine_mode last_mode;
! 3757: register char suffix;
! 3758: {
! 3759: register enum machine_mode mode;
! 3760: register unsigned opname_len = strlen (opname);
! 3761:
! 3762: for (mode = first_mode; (int) mode <= (int) last_mode;
! 3763: mode = (enum machine_mode) ((int) mode + 1))
! 3764: {
! 3765: register char *mname = mode_name[(int) mode];
! 3766: register unsigned mname_len = strlen (mname);
! 3767: register char *libfunc_name
! 3768: = (char *) xmalloc (2 + opname_len + mname_len + 1 + 1);
! 3769: register char *p;
! 3770: register char *q;
! 3771:
! 3772: p = libfunc_name;
! 3773: *p++ = '_';
! 3774: *p++ = '_';
! 3775: for (q = opname; *q; )
! 3776: *p++ = *q++;
! 3777: for (q = mname; *q; q++)
! 3778: *p++ = tolower (*q);
! 3779: *p++ = suffix;
! 3780: *p++ = '\0';
! 3781: optable->handlers[(int) mode].libfunc
! 3782: = gen_rtx (SYMBOL_REF, Pmode, libfunc_name);
! 3783: }
! 3784: }
! 3785:
! 3786: /* Initialize the libfunc fields of an entire group of entries in some
! 3787: optab which correspond to all integer mode operations. The parameters
! 3788: have the same meaning as similarly named ones for the `init_libfuncs'
! 3789: routine. (See above). */
! 3790:
! 3791: static void
! 3792: init_integral_libfuncs (optable, opname, suffix)
! 3793: register optab optable;
! 3794: register char *opname;
! 3795: register char suffix;
! 3796: {
! 3797: init_libfuncs (optable, SImode, TImode, opname, suffix);
! 3798: }
! 3799:
! 3800: /* Initialize the libfunc fields of an entire group of entries in some
! 3801: optab which correspond to all real mode operations. The parameters
! 3802: have the same meaning as similarly named ones for the `init_libfuncs'
! 3803: routine. (See above). */
! 3804:
! 3805: static void
! 3806: init_floating_libfuncs (optable, opname, suffix)
! 3807: register optab optable;
! 3808: register char *opname;
! 3809: register char suffix;
! 3810: {
! 3811: init_libfuncs (optable, SFmode, TFmode, opname, suffix);
! 3812: }
! 3813:
! 3814: /* Initialize the libfunc fields of an entire group of entries in some
! 3815: optab which correspond to all complex floating modes. The parameters
! 3816: have the same meaning as similarly named ones for the `init_libfuncs'
! 3817: routine. (See above). */
! 3818:
! 3819: static void
! 3820: init_complex_libfuncs (optable, opname, suffix)
! 3821: register optab optable;
! 3822: register char *opname;
! 3823: register char suffix;
! 3824: {
! 3825: init_libfuncs (optable, SCmode, TCmode, opname, suffix);
! 3826: }
! 3827:
1.1 root 3828: /* Call this once to initialize the contents of the optabs
3829: appropriately for the current target machine. */
3830:
3831: void
3832: init_optabs ()
3833: {
3834: int i;
3835:
3836: init_fixtab ();
3837: init_floattab ();
3838: init_extends ();
3839:
3840: add_optab = init_optab (PLUS);
3841: sub_optab = init_optab (MINUS);
3842: smul_optab = init_optab (MULT);
3843: smul_widen_optab = init_optab (UNKNOWN);
3844: umul_widen_optab = init_optab (UNKNOWN);
3845: sdiv_optab = init_optab (DIV);
3846: sdivmod_optab = init_optab (UNKNOWN);
3847: udiv_optab = init_optab (UDIV);
3848: udivmod_optab = init_optab (UNKNOWN);
3849: smod_optab = init_optab (MOD);
3850: umod_optab = init_optab (UMOD);
3851: flodiv_optab = init_optab (DIV);
3852: ftrunc_optab = init_optab (UNKNOWN);
3853: and_optab = init_optab (AND);
3854: ior_optab = init_optab (IOR);
3855: xor_optab = init_optab (XOR);
3856: ashl_optab = init_optab (ASHIFT);
3857: ashr_optab = init_optab (ASHIFTRT);
3858: lshl_optab = init_optab (LSHIFT);
3859: lshr_optab = init_optab (LSHIFTRT);
3860: rotl_optab = init_optab (ROTATE);
3861: rotr_optab = init_optab (ROTATERT);
3862: smin_optab = init_optab (SMIN);
3863: smax_optab = init_optab (SMAX);
3864: umin_optab = init_optab (UMIN);
3865: umax_optab = init_optab (UMAX);
3866: mov_optab = init_optab (UNKNOWN);
3867: movstrict_optab = init_optab (UNKNOWN);
3868: cmp_optab = init_optab (UNKNOWN);
3869: ucmp_optab = init_optab (UNKNOWN);
3870: tst_optab = init_optab (UNKNOWN);
3871: neg_optab = init_optab (NEG);
3872: abs_optab = init_optab (ABS);
3873: one_cmpl_optab = init_optab (NOT);
3874: ffs_optab = init_optab (FFS);
1.1.1.2 root 3875: sqrt_optab = init_optab (SQRT);
1.1.1.4 ! root 3876: sin_optab = init_optab (UNKNOWN);
! 3877: cos_optab = init_optab (UNKNOWN);
1.1.1.3 root 3878: strlen_optab = init_optab (UNKNOWN);
1.1 root 3879:
3880: #ifdef HAVE_addqi3
3881: if (HAVE_addqi3)
3882: add_optab->handlers[(int) QImode].insn_code = CODE_FOR_addqi3;
3883: #endif
3884: #ifdef HAVE_addhi3
3885: if (HAVE_addhi3)
3886: add_optab->handlers[(int) HImode].insn_code = CODE_FOR_addhi3;
3887: #endif
3888: #ifdef HAVE_addpsi3
3889: if (HAVE_addpsi3)
3890: add_optab->handlers[(int) PSImode].insn_code = CODE_FOR_addpsi3;
3891: #endif
3892: #ifdef HAVE_addsi3
3893: if (HAVE_addsi3)
3894: add_optab->handlers[(int) SImode].insn_code = CODE_FOR_addsi3;
3895: #endif
3896: #ifdef HAVE_adddi3
3897: if (HAVE_adddi3)
3898: add_optab->handlers[(int) DImode].insn_code = CODE_FOR_adddi3;
3899: #endif
3900: #ifdef HAVE_addti3
3901: if (HAVE_addti3)
3902: add_optab->handlers[(int) TImode].insn_code = CODE_FOR_addti3;
3903: #endif
3904: #ifdef HAVE_addsf3
3905: if (HAVE_addsf3)
3906: add_optab->handlers[(int) SFmode].insn_code = CODE_FOR_addsf3;
3907: #endif
3908: #ifdef HAVE_adddf3
3909: if (HAVE_adddf3)
3910: add_optab->handlers[(int) DFmode].insn_code = CODE_FOR_adddf3;
3911: #endif
1.1.1.4 ! root 3912: #ifdef HAVE_addxf3
! 3913: if (HAVE_addxf3)
! 3914: add_optab->handlers[(int) XFmode].insn_code = CODE_FOR_addxf3;
! 3915: #endif
1.1 root 3916: #ifdef HAVE_addtf3
3917: if (HAVE_addtf3)
3918: add_optab->handlers[(int) TFmode].insn_code = CODE_FOR_addtf3;
3919: #endif
1.1.1.4 ! root 3920: init_integral_libfuncs (add_optab, "add", '3');
! 3921: init_floating_libfuncs (add_optab, "add", '3');
1.1 root 3922:
3923: #ifdef HAVE_subqi3
3924: if (HAVE_subqi3)
3925: sub_optab->handlers[(int) QImode].insn_code = CODE_FOR_subqi3;
3926: #endif
3927: #ifdef HAVE_subhi3
3928: if (HAVE_subhi3)
3929: sub_optab->handlers[(int) HImode].insn_code = CODE_FOR_subhi3;
3930: #endif
3931: #ifdef HAVE_subpsi3
3932: if (HAVE_subpsi3)
3933: sub_optab->handlers[(int) PSImode].insn_code = CODE_FOR_subpsi3;
3934: #endif
3935: #ifdef HAVE_subsi3
3936: if (HAVE_subsi3)
3937: sub_optab->handlers[(int) SImode].insn_code = CODE_FOR_subsi3;
3938: #endif
3939: #ifdef HAVE_subdi3
3940: if (HAVE_subdi3)
3941: sub_optab->handlers[(int) DImode].insn_code = CODE_FOR_subdi3;
3942: #endif
3943: #ifdef HAVE_subti3
3944: if (HAVE_subti3)
1.1.1.2 root 3945: sub_optab->handlers[(int) TImode].insn_code = CODE_FOR_subti3;
1.1 root 3946: #endif
3947: #ifdef HAVE_subsf3
3948: if (HAVE_subsf3)
3949: sub_optab->handlers[(int) SFmode].insn_code = CODE_FOR_subsf3;
3950: #endif
3951: #ifdef HAVE_subdf3
3952: if (HAVE_subdf3)
3953: sub_optab->handlers[(int) DFmode].insn_code = CODE_FOR_subdf3;
3954: #endif
1.1.1.4 ! root 3955: #ifdef HAVE_subxf3
! 3956: if (HAVE_subxf3)
! 3957: sub_optab->handlers[(int) XFmode].insn_code = CODE_FOR_subxf3;
! 3958: #endif
1.1 root 3959: #ifdef HAVE_subtf3
3960: if (HAVE_subtf3)
3961: sub_optab->handlers[(int) TFmode].insn_code = CODE_FOR_subtf3;
3962: #endif
1.1.1.4 ! root 3963: init_integral_libfuncs (sub_optab, "sub", '3');
! 3964: init_floating_libfuncs (sub_optab, "sub", '3');
1.1 root 3965:
3966: #ifdef HAVE_mulqi3
3967: if (HAVE_mulqi3)
3968: smul_optab->handlers[(int) QImode].insn_code = CODE_FOR_mulqi3;
3969: #endif
3970: #ifdef HAVE_mulhi3
3971: if (HAVE_mulhi3)
3972: smul_optab->handlers[(int) HImode].insn_code = CODE_FOR_mulhi3;
3973: #endif
3974: #ifdef HAVE_mulpsi3
3975: if (HAVE_mulpsi3)
3976: smul_optab->handlers[(int) PSImode].insn_code = CODE_FOR_mulpsi3;
3977: #endif
3978: #ifdef HAVE_mulsi3
3979: if (HAVE_mulsi3)
3980: smul_optab->handlers[(int) SImode].insn_code = CODE_FOR_mulsi3;
3981: #endif
3982: #ifdef HAVE_muldi3
3983: if (HAVE_muldi3)
3984: smul_optab->handlers[(int) DImode].insn_code = CODE_FOR_muldi3;
3985: #endif
3986: #ifdef HAVE_multi3
3987: if (HAVE_multi3)
3988: smul_optab->handlers[(int) TImode].insn_code = CODE_FOR_multi3;
3989: #endif
3990: #ifdef HAVE_mulsf3
3991: if (HAVE_mulsf3)
3992: smul_optab->handlers[(int) SFmode].insn_code = CODE_FOR_mulsf3;
3993: #endif
3994: #ifdef HAVE_muldf3
3995: if (HAVE_muldf3)
3996: smul_optab->handlers[(int) DFmode].insn_code = CODE_FOR_muldf3;
3997: #endif
1.1.1.4 ! root 3998: #ifdef HAVE_mulxf3
! 3999: if (HAVE_mulxf3)
! 4000: smul_optab->handlers[(int) XFmode].insn_code = CODE_FOR_mulxf3;
! 4001: #endif
1.1 root 4002: #ifdef HAVE_multf3
4003: if (HAVE_multf3)
4004: smul_optab->handlers[(int) TFmode].insn_code = CODE_FOR_multf3;
4005: #endif
1.1.1.4 ! root 4006: init_integral_libfuncs (smul_optab, "mul", '3');
! 4007: init_floating_libfuncs (smul_optab, "mul", '3');
1.1 root 4008:
4009: #ifdef MULSI3_LIBCALL
4010: smul_optab->handlers[(int) SImode].libfunc
4011: = gen_rtx (SYMBOL_REF, Pmode, MULSI3_LIBCALL);
4012: #endif
4013: #ifdef MULDI3_LIBCALL
4014: smul_optab->handlers[(int) DImode].libfunc
4015: = gen_rtx (SYMBOL_REF, Pmode, MULDI3_LIBCALL);
4016: #endif
1.1.1.4 ! root 4017: #ifdef MULTI3_LIBCALL
! 4018: smul_optab->handlers[(int) TImode].libfunc
! 4019: = gen_rtx (SYMBOL_REF, Pmode, MULTI3_LIBCALL);
! 4020: #endif
1.1 root 4021:
4022: #ifdef HAVE_mulqihi3
4023: if (HAVE_mulqihi3)
4024: smul_widen_optab->handlers[(int) HImode].insn_code = CODE_FOR_mulqihi3;
4025: #endif
4026: #ifdef HAVE_mulhisi3
4027: if (HAVE_mulhisi3)
4028: smul_widen_optab->handlers[(int) SImode].insn_code = CODE_FOR_mulhisi3;
4029: #endif
4030: #ifdef HAVE_mulsidi3
4031: if (HAVE_mulsidi3)
4032: smul_widen_optab->handlers[(int) DImode].insn_code = CODE_FOR_mulsidi3;
4033: #endif
4034: #ifdef HAVE_mulditi3
4035: if (HAVE_mulditi3)
4036: smul_widen_optab->handlers[(int) TImode].insn_code = CODE_FOR_mulditi3;
4037: #endif
4038:
4039: #ifdef HAVE_umulqihi3
4040: if (HAVE_umulqihi3)
4041: umul_widen_optab->handlers[(int) HImode].insn_code = CODE_FOR_umulqihi3;
4042: #endif
4043: #ifdef HAVE_umulhisi3
4044: if (HAVE_umulhisi3)
4045: umul_widen_optab->handlers[(int) SImode].insn_code = CODE_FOR_umulhisi3;
4046: #endif
4047: #ifdef HAVE_umulsidi3
4048: if (HAVE_umulsidi3)
4049: umul_widen_optab->handlers[(int) DImode].insn_code = CODE_FOR_umulsidi3;
4050: #endif
4051: #ifdef HAVE_umulditi3
4052: if (HAVE_umulditi3)
4053: umul_widen_optab->handlers[(int) TImode].insn_code = CODE_FOR_umulditi3;
4054: #endif
4055:
4056: #ifdef HAVE_divqi3
4057: if (HAVE_divqi3)
4058: sdiv_optab->handlers[(int) QImode].insn_code = CODE_FOR_divqi3;
4059: #endif
4060: #ifdef HAVE_divhi3
4061: if (HAVE_divhi3)
4062: sdiv_optab->handlers[(int) HImode].insn_code = CODE_FOR_divhi3;
4063: #endif
4064: #ifdef HAVE_divpsi3
4065: if (HAVE_divpsi3)
4066: sdiv_optab->handlers[(int) PSImode].insn_code = CODE_FOR_divpsi3;
4067: #endif
4068: #ifdef HAVE_divsi3
4069: if (HAVE_divsi3)
4070: sdiv_optab->handlers[(int) SImode].insn_code = CODE_FOR_divsi3;
4071: #endif
4072: #ifdef HAVE_divdi3
4073: if (HAVE_divdi3)
4074: sdiv_optab->handlers[(int) DImode].insn_code = CODE_FOR_divdi3;
4075: #endif
4076: #ifdef HAVE_divti3
4077: if (HAVE_divti3)
4078: sdiv_optab->handlers[(int) TImode].insn_code = CODE_FOR_divti3;
4079: #endif
1.1.1.4 ! root 4080: init_integral_libfuncs (sdiv_optab, "div", '3');
1.1 root 4081:
4082: #ifdef DIVSI3_LIBCALL
4083: sdiv_optab->handlers[(int) SImode].libfunc
4084: = gen_rtx (SYMBOL_REF, Pmode, DIVSI3_LIBCALL);
4085: #endif
4086: #ifdef DIVDI3_LIBCALL
4087: sdiv_optab->handlers[(int) DImode].libfunc
4088: = gen_rtx (SYMBOL_REF, Pmode, DIVDI3_LIBCALL);
1.1.1.4 ! root 4089: #endif
! 4090: #ifdef DIVTI3_LIBCALL
! 4091: sdiv_optab->handlers[(int) TImode].libfunc
! 4092: = gen_rtx (SYMBOL_REF, Pmode, DIVTI3_LIBCALL);
1.1 root 4093: #endif
4094:
4095: #ifdef HAVE_udivqi3
4096: if (HAVE_udivqi3)
4097: udiv_optab->handlers[(int) QImode].insn_code = CODE_FOR_udivqi3;
4098: #endif
4099: #ifdef HAVE_udivhi3
4100: if (HAVE_udivhi3)
4101: udiv_optab->handlers[(int) HImode].insn_code = CODE_FOR_udivhi3;
4102: #endif
4103: #ifdef HAVE_udivpsi3
4104: if (HAVE_udivpsi3)
4105: udiv_optab->handlers[(int) PSImode].insn_code = CODE_FOR_udivpsi3;
4106: #endif
4107: #ifdef HAVE_udivsi3
4108: if (HAVE_udivsi3)
4109: udiv_optab->handlers[(int) SImode].insn_code = CODE_FOR_udivsi3;
4110: #endif
4111: #ifdef HAVE_udivdi3
4112: if (HAVE_udivdi3)
4113: udiv_optab->handlers[(int) DImode].insn_code = CODE_FOR_udivdi3;
4114: #endif
4115: #ifdef HAVE_udivti3
4116: if (HAVE_udivti3)
4117: udiv_optab->handlers[(int) TImode].insn_code = CODE_FOR_udivti3;
4118: #endif
1.1.1.4 ! root 4119: init_integral_libfuncs (udiv_optab, "udiv", '3');
1.1 root 4120:
4121: #ifdef UDIVSI3_LIBCALL
4122: udiv_optab->handlers[(int) SImode].libfunc
4123: = gen_rtx (SYMBOL_REF, Pmode, UDIVSI3_LIBCALL);
4124: #endif
4125: #ifdef UDIVDI3_LIBCALL
4126: udiv_optab->handlers[(int) DImode].libfunc
4127: = gen_rtx (SYMBOL_REF, Pmode, UDIVDI3_LIBCALL);
1.1.1.4 ! root 4128: #endif
! 4129: #ifdef UDIVTI3_LIBCALL
! 4130: udiv_optab->handlers[(int) TImode].libfunc
! 4131: = gen_rtx (SYMBOL_REF, Pmode, UDIVTI3_LIBCALL);
1.1 root 4132: #endif
4133:
4134: #ifdef HAVE_divmodqi4
4135: if (HAVE_divmodqi4)
4136: sdivmod_optab->handlers[(int) QImode].insn_code = CODE_FOR_divmodqi4;
4137: #endif
4138: #ifdef HAVE_divmodhi4
4139: if (HAVE_divmodhi4)
4140: sdivmod_optab->handlers[(int) HImode].insn_code = CODE_FOR_divmodhi4;
4141: #endif
4142: #ifdef HAVE_divmodsi4
4143: if (HAVE_divmodsi4)
4144: sdivmod_optab->handlers[(int) SImode].insn_code = CODE_FOR_divmodsi4;
4145: #endif
4146: #ifdef HAVE_divmoddi4
4147: if (HAVE_divmoddi4)
4148: sdivmod_optab->handlers[(int) DImode].insn_code = CODE_FOR_divmoddi4;
4149: #endif
4150: #ifdef HAVE_divmodti4
4151: if (HAVE_divmodti4)
4152: sdivmod_optab->handlers[(int) TImode].insn_code = CODE_FOR_divmodti4;
4153: #endif
1.1.1.4 ! root 4154: init_integral_libfuncs (sdivmod_optab, "divmod", '4');
1.1 root 4155:
4156: #ifdef HAVE_udivmodqi4
4157: if (HAVE_udivmodqi4)
4158: udivmod_optab->handlers[(int) QImode].insn_code = CODE_FOR_udivmodqi4;
4159: #endif
4160: #ifdef HAVE_udivmodhi4
4161: if (HAVE_udivmodhi4)
4162: udivmod_optab->handlers[(int) HImode].insn_code = CODE_FOR_udivmodhi4;
4163: #endif
4164: #ifdef HAVE_udivmodsi4
4165: if (HAVE_udivmodsi4)
4166: udivmod_optab->handlers[(int) SImode].insn_code = CODE_FOR_udivmodsi4;
4167: #endif
4168: #ifdef HAVE_udivmoddi4
4169: if (HAVE_udivmoddi4)
4170: udivmod_optab->handlers[(int) DImode].insn_code = CODE_FOR_udivmoddi4;
4171: #endif
4172: #ifdef HAVE_udivmodti4
4173: if (HAVE_udivmodti4)
4174: udivmod_optab->handlers[(int) TImode].insn_code = CODE_FOR_udivmodti4;
4175: #endif
1.1.1.4 ! root 4176: init_integral_libfuncs (udivmod_optab, "udivmod", '4');
1.1 root 4177:
4178: #ifdef HAVE_modqi3
4179: if (HAVE_modqi3)
4180: smod_optab->handlers[(int) QImode].insn_code = CODE_FOR_modqi3;
4181: #endif
4182: #ifdef HAVE_modhi3
4183: if (HAVE_modhi3)
4184: smod_optab->handlers[(int) HImode].insn_code = CODE_FOR_modhi3;
4185: #endif
4186: #ifdef HAVE_modpsi3
4187: if (HAVE_modpsi3)
4188: smod_optab->handlers[(int) PSImode].insn_code = CODE_FOR_modpsi3;
4189: #endif
4190: #ifdef HAVE_modsi3
4191: if (HAVE_modsi3)
4192: smod_optab->handlers[(int) SImode].insn_code = CODE_FOR_modsi3;
4193: #endif
4194: #ifdef HAVE_moddi3
4195: if (HAVE_moddi3)
4196: smod_optab->handlers[(int) DImode].insn_code = CODE_FOR_moddi3;
4197: #endif
4198: #ifdef HAVE_modti3
4199: if (HAVE_modti3)
4200: smod_optab->handlers[(int) TImode].insn_code = CODE_FOR_modti3;
4201: #endif
1.1.1.4 ! root 4202: init_integral_libfuncs (smod_optab, "mod", '3');
1.1 root 4203:
4204: #ifdef MODSI3_LIBCALL
4205: smod_optab->handlers[(int) SImode].libfunc
4206: = gen_rtx (SYMBOL_REF, Pmode, MODSI3_LIBCALL);
4207: #endif
4208: #ifdef MODDI3_LIBCALL
4209: smod_optab->handlers[(int) DImode].libfunc
4210: = gen_rtx (SYMBOL_REF, Pmode, MODDI3_LIBCALL);
1.1.1.4 ! root 4211: #endif
! 4212: #ifdef MODTI3_LIBCALL
! 4213: smod_optab->handlers[(int) TImode].libfunc
! 4214: = gen_rtx (SYMBOL_REF, Pmode, MODTI3_LIBCALL);
1.1 root 4215: #endif
4216:
4217: #ifdef HAVE_umodqi3
4218: if (HAVE_umodqi3)
4219: umod_optab->handlers[(int) QImode].insn_code = CODE_FOR_umodqi3;
4220: #endif
4221: #ifdef HAVE_umodhi3
4222: if (HAVE_umodhi3)
4223: umod_optab->handlers[(int) HImode].insn_code = CODE_FOR_umodhi3;
4224: #endif
4225: #ifdef HAVE_umodpsi3
4226: if (HAVE_umodpsi3)
4227: umod_optab->handlers[(int) PSImode].insn_code = CODE_FOR_umodpsi3;
4228: #endif
4229: #ifdef HAVE_umodsi3
4230: if (HAVE_umodsi3)
4231: umod_optab->handlers[(int) SImode].insn_code = CODE_FOR_umodsi3;
4232: #endif
4233: #ifdef HAVE_umoddi3
4234: if (HAVE_umoddi3)
4235: umod_optab->handlers[(int) DImode].insn_code = CODE_FOR_umoddi3;
4236: #endif
4237: #ifdef HAVE_umodti3
4238: if (HAVE_umodti3)
4239: umod_optab->handlers[(int) TImode].insn_code = CODE_FOR_umodti3;
4240: #endif
1.1.1.4 ! root 4241: init_integral_libfuncs (umod_optab, "umod", '3');
1.1 root 4242:
4243: #ifdef UMODSI3_LIBCALL
4244: umod_optab->handlers[(int) SImode].libfunc
4245: = gen_rtx (SYMBOL_REF, Pmode, UMODSI3_LIBCALL);
4246: #endif
4247: #ifdef UMODDI3_LIBCALL
4248: umod_optab->handlers[(int) DImode].libfunc
4249: = gen_rtx (SYMBOL_REF, Pmode, UMODDI3_LIBCALL);
1.1.1.4 ! root 4250: #endif
! 4251: #ifdef UMODTI3_LIBCALL
! 4252: umod_optab->handlers[(int) TImode].libfunc
! 4253: = gen_rtx (SYMBOL_REF, Pmode, UMODTI3_LIBCALL);
1.1 root 4254: #endif
4255:
4256: #ifdef HAVE_divsf3
4257: if (HAVE_divsf3)
4258: flodiv_optab->handlers[(int) SFmode].insn_code = CODE_FOR_divsf3;
4259: #endif
4260: #ifdef HAVE_divdf3
4261: if (HAVE_divdf3)
4262: flodiv_optab->handlers[(int) DFmode].insn_code = CODE_FOR_divdf3;
4263: #endif
1.1.1.4 ! root 4264: #ifdef HAVE_divxf3
! 4265: if (HAVE_divxf3)
! 4266: flodiv_optab->handlers[(int) XFmode].insn_code = CODE_FOR_divxf3;
! 4267: #endif
1.1 root 4268: #ifdef HAVE_divtf3
4269: if (HAVE_divtf3)
4270: flodiv_optab->handlers[(int) TFmode].insn_code = CODE_FOR_divtf3;
4271: #endif
1.1.1.4 ! root 4272: init_floating_libfuncs (flodiv_optab, "div", '3');
1.1 root 4273:
4274: #ifdef HAVE_ftruncsf2
4275: if (HAVE_ftruncsf2)
4276: ftrunc_optab->handlers[(int) SFmode].insn_code = CODE_FOR_ftruncsf2;
4277: #endif
4278: #ifdef HAVE_ftruncdf2
4279: if (HAVE_ftruncdf2)
4280: ftrunc_optab->handlers[(int) DFmode].insn_code = CODE_FOR_ftruncdf2;
4281: #endif
1.1.1.4 ! root 4282: #ifdef HAVE_ftruncxf2
! 4283: if (HAVE_ftruncxf2)
! 4284: ftrunc_optab->handlers[(int) XFmode].insn_code = CODE_FOR_ftruncxf2;
! 4285: #endif
1.1 root 4286: #ifdef HAVE_ftrunctf2
4287: if (HAVE_ftrunctf2)
4288: ftrunc_optab->handlers[(int) TFmode].insn_code = CODE_FOR_ftrunctf2;
4289: #endif
1.1.1.4 ! root 4290: init_floating_libfuncs (ftrunc_optab, "ftrunc", '2');
1.1 root 4291:
4292: #ifdef HAVE_andqi3
4293: if (HAVE_andqi3)
4294: and_optab->handlers[(int) QImode].insn_code = CODE_FOR_andqi3;
4295: #endif
4296: #ifdef HAVE_andhi3
4297: if (HAVE_andhi3)
4298: and_optab->handlers[(int) HImode].insn_code = CODE_FOR_andhi3;
4299: #endif
4300: #ifdef HAVE_andpsi3
4301: if (HAVE_andpsi3)
4302: and_optab->handlers[(int) PSImode].insn_code = CODE_FOR_andpsi3;
4303: #endif
4304: #ifdef HAVE_andsi3
4305: if (HAVE_andsi3)
4306: and_optab->handlers[(int) SImode].insn_code = CODE_FOR_andsi3;
4307: #endif
4308: #ifdef HAVE_anddi3
4309: if (HAVE_anddi3)
4310: and_optab->handlers[(int) DImode].insn_code = CODE_FOR_anddi3;
4311: #endif
4312: #ifdef HAVE_andti3
4313: if (HAVE_andti3)
4314: and_optab->handlers[(int) TImode].insn_code = CODE_FOR_andti3;
4315: #endif
1.1.1.4 ! root 4316: init_integral_libfuncs (and_optab, "and", '3');
1.1 root 4317:
4318: #ifdef HAVE_iorqi3
4319: if (HAVE_iorqi3)
4320: ior_optab->handlers[(int) QImode].insn_code = CODE_FOR_iorqi3;
4321: #endif
4322: #ifdef HAVE_iorhi3
4323: if (HAVE_iorhi3)
4324: ior_optab->handlers[(int) HImode].insn_code = CODE_FOR_iorhi3;
4325: #endif
4326: #ifdef HAVE_iorpsi3
4327: if (HAVE_iorpsi3)
4328: ior_optab->handlers[(int) PSImode].insn_code = CODE_FOR_iorpsi3;
4329: #endif
4330: #ifdef HAVE_iorsi3
4331: if (HAVE_iorsi3)
4332: ior_optab->handlers[(int) SImode].insn_code = CODE_FOR_iorsi3;
4333: #endif
4334: #ifdef HAVE_iordi3
4335: if (HAVE_iordi3)
4336: ior_optab->handlers[(int) DImode].insn_code = CODE_FOR_iordi3;
4337: #endif
4338: #ifdef HAVE_iorti3
4339: if (HAVE_iorti3)
4340: ior_optab->handlers[(int) TImode].insn_code = CODE_FOR_iorti3;
4341: #endif
1.1.1.4 ! root 4342: init_integral_libfuncs (ior_optab, "ior", '3');
1.1 root 4343:
4344: #ifdef HAVE_xorqi3
4345: if (HAVE_xorqi3)
4346: xor_optab->handlers[(int) QImode].insn_code = CODE_FOR_xorqi3;
4347: #endif
4348: #ifdef HAVE_xorhi3
4349: if (HAVE_xorhi3)
4350: xor_optab->handlers[(int) HImode].insn_code = CODE_FOR_xorhi3;
4351: #endif
4352: #ifdef HAVE_xorpsi3
4353: if (HAVE_xorpsi3)
4354: xor_optab->handlers[(int) PSImode].insn_code = CODE_FOR_xorpsi3;
4355: #endif
4356: #ifdef HAVE_xorsi3
4357: if (HAVE_xorsi3)
4358: xor_optab->handlers[(int) SImode].insn_code = CODE_FOR_xorsi3;
4359: #endif
4360: #ifdef HAVE_xordi3
4361: if (HAVE_xordi3)
4362: xor_optab->handlers[(int) DImode].insn_code = CODE_FOR_xordi3;
4363: #endif
4364: #ifdef HAVE_xorti3
4365: if (HAVE_xorti3)
4366: xor_optab->handlers[(int) TImode].insn_code = CODE_FOR_xorti3;
4367: #endif
1.1.1.4 ! root 4368: init_integral_libfuncs (xor_optab, "xor", '3');
1.1 root 4369:
4370: #ifdef HAVE_ashlqi3
4371: if (HAVE_ashlqi3)
4372: ashl_optab->handlers[(int) QImode].insn_code = CODE_FOR_ashlqi3;
4373: #endif
4374: #ifdef HAVE_ashlhi3
4375: if (HAVE_ashlhi3)
4376: ashl_optab->handlers[(int) HImode].insn_code = CODE_FOR_ashlhi3;
4377: #endif
4378: #ifdef HAVE_ashlpsi3
4379: if (HAVE_ashlpsi3)
4380: ashl_optab->handlers[(int) PSImode].insn_code = CODE_FOR_ashlpsi3;
4381: #endif
4382: #ifdef HAVE_ashlsi3
4383: if (HAVE_ashlsi3)
4384: ashl_optab->handlers[(int) SImode].insn_code = CODE_FOR_ashlsi3;
4385: #endif
4386: #ifdef HAVE_ashldi3
4387: if (HAVE_ashldi3)
4388: ashl_optab->handlers[(int) DImode].insn_code = CODE_FOR_ashldi3;
4389: #endif
4390: #ifdef HAVE_ashlti3
4391: if (HAVE_ashlti3)
4392: ashl_optab->handlers[(int) TImode].insn_code = CODE_FOR_ashlti3;
4393: #endif
1.1.1.4 ! root 4394: init_integral_libfuncs (ashl_optab, "ashl", '3');
1.1 root 4395:
4396: #ifdef HAVE_ashrqi3
4397: if (HAVE_ashrqi3)
4398: ashr_optab->handlers[(int) QImode].insn_code = CODE_FOR_ashrqi3;
4399: #endif
4400: #ifdef HAVE_ashrhi3
4401: if (HAVE_ashrhi3)
4402: ashr_optab->handlers[(int) HImode].insn_code = CODE_FOR_ashrhi3;
4403: #endif
4404: #ifdef HAVE_ashrpsi3
4405: if (HAVE_ashrpsi3)
4406: ashr_optab->handlers[(int) PSImode].insn_code = CODE_FOR_ashrpsi3;
4407: #endif
4408: #ifdef HAVE_ashrsi3
4409: if (HAVE_ashrsi3)
4410: ashr_optab->handlers[(int) SImode].insn_code = CODE_FOR_ashrsi3;
4411: #endif
4412: #ifdef HAVE_ashrdi3
4413: if (HAVE_ashrdi3)
4414: ashr_optab->handlers[(int) DImode].insn_code = CODE_FOR_ashrdi3;
4415: #endif
4416: #ifdef HAVE_ashrti3
4417: if (HAVE_ashrti3)
4418: ashr_optab->handlers[(int) TImode].insn_code = CODE_FOR_ashrti3;
4419: #endif
1.1.1.4 ! root 4420: init_integral_libfuncs (ashr_optab, "ashr", '3');
1.1 root 4421:
4422: #ifdef HAVE_lshlqi3
4423: if (HAVE_lshlqi3)
4424: lshl_optab->handlers[(int) QImode].insn_code = CODE_FOR_lshlqi3;
4425: #endif
4426: #ifdef HAVE_lshlhi3
4427: if (HAVE_lshlhi3)
4428: lshl_optab->handlers[(int) HImode].insn_code = CODE_FOR_lshlhi3;
4429: #endif
4430: #ifdef HAVE_lshlpsi3
4431: if (HAVE_lshlpsi3)
4432: lshl_optab->handlers[(int) PSImode].insn_code = CODE_FOR_lshlpsi3;
4433: #endif
4434: #ifdef HAVE_lshlsi3
4435: if (HAVE_lshlsi3)
4436: lshl_optab->handlers[(int) SImode].insn_code = CODE_FOR_lshlsi3;
4437: #endif
4438: #ifdef HAVE_lshldi3
4439: if (HAVE_lshldi3)
4440: lshl_optab->handlers[(int) DImode].insn_code = CODE_FOR_lshldi3;
4441: #endif
4442: #ifdef HAVE_lshlti3
4443: if (HAVE_lshlti3)
4444: lshl_optab->handlers[(int) TImode].insn_code = CODE_FOR_lshlti3;
4445: #endif
1.1.1.4 ! root 4446: init_integral_libfuncs (lshl_optab, "lshl", '3');
1.1 root 4447:
4448: #ifdef HAVE_lshrqi3
4449: if (HAVE_lshrqi3)
4450: lshr_optab->handlers[(int) QImode].insn_code = CODE_FOR_lshrqi3;
4451: #endif
4452: #ifdef HAVE_lshrhi3
4453: if (HAVE_lshrhi3)
4454: lshr_optab->handlers[(int) HImode].insn_code = CODE_FOR_lshrhi3;
4455: #endif
4456: #ifdef HAVE_lshrpsi3
4457: if (HAVE_lshrpsi3)
4458: lshr_optab->handlers[(int) PSImode].insn_code = CODE_FOR_lshrpsi3;
4459: #endif
4460: #ifdef HAVE_lshrsi3
4461: if (HAVE_lshrsi3)
4462: lshr_optab->handlers[(int) SImode].insn_code = CODE_FOR_lshrsi3;
4463: #endif
4464: #ifdef HAVE_lshrdi3
4465: if (HAVE_lshrdi3)
4466: lshr_optab->handlers[(int) DImode].insn_code = CODE_FOR_lshrdi3;
4467: #endif
4468: #ifdef HAVE_lshrti3
4469: if (HAVE_lshrti3)
4470: lshr_optab->handlers[(int) TImode].insn_code = CODE_FOR_lshrti3;
4471: #endif
1.1.1.4 ! root 4472: init_integral_libfuncs (lshr_optab, "lshr", '3');
1.1 root 4473:
4474: #ifdef HAVE_rotlqi3
4475: if (HAVE_rotlqi3)
4476: rotl_optab->handlers[(int) QImode].insn_code = CODE_FOR_rotlqi3;
4477: #endif
4478: #ifdef HAVE_rotlhi3
4479: if (HAVE_rotlhi3)
4480: rotl_optab->handlers[(int) HImode].insn_code = CODE_FOR_rotlhi3;
4481: #endif
4482: #ifdef HAVE_rotlpsi3
4483: if (HAVE_rotlpsi3)
4484: rotl_optab->handlers[(int) PSImode].insn_code = CODE_FOR_rotlpsi3;
4485: #endif
4486: #ifdef HAVE_rotlsi3
4487: if (HAVE_rotlsi3)
4488: rotl_optab->handlers[(int) SImode].insn_code = CODE_FOR_rotlsi3;
4489: #endif
4490: #ifdef HAVE_rotldi3
4491: if (HAVE_rotldi3)
4492: rotl_optab->handlers[(int) DImode].insn_code = CODE_FOR_rotldi3;
4493: #endif
4494: #ifdef HAVE_rotlti3
4495: if (HAVE_rotlti3)
4496: rotl_optab->handlers[(int) TImode].insn_code = CODE_FOR_rotlti3;
4497: #endif
1.1.1.4 ! root 4498: init_integral_libfuncs (rotl_optab, "rotl", '3');
1.1 root 4499:
4500: #ifdef HAVE_rotrqi3
4501: if (HAVE_rotrqi3)
4502: rotr_optab->handlers[(int) QImode].insn_code = CODE_FOR_rotrqi3;
4503: #endif
4504: #ifdef HAVE_rotrhi3
4505: if (HAVE_rotrhi3)
4506: rotr_optab->handlers[(int) HImode].insn_code = CODE_FOR_rotrhi3;
4507: #endif
4508: #ifdef HAVE_rotrpsi3
4509: if (HAVE_rotrpsi3)
4510: rotr_optab->handlers[(int) PSImode].insn_code = CODE_FOR_rotrpsi3;
4511: #endif
4512: #ifdef HAVE_rotrsi3
4513: if (HAVE_rotrsi3)
4514: rotr_optab->handlers[(int) SImode].insn_code = CODE_FOR_rotrsi3;
4515: #endif
4516: #ifdef HAVE_rotrdi3
4517: if (HAVE_rotrdi3)
4518: rotr_optab->handlers[(int) DImode].insn_code = CODE_FOR_rotrdi3;
4519: #endif
4520: #ifdef HAVE_rotrti3
4521: if (HAVE_rotrti3)
4522: rotr_optab->handlers[(int) TImode].insn_code = CODE_FOR_rotrti3;
4523: #endif
1.1.1.4 ! root 4524: init_integral_libfuncs (rotr_optab, "rotr", '3');
1.1 root 4525:
4526: #ifdef HAVE_sminqi3
4527: if (HAVE_sminqi3)
4528: smin_optab->handlers[(int) QImode].insn_code = CODE_FOR_sminqi3;
4529: #endif
4530: #ifdef HAVE_sminhi3
4531: if (HAVE_sminhi3)
4532: smin_optab->handlers[(int) HImode].insn_code = CODE_FOR_sminhi3;
4533: #endif
4534: #ifdef HAVE_sminsi3
4535: if (HAVE_sminsi3)
4536: smin_optab->handlers[(int) SImode].insn_code = CODE_FOR_sminsi3;
4537: #endif
4538: #ifdef HAVE_smindi3
4539: if (HAVE_smindi3)
4540: smin_optab->handlers[(int) DImode].insn_code = CODE_FOR_smindi3;
4541: #endif
4542: #ifdef HAVE_sminti3
4543: if (HAVE_sminti3)
4544: smin_optab->handlers[(int) TImode].insn_code = CODE_FOR_sminti3;
4545: #endif
1.1.1.4 ! root 4546: #ifdef HAVE_minsf3
! 4547: if (HAVE_minsf3)
! 4548: smin_optab->handlers[(int) SFmode].insn_code = CODE_FOR_minsf3;
! 4549: #endif
! 4550: #ifdef HAVE_mindf3
! 4551: if (HAVE_mindf3)
! 4552: smin_optab->handlers[(int) DFmode].insn_code = CODE_FOR_mindf3;
! 4553: #endif
! 4554: #ifdef HAVE_minxf3
! 4555: if (HAVE_minxf3)
! 4556: smin_optab->handlers[(int) XFmode].insn_code = CODE_FOR_minxf3;
! 4557: #endif
! 4558: #ifdef HAVE_mintf3
! 4559: if (HAVE_mintf3)
! 4560: smin_optab->handlers[(int) TFmode].insn_code = CODE_FOR_mintf3;
1.1 root 4561: #endif
1.1.1.4 ! root 4562: init_integral_libfuncs (smin_optab, "min", '3');
! 4563: init_floating_libfuncs (smin_optab, "min", '3');
1.1 root 4564:
4565: #ifdef HAVE_smaxqi3
4566: if (HAVE_smaxqi3)
4567: smax_optab->handlers[(int) QImode].insn_code = CODE_FOR_smaxqi3;
4568: #endif
4569: #ifdef HAVE_smaxhi3
4570: if (HAVE_smaxhi3)
4571: smax_optab->handlers[(int) HImode].insn_code = CODE_FOR_smaxhi3;
4572: #endif
4573: #ifdef HAVE_smaxsi3
4574: if (HAVE_smaxsi3)
4575: smax_optab->handlers[(int) SImode].insn_code = CODE_FOR_smaxsi3;
4576: #endif
4577: #ifdef HAVE_smaxdi3
4578: if (HAVE_smaxdi3)
4579: smax_optab->handlers[(int) DImode].insn_code = CODE_FOR_smaxdi3;
4580: #endif
4581: #ifdef HAVE_smaxti3
4582: if (HAVE_smaxti3)
4583: smax_optab->handlers[(int) TImode].insn_code = CODE_FOR_smaxti3;
4584: #endif
1.1.1.4 ! root 4585: #ifdef HAVE_maxsf3
! 4586: if (HAVE_maxsf3)
! 4587: smax_optab->handlers[(int) SFmode].insn_code = CODE_FOR_maxsf3;
! 4588: #endif
! 4589: #ifdef HAVE_maxdf3
! 4590: if (HAVE_maxdf3)
! 4591: smax_optab->handlers[(int) DFmode].insn_code = CODE_FOR_maxdf3;
! 4592: #endif
! 4593: #ifdef HAVE_maxxf3
! 4594: if (HAVE_maxxf3)
! 4595: smax_optab->handlers[(int) XFmode].insn_code = CODE_FOR_maxxf3;
! 4596: #endif
! 4597: #ifdef HAVE_maxtf3
! 4598: if (HAVE_maxtf3)
! 4599: smax_optab->handlers[(int) TFmode].insn_code = CODE_FOR_maxtf3;
1.1 root 4600: #endif
1.1.1.4 ! root 4601: init_integral_libfuncs (smax_optab, "max", '3');
! 4602: init_floating_libfuncs (smax_optab, "max", '3');
1.1 root 4603:
4604: #ifdef HAVE_uminqi3
4605: if (HAVE_uminqi3)
4606: umin_optab->handlers[(int) QImode].insn_code = CODE_FOR_uminqi3;
4607: #endif
4608: #ifdef HAVE_uminhi3
4609: if (HAVE_uminhi3)
4610: umin_optab->handlers[(int) HImode].insn_code = CODE_FOR_uminhi3;
4611: #endif
4612: #ifdef HAVE_uminsi3
4613: if (HAVE_uminsi3)
4614: umin_optab->handlers[(int) SImode].insn_code = CODE_FOR_uminsi3;
4615: #endif
4616: #ifdef HAVE_umindi3
4617: if (HAVE_umindi3)
4618: umin_optab->handlers[(int) DImode].insn_code = CODE_FOR_umindi3;
4619: #endif
4620: #ifdef HAVE_uminti3
4621: if (HAVE_uminti3)
4622: umin_optab->handlers[(int) TImode].insn_code = CODE_FOR_uminti3;
4623: #endif
1.1.1.4 ! root 4624: init_integral_libfuncs (umin_optab, "umin", '3');
1.1 root 4625:
4626: #ifdef HAVE_umaxqi3
4627: if (HAVE_umaxqi3)
4628: umax_optab->handlers[(int) QImode].insn_code = CODE_FOR_umaxqi3;
4629: #endif
4630: #ifdef HAVE_umaxhi3
4631: if (HAVE_umaxhi3)
4632: umax_optab->handlers[(int) HImode].insn_code = CODE_FOR_umaxhi3;
4633: #endif
4634: #ifdef HAVE_umaxsi3
4635: if (HAVE_umaxsi3)
4636: umax_optab->handlers[(int) SImode].insn_code = CODE_FOR_umaxsi3;
4637: #endif
4638: #ifdef HAVE_umaxdi3
4639: if (HAVE_umaxdi3)
4640: umax_optab->handlers[(int) DImode].insn_code = CODE_FOR_umaxdi3;
4641: #endif
4642: #ifdef HAVE_umaxti3
4643: if (HAVE_umaxti3)
4644: umax_optab->handlers[(int) TImode].insn_code = CODE_FOR_umaxti3;
4645: #endif
1.1.1.4 ! root 4646: init_integral_libfuncs (umax_optab, "umax", '3');
1.1 root 4647:
4648: #ifdef HAVE_negqi2
4649: if (HAVE_negqi2)
4650: neg_optab->handlers[(int) QImode].insn_code = CODE_FOR_negqi2;
4651: #endif
4652: #ifdef HAVE_neghi2
4653: if (HAVE_neghi2)
4654: neg_optab->handlers[(int) HImode].insn_code = CODE_FOR_neghi2;
4655: #endif
4656: #ifdef HAVE_negpsi2
4657: if (HAVE_negpsi2)
4658: neg_optab->handlers[(int) PSImode].insn_code = CODE_FOR_negpsi2;
4659: #endif
4660: #ifdef HAVE_negsi2
4661: if (HAVE_negsi2)
4662: neg_optab->handlers[(int) SImode].insn_code = CODE_FOR_negsi2;
4663: #endif
4664: #ifdef HAVE_negdi2
4665: if (HAVE_negdi2)
4666: neg_optab->handlers[(int) DImode].insn_code = CODE_FOR_negdi2;
4667: #endif
4668: #ifdef HAVE_negti2
4669: if (HAVE_negti2)
4670: neg_optab->handlers[(int) TImode].insn_code = CODE_FOR_negti2;
4671: #endif
4672: #ifdef HAVE_negsf2
4673: if (HAVE_negsf2)
4674: neg_optab->handlers[(int) SFmode].insn_code = CODE_FOR_negsf2;
4675: #endif
4676: #ifdef HAVE_negdf2
4677: if (HAVE_negdf2)
4678: neg_optab->handlers[(int) DFmode].insn_code = CODE_FOR_negdf2;
4679: #endif
1.1.1.4 ! root 4680: #ifdef HAVE_negxf2
! 4681: if (HAVE_negxf2)
! 4682: neg_optab->handlers[(int) XFmode].insn_code = CODE_FOR_negxf2;
! 4683: #endif
1.1 root 4684: #ifdef HAVE_negtf2
4685: if (HAVE_negtf2)
4686: neg_optab->handlers[(int) TFmode].insn_code = CODE_FOR_negtf2;
4687: #endif
1.1.1.4 ! root 4688: init_integral_libfuncs (neg_optab, "neg", '2');
! 4689: init_floating_libfuncs (neg_optab, "neg", '2');
1.1 root 4690:
4691: #ifdef HAVE_absqi2
4692: if (HAVE_absqi2)
4693: abs_optab->handlers[(int) QImode].insn_code = CODE_FOR_absqi2;
4694: #endif
4695: #ifdef HAVE_abshi2
4696: if (HAVE_abshi2)
4697: abs_optab->handlers[(int) HImode].insn_code = CODE_FOR_abshi2;
4698: #endif
4699: #ifdef HAVE_abspsi2
4700: if (HAVE_abspsi2)
4701: abs_optab->handlers[(int) PSImode].insn_code = CODE_FOR_abspsi2;
4702: #endif
4703: #ifdef HAVE_abssi2
4704: if (HAVE_abssi2)
4705: abs_optab->handlers[(int) SImode].insn_code = CODE_FOR_abssi2;
4706: #endif
4707: #ifdef HAVE_absdi2
4708: if (HAVE_absdi2)
4709: abs_optab->handlers[(int) DImode].insn_code = CODE_FOR_absdi2;
4710: #endif
4711: #ifdef HAVE_absti2
4712: if (HAVE_absti2)
4713: abs_optab->handlers[(int) TImode].insn_code = CODE_FOR_absti2;
4714: #endif
4715: #ifdef HAVE_abssf2
4716: if (HAVE_abssf2)
4717: abs_optab->handlers[(int) SFmode].insn_code = CODE_FOR_abssf2;
4718: #endif
4719: #ifdef HAVE_absdf2
4720: if (HAVE_absdf2)
4721: abs_optab->handlers[(int) DFmode].insn_code = CODE_FOR_absdf2;
4722: #endif
1.1.1.4 ! root 4723: #ifdef HAVE_absxf2
! 4724: if (HAVE_absxf2)
! 4725: abs_optab->handlers[(int) XFmode].insn_code = CODE_FOR_absxf2;
! 4726: #endif
1.1 root 4727: #ifdef HAVE_abstf2
4728: if (HAVE_abstf2)
4729: abs_optab->handlers[(int) TFmode].insn_code = CODE_FOR_abstf2;
4730: #endif
1.1.1.4 ! root 4731:
! 4732: /* Use cabs for DC complex abs, since systems generally have cabs.
! 4733: Don't define any libcall for SCmode, so that cabs will be used. */
! 4734: abs_optab->handlers[(int) DCmode].libfunc
! 4735: = gen_rtx (SYMBOL_REF, Pmode, "cabs");
1.1 root 4736:
1.1.1.2 root 4737: #ifdef HAVE_sqrtqi2
4738: if (HAVE_sqrtqi2)
4739: sqrt_optab->handlers[(int) QImode].insn_code = CODE_FOR_sqrtqi2;
4740: #endif
4741: #ifdef HAVE_sqrthi2
4742: if (HAVE_sqrthi2)
4743: sqrt_optab->handlers[(int) HImode].insn_code = CODE_FOR_sqrthi2;
4744: #endif
4745: #ifdef HAVE_sqrtpsi2
4746: if (HAVE_sqrtpsi2)
4747: sqrt_optab->handlers[(int) PSImode].insn_code = CODE_FOR_sqrtpsi2;
4748: #endif
4749: #ifdef HAVE_sqrtsi2
4750: if (HAVE_sqrtsi2)
4751: sqrt_optab->handlers[(int) SImode].insn_code = CODE_FOR_sqrtsi2;
4752: #endif
4753: #ifdef HAVE_sqrtdi2
4754: if (HAVE_sqrtdi2)
4755: sqrt_optab->handlers[(int) DImode].insn_code = CODE_FOR_sqrtdi2;
4756: #endif
4757: #ifdef HAVE_sqrtti2
4758: if (HAVE_sqrtti2)
4759: sqrt_optab->handlers[(int) TImode].insn_code = CODE_FOR_sqrtti2;
4760: #endif
4761: #ifdef HAVE_sqrtsf2
4762: if (HAVE_sqrtsf2)
4763: sqrt_optab->handlers[(int) SFmode].insn_code = CODE_FOR_sqrtsf2;
4764: #endif
4765: #ifdef HAVE_sqrtdf2
4766: if (HAVE_sqrtdf2)
4767: sqrt_optab->handlers[(int) DFmode].insn_code = CODE_FOR_sqrtdf2;
4768: #endif
4769: #ifdef HAVE_sqrttf2
4770: if (HAVE_sqrttf2)
4771: sqrt_optab->handlers[(int) TFmode].insn_code = CODE_FOR_sqrttf2;
4772: #endif
4773: /* No library calls here! If there is no sqrt instruction expand_builtin
4774: should force the library call. */
4775:
1.1.1.4 ! root 4776: #ifdef HAVE_sinsf2
! 4777: if (HAVE_sinsf2)
! 4778: sin_optab->handlers[(int) SFmode].insn_code = CODE_FOR_sinsf2;
! 4779: #endif
! 4780: #ifdef HAVE_sindf2
! 4781: if (HAVE_sindf2)
! 4782: sin_optab->handlers[(int) DFmode].insn_code = CODE_FOR_sindf2;
! 4783: #endif
! 4784: #ifdef HAVE_sintf2
! 4785: if (HAVE_sintf2)
! 4786: sin_optab->handlers[(int) TFmode].insn_code = CODE_FOR_sintf2;
! 4787: #endif
! 4788: /* No library calls here! If there is no sin instruction expand_builtin
! 4789: should force the library call. */
! 4790:
! 4791: #ifdef HAVE_cossf2
! 4792: if (HAVE_cossf2)
! 4793: cos_optab->handlers[(int) SFmode].insn_code = CODE_FOR_cossf2;
! 4794: #endif
! 4795: #ifdef HAVE_cosdf2
! 4796: if (HAVE_cosdf2)
! 4797: cos_optab->handlers[(int) DFmode].insn_code = CODE_FOR_cosdf2;
! 4798: #endif
! 4799: #ifdef HAVE_costf2
! 4800: if (HAVE_costf2)
! 4801: cos_optab->handlers[(int) TFmode].insn_code = CODE_FOR_costf2;
! 4802: #endif
! 4803: /* No library calls here! If there is no cos instruction expand_builtin
! 4804: should force the library call. */
! 4805:
1.1.1.3 root 4806: #ifdef HAVE_strlenqi
4807: if (HAVE_strlenqi)
4808: strlen_optab->handlers[(int) QImode].insn_code = CODE_FOR_strlenqi;
4809: #endif
4810: #ifdef HAVE_strlenhi
4811: if (HAVE_strlenhi)
4812: strlen_optab->handlers[(int) HImode].insn_code = CODE_FOR_strlenhi;
4813: #endif
4814: #ifdef HAVE_strlenpsi
4815: if (HAVE_strlenpsi)
4816: strlen_optab->handlers[(int) PSImode].insn_code = CODE_FOR_strlenpsi;
4817: #endif
4818: #ifdef HAVE_strlensi
4819: if (HAVE_strlensi)
4820: strlen_optab->handlers[(int) SImode].insn_code = CODE_FOR_strlensi;
4821: #endif
4822: #ifdef HAVE_strlendi
4823: if (HAVE_strlendi)
4824: strlen_optab->handlers[(int) DImode].insn_code = CODE_FOR_strlendi;
4825: #endif
4826: #ifdef HAVE_strlenti
4827: if (HAVE_strlenti)
4828: strlen_optab->handlers[(int) TImode].insn_code = CODE_FOR_strlenti;
4829: #endif
4830: /* No library calls here! If there is no strlen instruction expand_builtin
4831: should force the library call. */
4832:
1.1 root 4833: #ifdef HAVE_one_cmplqi2
4834: if (HAVE_one_cmplqi2)
4835: one_cmpl_optab->handlers[(int) QImode].insn_code = CODE_FOR_one_cmplqi2;
4836: #endif
4837: #ifdef HAVE_one_cmplhi2
4838: if (HAVE_one_cmplhi2)
4839: one_cmpl_optab->handlers[(int) HImode].insn_code = CODE_FOR_one_cmplhi2;
4840: #endif
4841: #ifdef HAVE_one_cmplpsi2
4842: if (HAVE_one_cmplpsi2)
4843: one_cmpl_optab->handlers[(int) PSImode].insn_code = CODE_FOR_one_cmplpsi2;
4844: #endif
4845: #ifdef HAVE_one_cmplsi2
4846: if (HAVE_one_cmplsi2)
4847: one_cmpl_optab->handlers[(int) SImode].insn_code = CODE_FOR_one_cmplsi2;
4848: #endif
4849: #ifdef HAVE_one_cmpldi2
4850: if (HAVE_one_cmpldi2)
4851: one_cmpl_optab->handlers[(int) DImode].insn_code = CODE_FOR_one_cmpldi2;
4852: #endif
4853: #ifdef HAVE_one_cmplti2
4854: if (HAVE_one_cmplti2)
4855: one_cmpl_optab->handlers[(int) TImode].insn_code = CODE_FOR_one_cmplti2;
4856: #endif
1.1.1.4 ! root 4857: init_integral_libfuncs (one_cmpl_optab, "one_cmpl", '2');
1.1 root 4858:
4859: #ifdef HAVE_ffsqi2
4860: if (HAVE_ffsqi2)
4861: ffs_optab->handlers[(int) QImode].insn_code = CODE_FOR_ffsqi2;
4862: #endif
4863: #ifdef HAVE_ffshi2
4864: if (HAVE_ffshi2)
4865: ffs_optab->handlers[(int) HImode].insn_code = CODE_FOR_ffshi2;
4866: #endif
4867: #ifdef HAVE_ffspsi2
4868: if (HAVE_ffspsi2)
4869: ffs_optab->handlers[(int) PSImode].insn_code = CODE_FOR_ffspsi2;
4870: #endif
4871: #ifdef HAVE_ffssi2
4872: if (HAVE_ffssi2)
4873: ffs_optab->handlers[(int) SImode].insn_code = CODE_FOR_ffssi2;
4874: #endif
4875: #ifdef HAVE_ffsdi2
4876: if (HAVE_ffsdi2)
4877: ffs_optab->handlers[(int) DImode].insn_code = CODE_FOR_ffsdi2;
4878: #endif
4879: #ifdef HAVE_ffsti2
4880: if (HAVE_ffsti2)
4881: ffs_optab->handlers[(int) TImode].insn_code = CODE_FOR_ffsti2;
4882: #endif
1.1.1.4 ! root 4883: init_integral_libfuncs (ffs_optab, "ffs", '2');
1.1 root 4884:
4885: #ifdef HAVE_movqi
4886: if (HAVE_movqi)
4887: mov_optab->handlers[(int) QImode].insn_code = CODE_FOR_movqi;
4888: #endif
4889: #ifdef HAVE_movhi
4890: if (HAVE_movhi)
4891: mov_optab->handlers[(int) HImode].insn_code = CODE_FOR_movhi;
4892: #endif
4893: #ifdef HAVE_movpsi
4894: if (HAVE_movpsi)
4895: mov_optab->handlers[(int) PSImode].insn_code = CODE_FOR_movpsi;
4896: #endif
4897: #ifdef HAVE_movsi
4898: if (HAVE_movsi)
4899: mov_optab->handlers[(int) SImode].insn_code = CODE_FOR_movsi;
4900: #endif
4901: #ifdef HAVE_movdi
4902: if (HAVE_movdi)
4903: mov_optab->handlers[(int) DImode].insn_code = CODE_FOR_movdi;
4904: #endif
4905: #ifdef HAVE_movti
4906: if (HAVE_movti)
4907: mov_optab->handlers[(int) TImode].insn_code = CODE_FOR_movti;
4908: #endif
4909: #ifdef HAVE_movsf
4910: if (HAVE_movsf)
4911: mov_optab->handlers[(int) SFmode].insn_code = CODE_FOR_movsf;
4912: #endif
4913: #ifdef HAVE_movdf
4914: if (HAVE_movdf)
4915: mov_optab->handlers[(int) DFmode].insn_code = CODE_FOR_movdf;
4916: #endif
1.1.1.4 ! root 4917: #ifdef HAVE_movxf
! 4918: if (HAVE_movxf)
! 4919: mov_optab->handlers[(int) XFmode].insn_code = CODE_FOR_movxf;
! 4920: #endif
1.1 root 4921: #ifdef HAVE_movtf
4922: if (HAVE_movtf)
4923: mov_optab->handlers[(int) TFmode].insn_code = CODE_FOR_movtf;
4924: #endif
4925: #ifdef HAVE_movcc
4926: if (HAVE_movcc)
4927: mov_optab->handlers[(int) CCmode].insn_code = CODE_FOR_movcc;
4928: #endif
4929:
4930: #ifdef EXTRA_CC_MODES
4931: init_mov_optab ();
4932: #endif
4933:
4934: #ifdef HAVE_movstrictqi
4935: if (HAVE_movstrictqi)
4936: movstrict_optab->handlers[(int) QImode].insn_code = CODE_FOR_movstrictqi;
4937: #endif
4938: #ifdef HAVE_movstricthi
4939: if (HAVE_movstricthi)
4940: movstrict_optab->handlers[(int) HImode].insn_code = CODE_FOR_movstricthi;
4941: #endif
4942: #ifdef HAVE_movstrictpsi
4943: if (HAVE_movstrictpsi)
4944: movstrict_optab->handlers[(int) PSImode].insn_code = CODE_FOR_movstrictpsi;
4945: #endif
4946: #ifdef HAVE_movstrictsi
4947: if (HAVE_movstrictsi)
4948: movstrict_optab->handlers[(int) SImode].insn_code = CODE_FOR_movstrictsi;
4949: #endif
4950: #ifdef HAVE_movstrictdi
4951: if (HAVE_movstrictdi)
4952: movstrict_optab->handlers[(int) DImode].insn_code = CODE_FOR_movstrictdi;
4953: #endif
4954: #ifdef HAVE_movstrictti
4955: if (HAVE_movstrictti)
4956: movstrict_optab->handlers[(int) TImode].insn_code = CODE_FOR_movstrictti;
4957: #endif
4958:
4959: #ifdef HAVE_cmpqi
4960: if (HAVE_cmpqi)
4961: cmp_optab->handlers[(int) QImode].insn_code = CODE_FOR_cmpqi;
4962: #endif
4963: #ifdef HAVE_cmphi
4964: if (HAVE_cmphi)
4965: cmp_optab->handlers[(int) HImode].insn_code = CODE_FOR_cmphi;
4966: #endif
4967: #ifdef HAVE_cmppsi
4968: if (HAVE_cmppsi)
4969: cmp_optab->handlers[(int) PSImode].insn_code = CODE_FOR_cmppsi;
4970: #endif
4971: #ifdef HAVE_cmpsi
4972: if (HAVE_cmpsi)
4973: cmp_optab->handlers[(int) SImode].insn_code = CODE_FOR_cmpsi;
4974: #endif
4975: #ifdef HAVE_cmpdi
4976: if (HAVE_cmpdi)
4977: cmp_optab->handlers[(int) DImode].insn_code = CODE_FOR_cmpdi;
4978: #endif
4979: #ifdef HAVE_cmpti
4980: if (HAVE_cmpti)
4981: cmp_optab->handlers[(int) TImode].insn_code = CODE_FOR_cmpti;
4982: #endif
4983: #ifdef HAVE_cmpsf
4984: if (HAVE_cmpsf)
4985: cmp_optab->handlers[(int) SFmode].insn_code = CODE_FOR_cmpsf;
4986: #endif
4987: #ifdef HAVE_cmpdf
4988: if (HAVE_cmpdf)
4989: cmp_optab->handlers[(int) DFmode].insn_code = CODE_FOR_cmpdf;
4990: #endif
1.1.1.4 ! root 4991: #ifdef HAVE_cmpxf
! 4992: if (HAVE_cmpxf)
! 4993: cmp_optab->handlers[(int) XFmode].insn_code = CODE_FOR_cmpxf;
! 4994: #endif
1.1 root 4995: #ifdef HAVE_cmptf
4996: if (HAVE_cmptf)
4997: cmp_optab->handlers[(int) TFmode].insn_code = CODE_FOR_cmptf;
4998: #endif
1.1.1.4 ! root 4999: /* Comparison libcalls for integers MUST come in pairs, signed/unsigned. */
! 5000: init_integral_libfuncs (cmp_optab, "cmp", '2');
! 5001: init_integral_libfuncs (ucmp_optab, "ucmp", '2');
! 5002: init_floating_libfuncs (cmp_optab, "cmp", '2');
! 5003:
1.1 root 5004: #ifdef HAVE_tstqi
5005: if (HAVE_tstqi)
5006: tst_optab->handlers[(int) QImode].insn_code = CODE_FOR_tstqi;
5007: #endif
5008: #ifdef HAVE_tsthi
5009: if (HAVE_tsthi)
5010: tst_optab->handlers[(int) HImode].insn_code = CODE_FOR_tsthi;
5011: #endif
5012: #ifdef HAVE_tstpsi
5013: if (HAVE_tstpsi)
5014: tst_optab->handlers[(int) PSImode].insn_code = CODE_FOR_tstpsi;
5015: #endif
5016: #ifdef HAVE_tstsi
5017: if (HAVE_tstsi)
5018: tst_optab->handlers[(int) SImode].insn_code = CODE_FOR_tstsi;
5019: #endif
5020: #ifdef HAVE_tstdi
5021: if (HAVE_tstdi)
5022: tst_optab->handlers[(int) DImode].insn_code = CODE_FOR_tstdi;
5023: #endif
5024: #ifdef HAVE_tstti
5025: if (HAVE_tstti)
5026: tst_optab->handlers[(int) TImode].insn_code = CODE_FOR_tstti;
5027: #endif
5028: #ifdef HAVE_tstsf
5029: if (HAVE_tstsf)
5030: tst_optab->handlers[(int) SFmode].insn_code = CODE_FOR_tstsf;
5031: #endif
5032: #ifdef HAVE_tstdf
5033: if (HAVE_tstdf)
5034: tst_optab->handlers[(int) DFmode].insn_code = CODE_FOR_tstdf;
5035: #endif
1.1.1.4 ! root 5036: #ifdef HAVE_tstxf
! 5037: if (HAVE_tstxf)
! 5038: tst_optab->handlers[(int) XFmode].insn_code = CODE_FOR_tstxf;
! 5039: #endif
1.1 root 5040: #ifdef HAVE_tsttf
5041: if (HAVE_tsttf)
5042: tst_optab->handlers[(int) TFmode].insn_code = CODE_FOR_tsttf;
5043: #endif
5044:
5045: #ifdef HAVE_beq
5046: if (HAVE_beq)
5047: bcc_gen_fctn[(int) EQ] = gen_beq;
5048: #endif
5049: #ifdef HAVE_bne
5050: if (HAVE_bne)
5051: bcc_gen_fctn[(int) NE] = gen_bne;
5052: #endif
5053: #ifdef HAVE_bgt
5054: if (HAVE_bgt)
5055: bcc_gen_fctn[(int) GT] = gen_bgt;
5056: #endif
5057: #ifdef HAVE_bge
5058: if (HAVE_bge)
5059: bcc_gen_fctn[(int) GE] = gen_bge;
5060: #endif
5061: #ifdef HAVE_bgtu
5062: if (HAVE_bgtu)
5063: bcc_gen_fctn[(int) GTU] = gen_bgtu;
5064: #endif
5065: #ifdef HAVE_bgeu
5066: if (HAVE_bgeu)
5067: bcc_gen_fctn[(int) GEU] = gen_bgeu;
5068: #endif
5069: #ifdef HAVE_blt
5070: if (HAVE_blt)
5071: bcc_gen_fctn[(int) LT] = gen_blt;
5072: #endif
5073: #ifdef HAVE_ble
5074: if (HAVE_ble)
5075: bcc_gen_fctn[(int) LE] = gen_ble;
5076: #endif
5077: #ifdef HAVE_bltu
5078: if (HAVE_bltu)
5079: bcc_gen_fctn[(int) LTU] = gen_bltu;
5080: #endif
5081: #ifdef HAVE_bleu
5082: if (HAVE_bleu)
5083: bcc_gen_fctn[(int) LEU] = gen_bleu;
5084: #endif
5085:
5086: for (i = 0; i < NUM_RTX_CODE; i++)
5087: setcc_gen_code[i] = CODE_FOR_nothing;
5088:
5089: #ifdef HAVE_seq
5090: if (HAVE_seq)
5091: setcc_gen_code[(int) EQ] = CODE_FOR_seq;
5092: #endif
5093: #ifdef HAVE_sne
5094: if (HAVE_sne)
5095: setcc_gen_code[(int) NE] = CODE_FOR_sne;
5096: #endif
5097: #ifdef HAVE_sgt
5098: if (HAVE_sgt)
5099: setcc_gen_code[(int) GT] = CODE_FOR_sgt;
5100: #endif
5101: #ifdef HAVE_sge
5102: if (HAVE_sge)
5103: setcc_gen_code[(int) GE] = CODE_FOR_sge;
5104: #endif
5105: #ifdef HAVE_sgtu
5106: if (HAVE_sgtu)
5107: setcc_gen_code[(int) GTU] = CODE_FOR_sgtu;
5108: #endif
5109: #ifdef HAVE_sgeu
5110: if (HAVE_sgeu)
5111: setcc_gen_code[(int) GEU] = CODE_FOR_sgeu;
5112: #endif
5113: #ifdef HAVE_slt
5114: if (HAVE_slt)
5115: setcc_gen_code[(int) LT] = CODE_FOR_slt;
5116: #endif
5117: #ifdef HAVE_sle
5118: if (HAVE_sle)
5119: setcc_gen_code[(int) LE] = CODE_FOR_sle;
5120: #endif
5121: #ifdef HAVE_sltu
5122: if (HAVE_sltu)
5123: setcc_gen_code[(int) LTU] = CODE_FOR_sltu;
5124: #endif
5125: #ifdef HAVE_sleu
5126: if (HAVE_sleu)
5127: setcc_gen_code[(int) LEU] = CODE_FOR_sleu;
5128: #endif
5129:
5130: extendsfdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extendsfdf2");
1.1.1.4 ! root 5131: extendsfxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extendsfxf2");
! 5132: extendsftf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extendsftf2");
! 5133: extenddfxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extenddfxf2");
! 5134: extenddftf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extenddftf2");
! 5135:
1.1 root 5136: truncdfsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__truncdfsf2");
1.1.1.4 ! root 5137: truncxfsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__truncxfsf2");
! 5138: trunctfsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__trunctfsf2");
! 5139: truncxfdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__truncxfdf2");
! 5140: trunctfdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__trunctfdf2");
! 5141:
1.1 root 5142: memcpy_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memcpy");
5143: bcopy_libfunc = gen_rtx (SYMBOL_REF, Pmode, "bcopy");
5144: memcmp_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memcmp");
1.1.1.4 ! root 5145: bcmp_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gcc_bcmp");
1.1 root 5146: memset_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memset");
5147: bzero_libfunc = gen_rtx (SYMBOL_REF, Pmode, "bzero");
1.1.1.4 ! root 5148:
1.1 root 5149: eqsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqsf2");
5150: nesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nesf2");
5151: gtsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gtsf2");
5152: gesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gesf2");
5153: ltsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ltsf2");
5154: lesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__lesf2");
1.1.1.4 ! root 5155:
1.1 root 5156: eqdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqdf2");
5157: nedf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nedf2");
5158: gtdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gtdf2");
5159: gedf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gedf2");
5160: ltdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ltdf2");
5161: ledf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ledf2");
1.1.1.4 ! root 5162:
! 5163: eqxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqxf2");
! 5164: nexf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nexf2");
! 5165: gtxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gtxf2");
! 5166: gexf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gexf2");
! 5167: ltxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ltxf2");
! 5168: lexf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__lexf2");
! 5169:
! 5170: eqtf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqtf2");
! 5171: netf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__netf2");
! 5172: gttf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gttf2");
! 5173: getf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__getf2");
! 5174: lttf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__lttf2");
! 5175: letf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__letf2");
! 5176:
1.1 root 5177: floatsisf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsisf");
1.1.1.4 ! root 5178: floatdisf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatdisf");
! 5179: floattisf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floattisf");
! 5180:
1.1 root 5181: floatsidf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsidf");
1.1.1.4 ! root 5182: floatdidf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatdidf");
! 5183: floattidf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floattidf");
! 5184:
! 5185: floatsixf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsixf");
! 5186: floatdixf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatdixf");
! 5187: floattixf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floattixf");
! 5188:
! 5189: floatsitf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsitf");
! 5190: floatditf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatditf");
! 5191: floattitf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floattitf");
! 5192:
1.1 root 5193: fixsfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixsfsi");
5194: fixsfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixsfdi");
1.1.1.4 ! root 5195: fixsfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixsfti");
! 5196:
1.1 root 5197: fixdfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixdfsi");
5198: fixdfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixdfdi");
1.1.1.4 ! root 5199: fixdfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixdfti");
! 5200:
! 5201: fixxfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixxfsi");
! 5202: fixxfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixxfdi");
! 5203: fixxfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixxfti");
! 5204:
! 5205: fixtfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixtfsi");
! 5206: fixtfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixtfdi");
! 5207: fixtfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixtfti");
! 5208:
1.1 root 5209: fixunssfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunssfsi");
5210: fixunssfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunssfdi");
1.1.1.4 ! root 5211: fixunssfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunssfti");
! 5212:
1.1 root 5213: fixunsdfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsdfsi");
5214: fixunsdfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsdfdi");
1.1.1.4 ! root 5215: fixunsdfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsdfti");
! 5216:
! 5217: fixunsxfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsxfsi");
! 5218: fixunsxfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsxfdi");
! 5219: fixunsxfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsxfti");
! 5220:
! 5221: fixunstfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunstfsi");
! 5222: fixunstfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunstfdi");
! 5223: fixunstfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunstfti");
1.1 root 5224: }
1.1.1.2 root 5225:
5226: #ifdef BROKEN_LDEXP
5227:
5228: /* SCO 3.2 apparently has a broken ldexp. */
5229:
5230: double
5231: ldexp(x,n)
5232: double x;
5233: int n;
5234: {
5235: if (n > 0)
5236: while (n--)
5237: x *= 2;
5238:
5239: return x;
5240: }
5241: #endif /* BROKEN_LDEXP */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.