|
|
1.1 root 1: /* Subroutines for insn-output.c for Pyramid 90x, 9000, and MIServer Series.
2: Copyright (C) 1989, 1991 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
1.1.1.2 ! root 18: the Free Software Foundation, 59 Temple Place - Suite 330,
! 19: Boston, MA 02111-1307, USA. */
1.1 root 20:
21: /* Some output-actions in pyr.md need these. */
22: #include <stdio.h>
23: #include "config.h"
24: #include "rtl.h"
25: #include "regs.h"
26: #include "hard-reg-set.h"
27: #include "real.h"
28: #include "insn-config.h"
29: #include "conditions.h"
30: #include "insn-flags.h"
31: #include "output.h"
32: #include "insn-attr.h"
33: #include "tree.h"
34:
35: /*
36: * Do FUNCTION_ARG.
37: * This cannot be defined as a macro on pyramids, because Pyramid Technology's
38: * C compiler dies on (several equivalent definitions of) this macro.
39: * The only way around this cc bug was to make this a function.
40: * While it would be possible to use a macro version for gcc, it seems
41: * more reliable to have a single version of the code.
42: */
43: void *
44: pyr_function_arg(cum, mode, type, named)
45: CUMULATIVE_ARGS cum;
46: enum machine_mode mode;
47: tree type;
48: {
49: return (void *)(FUNCTION_ARG_HELPER (cum, mode,type,named));
50: }
51:
52: /* Do the hard part of PARAM_SAFE_FOR_REG_P.
53: * This cannot be defined as a macro on pyramids, because Pyramid Technology's
54: * C compiler dies on (several equivalent definitions of) this macro.
55: * The only way around this cc bug was to make this a function.
56: */
57: int
58: inner_param_safe_helper (type)
59: tree type;
60: {
61: return (INNER_PARAM_SAFE_HELPER(type));
62: }
63:
64:
65: /* Return 1 if OP is a non-indexed operand of mode MODE.
66: This is either a register reference, a memory reference,
67: or a constant. In the case of a memory reference, the address
68: is checked to make sure it isn't indexed.
69:
70: Register and memory references must have mode MODE in order to be valid,
71: but some constants have no machine mode and are valid for any mode.
72:
73: If MODE is VOIDmode, OP is checked for validity for whatever mode
74: it has.
75:
76: The main use of this function is as a predicate in match_operand
77: expressions in the machine description.
78:
79: It is useful to compare this with general_operand(). They should
80: be identical except for one line.
81:
82: This function seems necessary because of the non-orthogonality of
83: Pyramid insns.
84: For any 2-operand insn, and any combination of operand modes,
85: if indexing is valid for the isn's second operand, it is invalid
86: for the first operand to be indexed. */
87:
88: extern int volatile_ok;
89:
90: int
91: nonindexed_operand (op, mode)
92: register rtx op;
93: enum machine_mode mode;
94: {
95: register RTX_CODE code = GET_CODE (op);
96: int mode_altering_drug = 0;
97:
98: if (mode == VOIDmode)
99: mode = GET_MODE (op);
100:
101: /* Don't accept CONST_INT or anything similar
102: if the caller wants something floating. */
103: if (GET_MODE (op) == VOIDmode && mode != VOIDmode
104: && GET_MODE_CLASS (mode) != MODE_INT)
105: return 0;
106:
107: if (CONSTANT_P (op))
108: return ((GET_MODE (op) == VOIDmode || GET_MODE (op) == mode)
109: && LEGITIMATE_CONSTANT_P (op));
110:
111: /* Except for certain constants with VOIDmode, already checked for,
112: OP's mode must match MODE if MODE specifies a mode. */
113:
114: if (GET_MODE (op) != mode)
115: return 0;
116:
117: while (code == SUBREG)
118: {
119: op = SUBREG_REG (op);
120: code = GET_CODE (op);
121: #if 0
122: /* No longer needed, since (SUBREG (MEM...))
123: will load the MEM into a reload reg in the MEM's own mode. */
124: mode_altering_drug = 1;
125: #endif
126: }
127: if (code == REG)
128: return 1;
129: if (code == CONST_DOUBLE)
130: return LEGITIMATE_CONSTANT_P (op);
131: if (code == MEM)
132: {
133: register rtx y = XEXP (op, 0);
134: if (! volatile_ok && MEM_VOLATILE_P (op))
135: return 0;
136: GO_IF_NONINDEXED_ADDRESS (y, win);
137: }
138: return 0;
139:
140: win:
141: if (mode_altering_drug)
142: return ! mode_dependent_address_p (XEXP (op, 0));
143: return 1;
144: }
145:
146: /* Return non-zero if the rtx OP has an immediate component. An
147: immediate component or additive term equal to zero is rejected
148: due to assembler problems. */
149:
150: int
151: has_direct_base (op)
152: rtx op;
153: {
154: if ((CONSTANT_ADDRESS_P (op)
155: && op != const0_rtx)
156: || (GET_CODE (op) == PLUS
157: && ((CONSTANT_ADDRESS_P (XEXP (op, 1))
158: && XEXP (op, 1) != const0_rtx)
159: || (CONSTANT_ADDRESS_P (XEXP (op, 0))
160: && XEXP (op, 0) != const0_rtx))))
161: return 1;
162:
163: return 0;
164: }
165:
166: /* Return zero if the rtx OP has a (scaled) index. */
167:
168: int
169: has_index (op)
170: rtx op;
171: {
172: if (GET_CODE (op) == PLUS
173: && (GET_CODE (XEXP (op, 0)) == MULT
174: || (GET_CODE (XEXP (op, 1)) == MULT)))
175: return 1;
176: else
177: return 0;
178: }
179:
180: int swap_operands;
181:
182: /* weird_memory_memory -- return 1 if OP1 and OP2 can be compared (or
183: exchanged with xchw) with one instruction. If the operands need to
184: be swapped, set the global variable SWAP_OPERANDS. This function
185: silently assumes that both OP0 and OP1 are valid memory references.
186: */
187:
188: int
189: weird_memory_memory (op0, op1)
190: rtx op0, op1;
191: {
192: RTX_CODE code0, code1;
193:
194: op0 = XEXP (op0, 0);
195: op1 = XEXP (op1, 0);
196: code0 = GET_CODE (op0);
197: code1 = GET_CODE (op1);
198:
199: swap_operands = 0;
200:
201: if (code1 == REG || code1 == SUBREG)
202: {
203: return 1;
204: }
205: if (code0 == REG || code0 == SUBREG)
206: {
207: swap_operands = 1;
208: return 1;
209: }
210: if (has_direct_base (op0) && has_direct_base (op1))
211: {
212: if (has_index (op1))
213: {
214: if (has_index (op0))
215: return 0;
216: swap_operands = 1;
217: }
218:
219: return 1;
220: }
221: return 0;
222: }
223:
224: int
225: signed_comparison (x, mode)
226: rtx x;
227: enum machine_mode mode;
228: {
229: return ! TRULY_UNSIGNED_COMPARE_P (GET_CODE (x));
230: }
231:
232: extern rtx force_reg ();
233: rtx test_op0, test_op1;
234: enum machine_mode test_mode;
235:
236: /* Sign-extend or zero-extend constant X from FROM_MODE to TO_MODE. */
237:
238: rtx
239: extend_const (x, extop, from_mode, to_mode)
240: rtx x;
241: RTX_CODE extop;
242: enum machine_mode from_mode, to_mode;
243: {
244: int val;
245: int negative;
246: if (from_mode == to_mode)
247: return x;
248: if (GET_CODE (x) != CONST_INT)
249: abort ();
250: val = INTVAL (x);
251: negative = val & (1 << (GET_MODE_BITSIZE (from_mode) - 1));
252: if (GET_MODE_BITSIZE (from_mode) == HOST_BITS_PER_INT)
253: abort ();
254: if (negative && extop == SIGN_EXTEND)
255: val = val | ((-1) << (GET_MODE_BITSIZE (from_mode)));
256: else
257: val = val & ~((-1) << (GET_MODE_BITSIZE (from_mode)));
258: if (GET_MODE_BITSIZE (to_mode) == HOST_BITS_PER_INT)
259: return gen_rtx (CONST_INT, VOIDmode, val);
260: return gen_rtx (CONST_INT, VOIDmode,
261: val & ~((-1) << (GET_MODE_BITSIZE (to_mode))));
262: }
263:
264: rtx
265: ensure_extended (op, extop, from_mode)
266: rtx op;
267: RTX_CODE extop;
268: enum machine_mode from_mode;
269: {
270: if (GET_CODE (op) == CONST_INT)
271: return extend_const (op, extop, from_mode, SImode);
272: else
273: return force_reg (SImode, gen_rtx (extop, SImode, op));
274: }
275:
276: /* Emit rtl for a branch, as well as any delayed (integer) compare insns.
277: The compare insn to perform is determined by the global variables
278: test_op0 and test_op1. */
279:
280: void
281: extend_and_branch (extop)
282: RTX_CODE extop;
283: {
284: rtx op0, op1;
285: RTX_CODE code0, code1;
286:
287: op0 = test_op0, op1 = test_op1;
288: if (op0 == 0)
289: return;
290:
291: code0 = GET_CODE (op0);
292: if (op1 != 0)
293: code1 = GET_CODE (op1);
294: test_op0 = test_op1 = 0;
295:
296: if (op1 == 0)
297: {
298: op0 = ensure_extended (op0, extop, test_mode);
299: emit_insn (gen_rtx (SET, VOIDmode, cc0_rtx, op0));
300: }
301: else
302: {
303: if (CONSTANT_P (op0) && CONSTANT_P (op1))
304: {
305: op0 = ensure_extended (op0, extop, test_mode);
306: op1 = ensure_extended (op1, extop, test_mode);
307: }
308: else if (extop == ZERO_EXTEND && test_mode == HImode)
309: {
310: /* Pyramids have no unsigned "cmphi" instructions. We need to
311: zero extend unsigned halfwords into temporary registers. */
312: op0 = ensure_extended (op0, extop, test_mode);
313: op1 = ensure_extended (op1, extop, test_mode);
314: }
315: else if (CONSTANT_P (op0))
316: {
317: op0 = ensure_extended (op0, extop, test_mode);
318: op1 = ensure_extended (op1, extop, test_mode);
319: }
320: else if (CONSTANT_P (op1))
321: {
322: op1 = ensure_extended (op1, extop, test_mode);
323: op0 = ensure_extended (op0, extop, test_mode);
324: }
325: else if ((code0 == REG || code0 == SUBREG)
326: && (code1 == REG || code1 == SUBREG))
327: {
328: /* I could do this case without extension, by using the virtual
329: register address (but that would lose for global regs). */
330: op0 = ensure_extended (op0, extop, test_mode);
331: op1 = ensure_extended (op1, extop, test_mode);
332: }
333: else if (code0 == MEM && code1 == MEM)
334: {
335: /* Load into a reg if the address combination can't be handled
336: directly. */
337: if (! weird_memory_memory (op0, op1))
338: op0 = force_reg (test_mode, op0);
339: }
340:
341: emit_insn (gen_rtx (SET, VOIDmode, cc0_rtx,
342: gen_rtx (COMPARE, VOIDmode, op0, op1)));
343: }
344: }
345:
346: /* Return non-zero if the two single-word moves with operands[0]
347: and operands[1] for the first single-word move, and operands[2]
348: and operands[3] for the second single-word move, is possible to
349: combine to a double word move.
350:
351: The criterion is whether the operands are in consecutive memory cells,
352: registers, etc. */
353:
354: int
355: movdi_possible (operands)
356: rtx operands[];
357: {
358: int cnst_diff0, cnst_diff1;
359: RTX_CODE code0 = GET_CODE (operands[0]);
360: RTX_CODE code1 = GET_CODE (operands[1]);
361:
362: /* Don't dare to combine (possibly overlapping) memory -> memory moves. */
363: /* It would be possible to detect the cases where we dare, by using
364: constant_diff (operands[0], operands[1])!!! */
365: if (code0 == MEM && code1 == MEM)
366: return 0;
367:
368: cnst_diff0 = consecutive_operands (operands[0], operands[2]);
369: if (cnst_diff0 == 0)
370: return 0;
371:
372: cnst_diff1 = consecutive_operands (operands[1], operands[3]);
373: if (cnst_diff1 == 0)
374: return 0;
375:
376: if (cnst_diff0 & cnst_diff1)
377: {
378: /* The source and destination operands are consecutive. */
379:
380: /* If the first move writes into the source of the second move,
381: we cannot combine. */
382: if ((code0 == REG
383: && reg_overlap_mentioned_p (operands[0], operands[3]))
384: || (code0 == SUBREG
385: && subreg_overlap_mentioned_p (operands[0], operands[3])))
386: return 0;
387:
388: if (cnst_diff0 & 1)
389: /* operands[0],[1] has higher addresses than operands[2],[3]. */
390: swap_operands = 0;
391: else
392: /* operands[0],[1] has lower addresses than operands[2],[3]. */
393: swap_operands = 1;
394: return 1;
395: }
396: return 0;
397: }
398:
399: /* Like reg_overlap_mentioned_p, but accepts a subreg rtx instead
400: of a reg. */
401:
402: int
403: subreg_overlap_mentioned_p (subreg, x)
404: rtx subreg, x;
405: {
406: rtx reg = SUBREG_REG (subreg);
407: int regno = REGNO (reg) + SUBREG_WORD (subreg);
408: int endregno = regno + HARD_REGNO_NREGS (regno, GET_MODE (subreg));
409: return refers_to_regno_p (regno, endregno, x, 0);
410: }
411:
412: /* Return 1 if OP0 is a consecutive operand to OP1, 2 if OP1 is a
413: consecutive operand to OP0.
414:
415: This function is used to determine if addresses are consecutive,
416: and therefore possible to combine to fewer instructions. */
417:
418: int
419: consecutive_operands (op0, op1)
420: rtx op0, op1;
421: {
422: RTX_CODE code0, code1;
423: int cnst_diff;
424: int regno_off0, regno_off1;
425:
426: code0 = GET_CODE (op0);
427: code1 = GET_CODE (op1);
428:
429: regno_off0 = 0;
430: if (code0 == SUBREG)
431: {
432: if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0))) <= UNITS_PER_WORD)
433: return 0;
434: regno_off0 = SUBREG_WORD (op0);
435: op0 = SUBREG_REG (op0);
436: code0 = REG;
437: }
438:
439: regno_off1 = 0;
440: if (code1 == SUBREG)
441: {
442: if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (op1))) <= UNITS_PER_WORD)
443: return 0;
444: regno_off1 = SUBREG_WORD (op1);
445: op1 = SUBREG_REG (op1);
446: code1 = REG;
447: }
448:
449: if (code0 != code1)
450: return 0;
451:
452: switch (code0)
453: {
454: case CONST_INT:
455: /* Cannot permit any symbolic constants, even if the consecutive
456: operand is 0, since a movl really performs sign extension. */
457: if (code1 != CONST_INT)
458: return 0;
459: if ((INTVAL (op0) == 0 && INTVAL (op1) == 0)
460: || (INTVAL (op0) == -1 && INTVAL (op1) == -1))
461: return 3;
462: if ((INTVAL (op0) == 0 && INTVAL (op1) > 0)
463: || (INTVAL (op0) == -1 && INTVAL (op1) < 0))
464: return 2;
465: if ((INTVAL (op1) == 0 && INTVAL (op0) > 0)
466: || (INTVAL (op1) == -1 && INTVAL (op0) < 0))
467: return 1;
468: break;
469:
470: case REG:
471: regno_off0 = REGNO (op0) + regno_off0;
472: regno_off1 = REGNO (op1) + regno_off1;
473:
474: cnst_diff = regno_off0 - regno_off1;
475: if (cnst_diff == 1)
476: {
477: /* movl with the highest numbered parameter (local) register as
478: source or destination, doesn't wrap to the lowest numbered local
479: (temporary) register. */
480:
481: if (regno_off0 % 16 != 0)
482: return 1;
483: else
484: return 0;
485: }
486: else if (cnst_diff == -1)
487: {
488: if (regno_off1 % 16 != 0)
489: return 2;
490: else
491: return 0;
492: }
493: break;
494:
495: case MEM:
496: op0 = XEXP (op0, 0);
497: op1 = XEXP (op1, 0);
498: if (GET_CODE (op0) == CONST)
499: op0 = XEXP (op0, 0);
500: if (GET_CODE (op1) == CONST)
501: op1 = XEXP (op1, 0);
502:
503: cnst_diff = constant_diff (op0, op1);
504: if (cnst_diff)
505: {
506: if (cnst_diff == 4)
507: return 1;
508: else if (cnst_diff == -4)
509: return 2;
510: }
511: break;
512: }
513: return 0;
514: }
515:
516: /* Return the constant difference of the rtx expressions OP0 and OP1,
517: or 0 if they don't have a constant difference.
518:
519: This function is used to determine if addresses are consecutive,
520: and therefore possible to combine to fewer instructions. */
521:
522: int
523: constant_diff (op0, op1)
524: rtx op0, op1;
525: {
526: RTX_CODE code0, code1;
527: int cnst_diff;
528:
529: code0 = GET_CODE (op0);
530: code1 = GET_CODE (op1);
531:
532: if (code0 != code1)
533: {
534: if (code0 == PLUS)
535: {
536: if (GET_CODE (XEXP (op0, 1)) == CONST_INT
537: && rtx_equal_p (op1, XEXP (op0, 0)))
538: return INTVAL (XEXP (op0, 1));
539: }
540: else if (code1 == PLUS)
541: {
542: if (GET_CODE (XEXP (op1, 1)) == CONST_INT
543: && rtx_equal_p (op0, XEXP (op1, 0)))
544: return -INTVAL (XEXP (op1, 1));
545: }
546: return 0;
547: }
548:
549: if (code0 == CONST_INT)
550: return INTVAL (op0) - INTVAL (op1);
551:
552: if (code0 == PLUS)
553: {
554: cnst_diff = constant_diff (XEXP (op0, 0), XEXP (op1, 0));
555: if (cnst_diff)
556: return (rtx_equal_p (XEXP (op0, 1), XEXP (op1, 1)))
557: ? cnst_diff : 0;
558: cnst_diff = constant_diff (XEXP (op0, 1), XEXP (op1, 1));
559: if (cnst_diff)
560: return (rtx_equal_p (XEXP (op0, 0), XEXP (op1, 0)))
561: ? cnst_diff : 0;
562: }
563:
564: return 0;
565: }
566:
567: int
568: already_sign_extended (insn, from_mode, op)
569: rtx insn;
570: enum machine_mode from_mode;
571: rtx op;
572: {
573: rtx xinsn, xdest, xsrc;
574:
575: for (;;)
576: {
577: insn = PREV_INSN (insn);
578: if (insn == 0)
579: return 0;
580: if (GET_CODE (insn) == NOTE || GET_CODE (insn) == JUMP_INSN)
581: continue;
582: if (GET_CODE (insn) == CALL_INSN && ! call_used_regs[REGNO (op)])
583: continue;
584: if (GET_CODE (insn) != INSN)
585: return 0;
586: xinsn = PATTERN (insn);
587:
588: if (GET_CODE (xinsn) != SET)
589: return 0;
590:
591: xdest = SET_DEST (xinsn);
592: xsrc = SET_SRC (xinsn);
593:
594: if (GET_CODE (xdest) == SUBREG)
595: abort ();
596:
597: if ( ! REG_P (xdest))
598: continue;
599:
600: if (REGNO (op) == REGNO (xdest)
601: && ((GET_CODE (xsrc) == SIGN_EXTEND
602: && GET_MODE (XEXP (xsrc, 0)) == from_mode)
603: || (GET_CODE (xsrc) == MEM
604: && GET_MODE (xsrc) == from_mode)))
605: return 1;
606:
607: /* The register is modified by another operation. */
608: if (reg_overlap_mentioned_p (xdest, op))
609: return 0;
610: }
611: }
612:
613: char *
614: output_move_double (operands)
615: rtx *operands;
616: {
617: if (GET_CODE (operands[1]) == CONST_DOUBLE)
618: {
619: if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT)
620: {
621: /* In an integer, the low-order word is in CONST_DOUBLE_LOW. */
622: rtx const_op = operands[1];
623: if ((CONST_DOUBLE_HIGH (const_op) == 0
624: && CONST_DOUBLE_LOW (const_op) >= 0)
625: || (CONST_DOUBLE_HIGH (const_op) == -1
626: && CONST_DOUBLE_LOW (const_op) < 0))
627: {
628: operands[1] = gen_rtx (CONST_INT, VOIDmode,
629: CONST_DOUBLE_LOW (const_op));
630: return "movl %1,%0";
631: }
632: operands[1] = gen_rtx (CONST_INT, VOIDmode,
633: CONST_DOUBLE_HIGH (const_op));
634: output_asm_insn ("movw %1,%0", operands);
635: operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
636: operands[1] = gen_rtx (CONST_INT, VOIDmode,
637: CONST_DOUBLE_LOW (const_op));
638: return "movw %1,%0";
639: }
640: else
641: {
642: /* In a real, the low-address word is in CONST_DOUBLE_LOW. */
643: rtx const_op = operands[1];
644: if ((CONST_DOUBLE_LOW (const_op) == 0
645: && CONST_DOUBLE_HIGH (const_op) >= 0)
646: || (CONST_DOUBLE_LOW (const_op) == -1
647: && CONST_DOUBLE_HIGH (const_op) < 0))
648: {
649: operands[1] = gen_rtx (CONST_INT, VOIDmode,
650: CONST_DOUBLE_HIGH (const_op));
651: return "movl %1,%0";
652: }
653: operands[1] = gen_rtx (CONST_INT, VOIDmode,
654: CONST_DOUBLE_LOW (const_op));
655: output_asm_insn ("movw %1,%0", operands);
656: operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
657: operands[1] = gen_rtx (CONST_INT, VOIDmode,
658: CONST_DOUBLE_HIGH (const_op));
659: return "movw %1,%0";
660: }
661: }
662:
663: return "movl %1,%0";
664: }
665:
666: /* Output a shift insns, after having reduced integer arguments to
667: avoid as warnings. */
668:
669: char *
670: output_shift (pattern, op2, mod)
671: char *pattern;
672: rtx op2;
673: int mod;
674: {
675: if (GET_CODE (op2) == CONST_INT)
676: {
677: int cnt = INTVAL (op2) % mod;
678: if (cnt == 0)
679: {
680: cc_status = cc_prev_status;
681: return "";
682: }
683: op2 = gen_rtx (CONST_INT, VOIDmode, cnt);
684: }
685: return pattern;
686: }
687:
688: /* Return non-zero if the code of this rtx pattern is a relop. */
689:
690: int
691: relop (op, mode)
692: rtx op;
693: enum machine_mode mode;
694: {
695: switch (GET_CODE (op))
696: {
697: case EQ:
698: case NE:
699: case LT:
700: case LE:
701: case GE:
702: case GT:
703: case LTU:
704: case LEU:
705: case GEU:
706: case GTU:
707: return 1;
708: }
709: return 0;
710: }
711:
712: void
713: notice_update_cc (EXP, INSN)
714: rtx EXP, INSN;
715: {
716: switch (GET_CODE (EXP))
717: {
718: case SET:
719: switch (GET_CODE (SET_DEST (EXP)))
720: {
721: case CC0:
722: cc_status.mdep = 0;
723: cc_status.flags = 0;
724: cc_status.value1 = 0;
725: cc_status.value2 = SET_SRC (EXP);
726: break;
727:
728: case PC:
729: break;
730:
731: case REG:
732: switch (GET_CODE (SET_SRC (EXP)))
733: {
734: case CALL:
735: goto call;
736: case MEM:
737: if (GET_MODE (SET_SRC (EXP)) == QImode
738: || GET_MODE (SET_SRC (EXP)) == HImode)
739: {
740: cc_status.mdep = 0;
741: cc_status.flags = CC_NO_OVERFLOW;
742: cc_status.value1 = SET_DEST (EXP);
743: cc_status.value2 = SET_SRC (EXP);
744: break;
745: }
746: /* else: Fall through. */
747: case CONST_INT:
748: case SYMBOL_REF:
749: case LABEL_REF:
750: case CONST:
751: case CONST_DOUBLE:
752: case REG:
753: if (cc_status.value1
754: && reg_overlap_mentioned_p (SET_DEST (EXP),
755: cc_status.value1))
756: cc_status.value1 = 0;
757: if (cc_status.value2
758: && reg_overlap_mentioned_p (SET_DEST (EXP),
759: cc_status.value2))
760: cc_status.value2 = 0;
761: break;
762:
763: case UDIV:
764: case UMOD:
765: cc_status.mdep = CC_VALID_FOR_UNSIGNED;
766: cc_status.flags = CC_NO_OVERFLOW;
767: cc_status.value1 = SET_DEST (EXP);
768: cc_status.value2 = SET_SRC (EXP);
769: break;
770: default:
771: cc_status.mdep = 0;
772: cc_status.flags = CC_NO_OVERFLOW;
773: cc_status.value1 = SET_DEST (EXP);
774: cc_status.value2 = SET_SRC (EXP);
775: break;
776: }
777: break;
778:
779: case MEM:
780: switch (GET_CODE (SET_SRC (EXP)))
781: {
782: case REG:
783: if (GET_MODE (SET_SRC (EXP)) == QImode
784: || GET_MODE (SET_SRC (EXP)) == HImode)
785: {
786: cc_status.flags = CC_NO_OVERFLOW;
787: cc_status.value1 = SET_DEST (EXP);
788: cc_status.value2 = SET_SRC (EXP);
789: cc_status.mdep = 0;
790: break;
791: }
792: /* else: Fall through. */
793: case CONST_INT:
794: case SYMBOL_REF:
795: case LABEL_REF:
796: case CONST:
797: case CONST_DOUBLE:
798: case MEM:
799: /* Need to forget cc_status about memory positions each
800: time a memory store is made, even if the memory store
801: insns in question doesn't modify the condition codes. */
802: if (cc_status.value1 &&
803: GET_CODE (cc_status.value1) == MEM)
804: cc_status.value1 = 0;
805: if (cc_status.value2 &&
806: GET_CODE (cc_status.value2) == MEM)
807: cc_status.value2 = 0;
808: break;
809: case SIGN_EXTEND:
810: case FLOAT_EXTEND:
811: case FLOAT_TRUNCATE:
812: case FLOAT:
813: case FIX:
814: cc_status.flags = CC_NO_OVERFLOW;
815: cc_status.value1 = SET_DEST (EXP);
816: cc_status.value2 = SET_SRC (EXP);
817: cc_status.mdep = 0;
818: break;
819:
820: default:
821: abort ();
822: }
823: break;
824:
825: default:
826: abort ();
827: }
828: break;
829:
830: case CALL:
831: call:
832: CC_STATUS_INIT;
833: break;
834: /* Do calls preserve the condition codes? (At least forget
835: cc_status expressions if they refer to registers
836: not preserved across calls. Also forget expressions
837: about memory contents.) */
838: if (cc_status.value1
839: && (refers_to_regno_p (PYR_TREG (0), PYR_TREG (15),
840: cc_status.value1, 0)
841: || GET_CODE (cc_status.value1) == MEM))
842: cc_status.value1 = 0;
843: if (cc_status.value2
844: && (refers_to_regno_p (PYR_TREG (0), PYR_TREG (15),
845: cc_status.value2, 0)
846: || GET_CODE (cc_status.value2) == MEM))
847: cc_status.value2 = 0;
848: break;
849:
850: default:
851: CC_STATUS_INIT;
852: }
853: }
854:
855: void
856: forget_cc_if_dependent (op)
857: rtx op;
858: {
859: cc_status = cc_prev_status;
860: if (cc_status.value1 && reg_overlap_mentioned_p (op, cc_status.value1))
861: cc_status.value1 = 0;
862: if (cc_status.value2 && reg_overlap_mentioned_p (op, cc_status.value2))
863: cc_status.value2 = 0;
864: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.