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