|
|
1.1 root 1: /* Subroutines used for code generation on the DEC Alpha.
2: Copyright (C) 1992 Free Software Foundation, Inc.
3: Contributed by Richard Kenner ([email protected])
4:
5: This file is part of GNU CC.
6:
7: GNU CC is free software; you can redistribute it and/or modify
8: it under the terms of the GNU General Public License as published by
9: the Free Software Foundation; either version 2, or (at your option)
10: any later version.
11:
12: GNU CC is distributed in the hope that it will be useful,
13: but WITHOUT ANY WARRANTY; without even the implied warranty of
14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15: GNU General Public License for more details.
16:
17: You should have received a copy of the GNU General Public License
18: along with GNU CC; see the file COPYING. If not, write to
19: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20:
21:
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 "flags.h"
34: #include "recog.h"
35: #include "reload.h"
36: #include "expr.h"
37: #include "obstack.h"
38: #include "tree.h"
39:
40: /* Save information from a "cmpxx" operation until the branch or scc is
41: emitted. */
42:
43: rtx alpha_compare_op0, alpha_compare_op1;
44: int alpha_compare_fp_p;
45:
46: /* Save the name of the current function as used by the assembler. This
47: is used by the epilogue. */
48:
49: char *alpha_function_name;
50:
51: /* Nonzero if the current function needs gp. */
52:
53: int alpha_function_needs_gp;
54:
55: /* Returns 1 if VALUE is a mask that contains full bytes of zero or ones. */
56:
57: int
58: zap_mask (value)
59: HOST_WIDE_INT value;
60: {
61: int i;
62:
63: for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR;
64: i++, value >>= 8)
65: if ((value & 0xff) != 0 && (value & 0xff) != 0xff)
66: return 0;
67:
68: return 1;
69: }
70:
71: /* Returns 1 if OP is either the constant zero or a register. If a
72: register, it must be in the proper mode unless MODE is VOIDmode. */
73:
74: int
75: reg_or_0_operand (op, mode)
76: register rtx op;
77: enum machine_mode mode;
78: {
79: return op == const0_rtx || register_operand (op, mode);
80: }
81:
82: /* Return 1 if OP is an 8-bit constant or any register. */
83:
84: int
85: reg_or_8bit_operand (op, mode)
86: register rtx op;
87: enum machine_mode mode;
88: {
89: return ((GET_CODE (op) == CONST_INT
90: && (unsigned HOST_WIDE_INT) INTVAL (op) < 0x100)
91: || register_operand (op, mode));
92: }
93:
94: /* Return 1 if the operand is a valid second operand to an add insn. */
95:
96: int
97: add_operand (op, mode)
98: register rtx op;
99: enum machine_mode mode;
100: {
101: if (GET_CODE (op) == CONST_INT)
102: return ((unsigned HOST_WIDE_INT) (INTVAL (op) + 0x8000) < 0x10000
103: || ((INTVAL (op) & 0xffff) == 0
104: && (INTVAL (op) >> 31 == -1
105: || INTVAL (op) >> 31 == 0)));
106:
107: return register_operand (op, mode);
108: }
109:
110: /* Return 1 if the operand is a valid second operand to a sign-extending
111: add insn. */
112:
113: int
114: sext_add_operand (op, mode)
115: register rtx op;
116: enum machine_mode mode;
117: {
118: if (GET_CODE (op) == CONST_INT)
119: return ((unsigned HOST_WIDE_INT) INTVAL (op) < 255
120: || (unsigned HOST_WIDE_INT) (- INTVAL (op)) < 255);
121:
122: return register_operand (op, mode);
123: }
124:
125: /* Return 1 if OP is the constant 4 or 8. */
126:
127: int
128: const48_operand (op, mode)
129: register rtx op;
130: enum machine_mode mode;
131: {
132: return (GET_CODE (op) == CONST_INT
133: && (INTVAL (op) == 4 || INTVAL (op) == 8));
134: }
135:
136: /* Return 1 if OP is a valid first operand to an AND insn. */
137:
138: int
139: and_operand (op, mode)
140: register rtx op;
141: enum machine_mode mode;
142: {
143: if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == VOIDmode)
144: return (zap_mask (CONST_DOUBLE_LOW (op))
145: && zap_mask (CONST_DOUBLE_HIGH (op)));
146:
147: if (GET_CODE (op) == CONST_INT)
148: return ((unsigned HOST_WIDE_INT) INTVAL (op) < 0x100
149: || (unsigned HOST_WIDE_INT) ~ INTVAL (op) < 0x100
150: || zap_mask (INTVAL (op)));
151:
152: return register_operand (op, mode);
153: }
154:
155: /* Return 1 if OP is a constant that is the width, in bits, of an integral
156: mode smaller than DImode. */
157:
158: int
159: mode_width_operand (op, mode)
160: register rtx op;
161: enum machine_mode mode;
162: {
163: return (GET_CODE (op) == CONST_INT
164: && (INTVAL (op) == 8 || INTVAL (op) == 16 || INTVAL (op) == 32));
165: }
166:
167: /* Return 1 if OP is a constant that is the width of an integral machine mode
168: smaller than an integer. */
169:
170: int
171: mode_mask_operand (op, mode)
172: register rtx op;
173: enum machine_mode mode;
174: {
175: #if HOST_BITS_PER_WIDE_INT == 32
176: if (GET_CODE (op) == CONST_DOUBLE)
177: return CONST_DOUBLE_HIGH (op) == 0 && CONST_DOUBLE_LOW (op) == -1;
178: #endif
179:
180: if (GET_CODE (op) == CONST_INT)
181: return (INTVAL (op) == 0xff
182: || INTVAL (op) == 0xffff
183: #if HOST_BITS_PER_WIDE_INT == 64
184: || INTVAL (op) == 0xffffffff
185: #endif
186: );
187: }
188:
189: /* Return 1 if OP is a multiple of 8 less than 64. */
190:
191: int
192: mul8_operand (op, mode)
193: register rtx op;
194: enum machine_mode mode;
195: {
196: return (GET_CODE (op) == CONST_INT
197: && (unsigned HOST_WIDE_INT) INTVAL (op) < 64
198: && (INTVAL (op) & 7) == 0);
199: }
200:
201: /* Return 1 if OP is the constant zero in floating-point. */
202:
203: int
204: fp0_operand (op, mode)
205: register rtx op;
206: enum machine_mode mode;
207: {
208: return (GET_MODE (op) == mode
209: && GET_MODE_CLASS (mode) == MODE_FLOAT && op == CONST0_RTX (mode));
210: }
211:
212: /* Return 1 if OP is the floating-point constant zero or a register. */
213:
214: int
215: reg_or_fp0_operand (op, mode)
216: register rtx op;
217: enum machine_mode mode;
218: {
219: return fp0_operand (op, mode) || register_operand (op, mode);
220: }
221:
222: /* Return 1 if OP is a register or a constant integer. */
223:
224:
225: int
226: reg_or_cint_operand (op, mode)
227: register rtx op;
228: enum machine_mode mode;
229: {
230: return GET_CODE (op) == CONST_INT || register_operand (op, mode);
231: }
232:
233: /* Return 1 if OP is a valid operand for the source of a move insn. */
234:
235: int
236: input_operand (op, mode)
237: register rtx op;
238: enum machine_mode mode;
239: {
240: if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
241: return 0;
242:
243: if (GET_MODE_CLASS (mode) == MODE_FLOAT && GET_MODE (op) != mode)
244: return 0;
245:
246: switch (GET_CODE (op))
247: {
248: case LABEL_REF:
249: case SYMBOL_REF:
250: case CONST:
251: return mode == DImode;
252:
253: case REG:
254: return 1;
255:
256: case SUBREG:
257: if (register_operand (op, mode))
258: return 1;
259: /* ... fall through ... */
260: case MEM:
261: return mode != HImode && mode != QImode && general_operand (op, mode);
262:
263: case CONST_DOUBLE:
264: return GET_MODE_CLASS (mode) == MODE_FLOAT && op == CONST0_RTX (mode);
265:
266: case CONST_INT:
267: return mode == QImode || mode == HImode || add_operand (op, mode);
268: }
269:
270: return 0;
271: }
272:
273: /* Return 1 if OP is a SYMBOL_REF for the current function. */
274:
275: int
276: current_function_operand (op, mode)
277: rtx op;
278: enum machine_mode mode;
279: {
280: return (GET_CODE (op) == SYMBOL_REF
281: && ! strcmp (XSTR (op, 0), current_function_name));
282: }
283:
284: /* Return 1 if OP is a valid Alpha comparison operator. Here we know which
285: comparisons are valid in which insn. */
286:
287: int
288: alpha_comparison_operator (op, mode)
289: register rtx op;
290: enum machine_mode mode;
291: {
292: enum rtx_code code = GET_CODE (op);
293:
294: if (mode != GET_MODE (op) || GET_RTX_CLASS (code) != '<')
295: return 0;
296:
297: return (code == EQ || code == LE || code == LT
298: || (mode == DImode && (code == LEU || code == LTU)));
299: }
300:
301: /* Return 1 if OP is a signed comparison operation. */
302:
303: int
304: signed_comparison_operator (op, mode)
305: register rtx op;
306: enum machine_mode mode;
307: {
308: switch (GET_CODE (op))
309: {
310: case EQ: case NE: case LE: case LT: case GE: case GT:
311: return 1;
312: }
313:
314: return 0;
315: }
316:
317: /* Return 1 if this is a divide or modulus operator. */
318:
319: int
320: divmod_operator (op, mode)
321: register rtx op;
322: enum machine_mode mode;
323: {
324: switch (GET_CODE (op))
325: {
326: case DIV: case MOD: case UDIV: case UMOD:
327: return 1;
328: }
329:
330: return 0;
331: }
332:
333: /* Return 1 if this memory address is a known aligned register plus
334: a constant. It must be a valid address. This means that we can do
335: this as an aligned reference plus some offset.
336:
337: Take into account what reload will do.
338:
339: We could say that out-of-range stack slots are alignable, but that would
340: complicate get_aligned_mem and it isn't worth the trouble since few
341: functions have large stack space. */
342:
343: int
344: aligned_memory_operand (op, mode)
345: register rtx op;
346: enum machine_mode mode;
347: {
348: if (GET_CODE (op) == SUBREG)
349: {
350: if (GET_MODE (op) != mode)
351: return 0;
352: op = SUBREG_REG (op);
353: mode = GET_MODE (op);
354: }
355:
356: if (reload_in_progress && GET_CODE (op) == REG
357: && REGNO (op) >= FIRST_PSEUDO_REGISTER)
358: op = reg_equiv_mem[REGNO (op)];
359:
360: if (GET_CODE (op) != MEM || GET_MODE (op) != mode
361: || ! memory_address_p (mode, XEXP (op, 0)))
362: return 0;
363:
364: op = XEXP (op, 0);
365:
366: if (GET_CODE (op) == PLUS)
367: op = XEXP (op, 0);
368:
369: return (GET_CODE (op) == REG
370: && (REGNO (op) == STACK_POINTER_REGNUM || op == frame_pointer_rtx
371: || (REGNO (op) >= FIRST_VIRTUAL_REGISTER
372: && REGNO (op) <= LAST_VIRTUAL_REGISTER)));
373: }
374:
375: /* Similar, but return 1 if OP is a MEM which is not alignable. */
376:
377: int
378: unaligned_memory_operand (op, mode)
379: register rtx op;
380: enum machine_mode mode;
381: {
382: if (GET_CODE (op) == SUBREG)
383: {
384: if (GET_MODE (op) != mode)
385: return 0;
386: op = SUBREG_REG (op);
387: mode = GET_MODE (op);
388: }
389:
390: if (reload_in_progress && GET_CODE (op) == REG
391: && REGNO (op) >= FIRST_PSEUDO_REGISTER)
392: op = reg_equiv_mem[REGNO (op)];
393:
394: if (GET_CODE (op) != MEM || GET_MODE (op) != mode)
395: return 0;
396:
397: op = XEXP (op, 0);
398:
399: if (! memory_address_p (mode, op))
400: return 1;
401:
402: if (GET_CODE (op) == PLUS)
403: op = XEXP (op, 0);
404:
405: return (GET_CODE (op) != REG
406: || (REGNO (op) != STACK_POINTER_REGNUM && op != frame_pointer_rtx
407: && (REGNO (op) < FIRST_VIRTUAL_REGISTER
408: || REGNO (op) > LAST_VIRTUAL_REGISTER)));
409: }
410:
411: /* Return 1 if OP is any memory location. During reload a pseudo matches. */
412:
413: int
414: any_memory_operand (op, mode)
415: register rtx op;
416: enum machine_mode mode;
417: {
418: return (GET_CODE (op) == MEM
419: || (GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == REG)
420: || (reload_in_progress && GET_CODE (op) == REG
421: && REGNO (op) >= FIRST_PSEUDO_REGISTER)
422: || (reload_in_progress && GET_CODE (op) == SUBREG
423: && GET_CODE (SUBREG_REG (op)) == REG
424: && REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER));
425: }
426:
427: /* REF is an alignable memory location. Place an aligned SImode
428: reference into *PALIGNED_MEM and the number of bits to shift into
429: *PBITNUM. */
430:
431: void
432: get_aligned_mem (ref, paligned_mem, pbitnum)
433: rtx ref;
434: rtx *paligned_mem, *pbitnum;
435: {
436: rtx base;
437: HOST_WIDE_INT offset = 0;
438:
439: if (GET_CODE (ref) == SUBREG)
440: {
441: offset = SUBREG_WORD (ref) * UNITS_PER_WORD;
442: if (BYTES_BIG_ENDIAN)
443: offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (ref)))
444: - MIN (UNITS_PER_WORD,
445: GET_MODE_SIZE (GET_MODE (SUBREG_REG (ref)))));
446: ref = SUBREG_REG (ref);
447: }
448:
449: if (GET_CODE (ref) == REG)
450: ref = reg_equiv_mem[REGNO (ref)];
451:
452: if (reload_in_progress)
453: base = find_replacement (&XEXP (ref, 0));
454: else
455: base = XEXP (ref, 0);
456:
457: if (GET_CODE (base) == PLUS)
458: offset += INTVAL (XEXP (base, 1)), base = XEXP (base, 0);
459:
460: *paligned_mem = gen_rtx (MEM, SImode,
461: plus_constant (base, offset & ~3));
462: MEM_IN_STRUCT_P (*paligned_mem) = MEM_IN_STRUCT_P (ref);
463: MEM_VOLATILE_P (*paligned_mem) = MEM_VOLATILE_P (ref);
464: RTX_UNCHANGING_P (*paligned_mem) = RTX_UNCHANGING_P (ref);
465:
466: *pbitnum = GEN_INT ((offset & 3) * 8);
467: }
468:
469: /* Similar, but just get the address. Handle the two reload cases. */
470:
471: rtx
472: get_unaligned_address (ref)
473: rtx ref;
474: {
475: rtx base;
476: HOST_WIDE_INT offset = 0;
477:
478: if (GET_CODE (ref) == SUBREG)
479: {
480: offset = SUBREG_WORD (ref) * UNITS_PER_WORD;
481: if (BYTES_BIG_ENDIAN)
482: offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (ref)))
483: - MIN (UNITS_PER_WORD,
484: GET_MODE_SIZE (GET_MODE (SUBREG_REG (ref)))));
485: ref = SUBREG_REG (ref);
486: }
487:
488: if (GET_CODE (ref) == REG)
489: ref = reg_equiv_mem[REGNO (ref)];
490:
491: if (reload_in_progress)
492: base = find_replacement (&XEXP (ref, 0));
493: else
494: base = XEXP (ref, 0);
495:
496: if (GET_CODE (base) == PLUS)
497: offset += INTVAL (XEXP (base, 1)), base = XEXP (base, 0);
498:
499: return plus_constant (base, offset);
500: }
501:
502: /* Subfunction of the following function. Update the flags of any MEM
503: found in part of X. */
504:
505: static void
506: alpha_set_memflags_1 (x, in_struct_p, volatile_p, unchanging_p)
507: rtx x;
508: int in_struct_p, volatile_p, unchanging_p;
509: {
510: int i;
511:
512: switch (GET_CODE (x))
513: {
514: case SEQUENCE:
515: case PARALLEL:
516: for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
517: alpha_set_memflags_1 (XVECEXP (x, 0, i), in_struct_p, volatile_p,
518: unchanging_p);
519: break;
520:
521: case INSN:
522: alpha_set_memflags_1 (PATTERN (x), in_struct_p, volatile_p,
523: unchanging_p);
524: break;
525:
526: case SET:
527: alpha_set_memflags_1 (SET_DEST (x), in_struct_p, volatile_p,
528: unchanging_p);
529: alpha_set_memflags_1 (SET_SRC (x), in_struct_p, volatile_p,
530: unchanging_p);
531: break;
532:
533: case MEM:
534: MEM_IN_STRUCT_P (x) = in_struct_p;
535: MEM_VOLATILE_P (x) = volatile_p;
536: RTX_UNCHANGING_P (x) = unchanging_p;
537: break;
538: }
539: }
540:
541: /* Given INSN, which is either an INSN or a SEQUENCE generated to
542: perform a memory operation, look for any MEMs in either a SET_DEST or
543: a SET_SRC and copy the in-struct, unchanging, and volatile flags from
544: REF into each of the MEMs found. If REF is not a MEM, don't do
545: anything. */
546:
547: void
548: alpha_set_memflags (insn, ref)
549: rtx insn;
550: rtx ref;
551: {
552: /* Note that it is always safe to get these flags, though they won't
553: be what we think if REF is not a MEM. */
554: int in_struct_p = MEM_IN_STRUCT_P (ref);
555: int volatile_p = MEM_VOLATILE_P (ref);
556: int unchanging_p = RTX_UNCHANGING_P (ref);
557:
558: if (GET_CODE (ref) != MEM
559: || (! in_struct_p && ! volatile_p && ! unchanging_p))
560: return;
561:
562: alpha_set_memflags_1 (insn, in_struct_p, volatile_p, unchanging_p);
563: }
564:
565: /* Try to output insns to set TARGET equal to the constant C if it can be
566: done in less than N insns. Returns 1 if it can be done and the
567: insns have been emitted. If it would take more than N insns, zero is
568: returned and no insns and emitted. */
569:
570: int
571: alpha_emit_set_const (target, c, n)
572: rtx target;
573: HOST_WIDE_INT c;
574: int n;
575: {
576: HOST_WIDE_INT new = c;
577: int i, bits;
578:
579: #if HOST_BITS_PER_WIDE_INT == 64
580: /* We are only called for SImode and DImode. If this is SImode, ensure that
581: we are sign extended to a full word. This does not make any sense when
582: cross-compiling on a narrow machine. */
583:
584: if (GET_MODE (target) == SImode)
585: c = (c & 0xffffffff) - 2 * (c & 0x80000000);
586: #endif
587:
588: /* If this is a sign-extended 32-bit constant, we can do this in at most
589: three insns, so do it if we have enough insns left. We always have
590: a sign-extended 32-bit constant when compiling on a narrow machine. */
591:
592: if (HOST_BITS_PER_WIDE_INT != 64
593: || c >> 31 == -1 || c >> 31 == 0)
594: {
595: HOST_WIDE_INT low = (c & 0xffff) - 2 * (c & 0x8000);
596: HOST_WIDE_INT tmp1 = c - low;
597: HOST_WIDE_INT high
598: = ((tmp1 >> 16) & 0xffff) - 2 * ((tmp1 >> 16) & 0x8000);
599: HOST_WIDE_INT tmp2 = c - (high << 16) - low;
600: HOST_WIDE_INT extra = 0;
601:
602: if (tmp2)
603: {
604: extra = 0x4000;
605: tmp1 -= 0x40000000;
606: high = ((tmp1 >> 16) & 0xffff) - 2 * ((tmp1 >> 16) & 0x8000);
607: }
608:
609: if (c == low || (low == 0 && extra == 0))
610: {
611: emit_move_insn (target, GEN_INT (c));
612: return 1;
613: }
614: else if (n >= 2 + (extra != 0))
615: {
616: emit_move_insn (target, GEN_INT (low));
617: if (extra != 0)
618: emit_insn (gen_add2_insn (target, GEN_INT (extra << 16)));
619:
620: emit_insn (gen_add2_insn (target, GEN_INT (high << 16)));
621: return 1;
622: }
623: }
624:
625: /* If we couldn't do it that way, try some other methods (that depend on
626: being able to compute in the target's word size). But if we have no
627: instructions left, don't bother. Also, don't even try if this is
628: SImode (in which case we should have already done something, but
629: do a sanity check here). */
630:
631: if (n == 1 || HOST_BITS_PER_WIDE_INT < 64 || GET_MODE (target) != DImode)
632: return 0;
633:
634: /* First, see if can load a value into the target that is the same as the
635: constant except that all bytes that are 0 are changed to be 0xff. If we
636: can, then we can do a ZAPNOT to obtain the desired constant. */
637:
638: for (i = 0; i < 64; i += 8)
639: if ((new & ((HOST_WIDE_INT) 0xff << i)) == 0)
640: new |= (HOST_WIDE_INT) 0xff << i;
641:
642: if (alpha_emit_set_const (target, new, n - 1))
643: {
644: emit_insn (gen_anddi3 (target, target, GEN_INT (c | ~ new)));
645: return 1;
646: }
647:
648: /* Find, see if we can load a related constant and then shift and possibly
649: negate it to get the constant we want. Try this once each increasing
650: numbers of insns. */
651:
652: for (i = 1; i < n; i++)
653: {
654: /* First try complementing. */
655: if (alpha_emit_set_const (target, ~ c, i))
656: {
657: emit_insn (gen_one_cmpldi2 (target, target));
658: return 1;
659: }
660:
661: /* First try to form a constant and do a left shift. We can do this
662: if some low-order bits are zero; the exact_log2 call below tells
663: us that information. The bits we are shifting out could be any
664: value, but here we'll just try the 0- and sign-extended forms of
665: the constant. To try to increase the chance of having the same
666: constant in more than one insn, start at the highest number of
667: bits to shift, but try all possibilities in case a ZAPNOT will
668: be useful. */
669:
670: if ((bits = exact_log2 (c & - c)) > 0)
671: for (; bits > 0; bits--)
672: if (alpha_emit_set_const (target, c >> bits, i)
673: || alpha_emit_set_const (target,
674: ((unsigned HOST_WIDE_INT) c) >> bits,
675: i))
676: {
677: emit_insn (gen_ashldi3 (target, target, GEN_INT (bits)));
678: return 1;
679: }
680:
681: /* Now try high-order zero bits. Here we try the shifted-in bits as
682: all zero and all ones. */
683:
684: if ((bits = HOST_BITS_PER_WIDE_INT - floor_log2 (c) - 1) > 0)
685: for (; bits > 0; bits--)
686: if (alpha_emit_set_const (target, c << bits, i)
687: || alpha_emit_set_const (target,
688: ((c << bits)
689: | (((HOST_WIDE_INT) 1 << bits) - 1)),
690: i))
691: {
692: emit_insn (gen_lshrdi3 (target, target, GEN_INT (bits)));
693: return 1;
694: }
695:
696: /* Now try high-order 1 bits. We get that with a sign-extension.
697: But one bit isn't enough here. */
698:
699: if ((bits = HOST_BITS_PER_WIDE_INT - floor_log2 (~ c) - 2) > 0)
700: for (; bits > 0; bits--)
701: if (alpha_emit_set_const (target, c << bits, i)
702: || alpha_emit_set_const (target,
703: ((c << bits)
704: | (((HOST_WIDE_INT) 1 << bits) - 1)),
705: i))
706: {
707: emit_insn (gen_ashrdi3 (target, target, GEN_INT (bits)));
708: return 1;
709: }
710: }
711:
712: return 0;
713: }
714:
715: /* Adjust the cost of a scheduling dependency. Return the new cost of
716: a dependency LINK or INSN on DEP_INSN. COST is the current cost. */
717:
718: int
719: alpha_adjust_cost (insn, link, dep_insn, cost)
720: rtx insn;
721: rtx link;
722: rtx dep_insn;
723: int cost;
724: {
725: rtx set;
726:
727: /* If the dependence is an anti-dependence, there is no cost. For an
728: output dependence, there is sometimes a cost, but it doesn't seem
729: worth handling those few cases. */
730:
731: if (REG_NOTE_KIND (link) != 0)
732: return 0;
733:
734: /* If INSN is a store insn and DEP_INSN is setting the data being stored,
735: we can sometimes lower the cost. */
736:
737: if (recog_memoized (insn) >= 0 && get_attr_type (insn) == TYPE_ST
738: && (set = single_set (dep_insn)) != 0
739: && GET_CODE (PATTERN (insn)) == SET
740: && rtx_equal_p (SET_DEST (set), SET_SRC (PATTERN (insn))))
741: switch (get_attr_type (dep_insn))
742: {
743: case TYPE_LD:
744: /* No savings here. */
745: return cost;
746:
747: case TYPE_IMULL:
748: case TYPE_IMULQ:
749: /* In these cases, we save one cycle. */
750: return cost - 2;
751:
752: default:
753: /* In all other cases, we save two cycles. */
754: return MAX (0, cost - 4);
755: }
756:
757: /* Another case that needs adjustment is an arithmetic or logical
758: operation. It's cost is usually one cycle, but we default it to
759: two in the MD file. The only case that it is actually two is
760: for the address in loads and stores. */
761:
762: if (recog_memoized (dep_insn) >= 0
763: && get_attr_type (dep_insn) == TYPE_IADDLOG)
764: switch (get_attr_type (insn))
765: {
766: case TYPE_LD:
767: case TYPE_ST:
768: return cost;
769:
770: default:
771: return 2;
772: }
773:
774: /* The final case is when a compare feeds into an integer branch. The cost
775: is only one cycle in that case. */
776:
777: if (recog_memoized (dep_insn) >= 0
778: && get_attr_type (dep_insn) == TYPE_ICMP
779: && recog_memoized (insn) >= 0
780: && get_attr_type (insn) == TYPE_IBR)
781: return 2;
782:
783: /* Otherwise, return the default cost. */
784:
785: return cost;
786: }
787:
788: /* Print an operand. Recognize special options, documented below. */
789:
790: void
791: print_operand (file, x, code)
792: FILE *file;
793: rtx x;
794: char code;
795: {
796: int i;
797:
798: switch (code)
799: {
800: case 'r':
801: /* If this operand is the constant zero, write it as "$31". */
802: if (GET_CODE (x) == REG)
803: fprintf (file, "%s", reg_names[REGNO (x)]);
804: else if (x == CONST0_RTX (GET_MODE (x)))
805: fprintf (file, "$31");
806: else
807: output_operand_lossage ("invalid %%r value");
808:
809: break;
810:
811: case 'R':
812: /* Similar, but for floating-point. */
813: if (GET_CODE (x) == REG)
814: fprintf (file, "%s", reg_names[REGNO (x)]);
815: else if (x == CONST0_RTX (GET_MODE (x)))
816: fprintf (file, "$f31");
817: else
818: output_operand_lossage ("invalid %%R value");
819:
820: break;
821:
822: case 'N':
823: /* Write the 1's complement of a constant. */
824: if (GET_CODE (x) != CONST_INT)
825: output_operand_lossage ("invalid %%N value");
826:
827: fprintf (file, "%ld", ~ INTVAL (x));
828: break;
829:
830: case 'P':
831: /* Write 1 << C, for a constant C. */
832: if (GET_CODE (x) != CONST_INT)
833: output_operand_lossage ("invalid %%P value");
834:
835: fprintf (file, "%ld", (HOST_WIDE_INT) 1 << INTVAL (x));
836: break;
837:
838: case 'h':
839: /* Write the high-order 16 bits of a constant, sign-extended. */
840: if (GET_CODE (x) != CONST_INT)
841: output_operand_lossage ("invalid %%h value");
842:
843: fprintf (file, "%ld", INTVAL (x) >> 16);
844: break;
845:
846: case 'L':
847: /* Write the low-order 16 bits of a constant, sign-extended. */
848: if (GET_CODE (x) != CONST_INT)
849: output_operand_lossage ("invalid %%L value");
850:
851: fprintf (file, "%ld", (INTVAL (x) & 0xffff) - 2 * (INTVAL (x) & 0x8000));
852: break;
853:
854: case 'm':
855: /* Write mask for ZAP insn. */
856: if (GET_CODE (x) == CONST_DOUBLE)
857: {
858: HOST_WIDE_INT mask = 0;
859: HOST_WIDE_INT value;
860:
861: value = CONST_DOUBLE_LOW (x);
862: for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR;
863: i++, value >>= 8)
864: if (value & 0xff)
865: mask |= (1 << i);
866:
867: value = CONST_DOUBLE_HIGH (x);
868: for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR;
869: i++, value >>= 8)
870: if (value & 0xff)
871: mask |= (1 << (i + sizeof (int)));
872:
873: fprintf (file, "%ld", mask & 0xff);
874: }
875:
876: else if (GET_CODE (x) == CONST_INT)
877: {
878: HOST_WIDE_INT mask = 0, value = INTVAL (x);
879:
880: for (i = 0; i < 8; i++, value >>= 8)
881: if (value & 0xff)
882: mask |= (1 << i);
883:
884: fprintf (file, "%ld", mask);
885: }
886: else
887: output_operand_lossage ("invalid %%m value");
888: break;
889:
890: case 'M':
891: /* 'b', 'w', or 'l' as the value of the constant. */
892: if (GET_CODE (x) != CONST_INT
893: || (INTVAL (x) != 8 && INTVAL (x) != 16 && INTVAL (x) != 32))
894: output_operand_lossage ("invalid %%M value");
895:
896: fprintf (file, "%s",
897: INTVAL (x) == 8 ? "b" : INTVAL (x) == 16 ? "w" : "l");
898: break;
899:
900: case 'U':
901: /* Similar, except do it from the mask. */
902: if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xff)
903: fprintf (file, "b");
904: else if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xffff)
905: fprintf (file, "w");
906: #if HOST_BITS_PER_WIDE_INT == 32
907: else if (GET_CODE (x) == CONST_DOUBLE
908: && CONST_DOUBLE_HIGH (x) == 0
909: && CONST_DOUBLE_LOW (x) == -1)
910: fprintf (file, "l");
911: #else
912: else if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xffffffff)
913: fprintf (file, "l");
914: #endif
915: else
916: output_operand_lossage ("invalid %%U value");
917: break;
918:
919: case 's':
920: /* Write the constant value divided by 8. */
921: if (GET_CODE (x) != CONST_INT
922: && (unsigned HOST_WIDE_INT) INTVAL (x) >= 64
923: && (INTVAL (x) & 7) != 8)
924: output_operand_lossage ("invalid %%s value");
925:
926: fprintf (file, "%ld", INTVAL (x) / 8);
927: break;
928:
929: case 'S':
930: /* Same, except compute (64 - c) / 8 */
931:
932: if (GET_CODE (x) != CONST_INT
933: && (unsigned HOST_WIDE_INT) INTVAL (x) >= 64
934: && (INTVAL (x) & 7) != 8)
935: output_operand_lossage ("invalid %%s value");
936:
937: fprintf (file, "%ld", (64 - INTVAL (x)) / 8);
938: break;
939:
940: case 'C':
941: /* Write out comparison name. */
942: if (GET_RTX_CLASS (GET_CODE (x)) != '<')
943: output_operand_lossage ("invalid %%C value");
944:
945: if (GET_CODE (x) == LEU)
946: fprintf (file, "ule");
947: else if (GET_CODE (x) == LTU)
948: fprintf (file, "ult");
949: else
950: fprintf (file, "%s", GET_RTX_NAME (GET_CODE (x)));
951: break;
952:
953: case 'D':
954: /* Similar, but write reversed code. We can't get an unsigned code
955: here. */
956: if (GET_RTX_CLASS (GET_CODE (x)) != '<')
957: output_operand_lossage ("invalid %%D value");
958:
959: fprintf (file, "%s", GET_RTX_NAME (reverse_condition (GET_CODE (x))));
960: break;
961:
962: case 'E':
963: /* Write the divide or modulus operator. */
964: switch (GET_CODE (x))
965: {
966: case DIV:
967: fprintf (file, "div%s", GET_MODE (x) == SImode ? "l" : "q");
968: break;
969: case UDIV:
970: fprintf (file, "div%su", GET_MODE (x) == SImode ? "l" : "q");
971: break;
972: case MOD:
973: fprintf (file, "rem%s", GET_MODE (x) == SImode ? "l" : "q");
974: break;
975: case UMOD:
976: fprintf (file, "rem%su", GET_MODE (x) == SImode ? "l" : "q");
977: break;
978: default:
979: output_operand_lossage ("invalid %%E value");
980: break;
981: }
982: break;
983:
984: case 'F':
985: /* Write the symbol; if the current function uses GP, write a
986: modified version. */
987: if (GET_CODE (x) != SYMBOL_REF)
988: output_operand_lossage ("invalid %%F value");
989:
990: output_addr_const (file, x);
991: if (alpha_function_needs_gp)
992: fprintf (file, "..ng");
993: break;
994:
995: case 'A':
996: /* Write "_u" for unaligned access. */
997: if (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == AND)
998: fprintf (file, "_u");
999: break;
1000:
1001: case 0:
1002: if (GET_CODE (x) == REG)
1003: fprintf (file, "%s", reg_names[REGNO (x)]);
1004: else if (GET_CODE (x) == MEM)
1005: output_address (XEXP (x, 0));
1006: else
1007: output_addr_const (file, x);
1008: break;
1009:
1010: default:
1011: output_operand_lossage ("invalid %%xn code");
1012: }
1013: }
1014:
1015: /* Do what is necessary for `va_start'. The argument is ignored;
1016: We look at the current function to determine if stdarg or varargs
1017: is used and fill in an initial va_list. A pointer to this constructor
1018: is returned. */
1019:
1020: struct rtx_def *
1021: alpha_builtin_saveregs (arglist)
1022: tree arglist;
1023: {
1024: rtx block, addr, argsize;
1025: tree fntype = TREE_TYPE (current_function_decl);
1026: int stdarg = (TYPE_ARG_TYPES (fntype) != 0
1027: && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
1028: != void_type_node));
1029: int nregs = current_function_args_info;
1030:
1031: /* If we have a variable-sized argument already, we will have used all
1032: the registers, so set up to indicate that. */
1033:
1034: if (GET_CODE (current_function_arg_offset_rtx) != CONST_INT)
1035: {
1036: argsize = plus_constant (current_function_arg_offset_rtx,
1037: (6 * UNITS_PER_WORD + UNITS_PER_WORD - 1));
1038: argsize = expand_shift (RSHIFT_EXPR, Pmode, argsize,
1039: build_int_2 (3, 0), argsize, 0);
1040: }
1041: else
1042: {
1043: /* Compute the number of args in memory and number of arguments already
1044: processed. Then adjust the number of registers if this is stdarg. */
1045: int memargs = ((INTVAL (current_function_arg_offset_rtx)
1046: + UNITS_PER_WORD - 1)
1047: / UNITS_PER_WORD);
1048:
1049: argsize = GEN_INT (MIN (nregs, 6) + memargs);
1050:
1051: if (nregs <= 6)
1052: nregs -= stdarg;
1053: }
1054:
1055: /* Allocate the va_list constructor */
1056: block = assign_stack_local (BLKmode, 4 * UNITS_PER_WORD, BITS_PER_WORD);
1057: RTX_UNCHANGING_P (block) = 1;
1058: RTX_UNCHANGING_P (XEXP (block, 0)) = 1;
1059:
1060: /* Store the argsize as the __va_arg member. */
1061: emit_move_insn (change_address (block, DImode, XEXP (block, 0)),
1062: argsize);
1063:
1064: /* Store the arg pointer in the __va_stack member. */
1065: emit_move_insn (change_address (block, Pmode,
1066: plus_constant (XEXP (block, 0),
1067: UNITS_PER_WORD)),
1068: virtual_incoming_args_rtx);
1069:
1070: /* Allocate the integer register space, and store it as the
1071: __va_ireg member. */
1072: addr = assign_stack_local (BLKmode, 6 * UNITS_PER_WORD, -1);
1073: MEM_IN_STRUCT_P (addr) = 1;
1074: RTX_UNCHANGING_P (addr) = 1;
1075: RTX_UNCHANGING_P (XEXP (addr, 0)) = 1;
1076:
1077: emit_move_insn (change_address (block, Pmode,
1078: plus_constant (XEXP (block, 0),
1079: 2 * UNITS_PER_WORD)),
1080: copy_to_reg (XEXP (addr, 0)));
1081:
1082: /* Now store the incoming integer registers. */
1083: if (nregs < 6)
1084: move_block_from_reg
1085: (16 + nregs,
1086: change_address (addr, Pmode,
1087: plus_constant (XEXP (addr, 0),
1088: nregs * UNITS_PER_WORD)),
1089: 6 - nregs);
1090:
1091: /* Allocate the FP register space, and store it as the
1092: __va_freg member. */
1093: addr = assign_stack_local (BLKmode, 6 * UNITS_PER_WORD, -1);
1094: MEM_IN_STRUCT_P (addr) = 1;
1095: RTX_UNCHANGING_P (addr) = 1;
1096: RTX_UNCHANGING_P (XEXP (addr, 0)) = 1;
1097:
1098: emit_move_insn (change_address (block, Pmode,
1099: plus_constant (XEXP (block, 0),
1100: 3 * UNITS_PER_WORD)),
1101: copy_to_reg (XEXP (addr, 0)));
1102:
1103: /* Now store the incoming floating-point registers. If we are not
1104: to use the floating-point registers, store the integer registers
1105: in those locations too. */
1106: if (nregs < 6)
1107: move_block_from_reg
1108: (16 + 32 * (TARGET_FPREGS != 0) + nregs,
1109: change_address (addr, Pmode,
1110: plus_constant (XEXP (addr, 0),
1111: nregs * UNITS_PER_WORD)),
1112: 6 - nregs);
1113:
1114: /* Return the address of the va_list constructor, but don't put it in a
1115: register. This fails when not optimizing and produces worse code when
1116: optimizing. */
1117: return XEXP (block, 0);
1118: }
1119:
1120: /* This page contains routines that are used to determine what the function
1121: prologue and epilogue code will do and write them out. */
1122:
1123: /* Compute the size of the save area in the stack. */
1124:
1125: int
1126: alpha_sa_size ()
1127: {
1128: int size = 0;
1129: int i;
1130:
1131: for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
1132: if (! fixed_regs[i] && ! call_used_regs[i] && regs_ever_live[i])
1133: size++;
1134:
1135: return size * 8;
1136: }
1137:
1138: /* Return non-zero if this function needs gp. It does if it has
1139: an LDSYM insn. */
1140:
1141: int
1142: alpha_need_gp ()
1143: {
1144: rtx insn;
1145:
1146: for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
1147: if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
1148: && GET_CODE (PATTERN (insn)) != USE
1149: && GET_CODE (PATTERN (insn)) != CLOBBER
1150: && get_attr_type (insn) == TYPE_LDSYM)
1151: return 1;
1152:
1153: return 0;
1154: }
1155:
1156: /* Return 1 if GP is dead at after INSN. */
1157:
1158: int
1159: alpha_gp_dead_after (insn)
1160: rtx insn;
1161: {
1162: int jump_count = 0;
1163: int found = 0;
1164: rtx p;
1165:
1166: /* If we aren't optimizing, don't do this optimization. More importantly,
1167: JUMP_LABEL isn't properly set when not optimizing. */
1168:
1169: if (optimize == 0)
1170: return 0;
1171:
1172: /* If we are followed by a BARRIER, we don't return. */
1173: if (NEXT_INSN (insn) && GET_CODE (NEXT_INSN (insn)) == BARRIER)
1174: return 1;
1175:
1176: /* Otherwise search for a use of GP before a return. */
1177:
1178: for (p = next_active_insn (insn); p; p = next_active_insn (p))
1179: {
1180: if (get_attr_type (p) == TYPE_LDSYM
1181: || get_attr_type (p) == TYPE_JSR)
1182: {
1183: found = 1;
1184: break;
1185: }
1186:
1187: if (GET_CODE (p) == JUMP_INSN)
1188: {
1189: if (GET_CODE (PATTERN (p)) == RETURN)
1190: break;
1191:
1192: if (! simplejump_p (p) || jump_count++ > 10)
1193: {
1194: found = 1;
1195: break;
1196: }
1197:
1198: p = JUMP_LABEL (p);
1199: }
1200: }
1201:
1202: /* Restore any operands destroyed by the attribute calls above. */
1203: insn_extract (insn);
1204:
1205: return ! found;
1206: }
1207:
1208: /* Return 1 if this function can directly return via $26. */
1209:
1210: int
1211: direct_return ()
1212: {
1213: return (reload_completed && alpha_sa_size () == 0
1214: && get_frame_size () == 0
1215: && current_function_pretend_args_size == 0);
1216: }
1217:
1218: /* Write function prologue. */
1219:
1220: void
1221: output_prolog (file, size)
1222: FILE *file;
1223: int size;
1224: {
1225: HOST_WIDE_INT frame_size = ((size + current_function_outgoing_args_size
1226: + current_function_pretend_args_size
1227: + alpha_sa_size () + 15) & ~15);
1228: int reg_offset = current_function_outgoing_args_size;
1229: int start_reg_offset = reg_offset;
1230: unsigned reg_mask = 0;
1231: int i;
1232:
1233: /* If we need a GP, load it first. */
1234: alpha_function_needs_gp = alpha_need_gp ();
1235:
1236: if (alpha_function_needs_gp)
1237: {
1238: rtx insn;
1239:
1240: fprintf (file, "\tldgp $29,0($27)\n");
1241:
1242: /* If we have a recursive call, put a special label here. */
1243: for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
1244: if (GET_CODE (insn) == CALL_INSN
1245: && get_attr_type (insn) != TYPE_JSR)
1246: {
1247: fprintf (file, "%s..ng:\n", current_function_name);
1248: break;
1249: }
1250: }
1251:
1252: /* Adjust the stack by the frame size. If the frame size is > 32768
1253: bytes, we have to load it into a register first and then subtract
1254: from sp. Note that we are only allowed to adjust sp once in the
1255: prologue. */
1256:
1257: if (frame_size > 32768)
1258: {
1259: HOST_WIDE_INT low = (frame_size & 0xffff) - 2 * (frame_size & 0x8000);
1260: HOST_WIDE_INT tmp1 = frame_size - low;
1261: HOST_WIDE_INT high
1262: = ((tmp1 >> 16) & 0xfff) - 2 * ((tmp1 >> 16) & 0x8000);
1263: HOST_WIDE_INT tmp2 = frame_size - (high << 16) - low;
1264: HOST_WIDE_INT extra = 0;
1265: int in_reg = 31;
1266:
1267: /* We haven't written code to handle frames > 4GB. */
1268: #if HOST_BITS_PER_LONG_INT == 64
1269: if ((unsigned HOST_WIDE_INT) frame_size >> 32 != 0)
1270: abort ();
1271: #endif
1272:
1273: if (tmp2)
1274: {
1275: extra = 0x4000;
1276: tmp1 -= 0x40000000;
1277: high = ((tmp1 >> 16) & 0xffff) - 2 * ((tmp1 >> 16) & 0x8000);
1278: }
1279:
1280: if (low != 0)
1281: {
1282: fprintf (file, "\tlda $28,%d($%d)\n", low, in_reg);
1283: in_reg = 28;
1284: }
1285:
1286: if (extra)
1287: {
1288: fprintf (file, "\tldah $28,%d($%d)\n", extra, in_reg);
1289: in_reg = 28;
1290: }
1291:
1292: fprintf (file, "\tldah $28,%d($%d)\n", high, in_reg);
1293:
1294: fprintf (file, "\tsubq $30,$28,$30\n");
1295: }
1296: else if (frame_size)
1297: fprintf (file, "\tlda $30,-%d($30)\n", frame_size);
1298:
1299: /* Write out the .frame line. If we need a frame pointer, we use
1300: an offset of zero. */
1301:
1302: if (frame_pointer_needed)
1303: fprintf (file, "\t.frame $15,0,$26\n");
1304: else
1305: fprintf (file, "\t.frame $30,%d,$26\n", frame_size);
1306:
1307:
1308: /* Save register 26 if it is used. */
1309: if (regs_ever_live[26])
1310: {
1311: reg_mask |= 1 << 26;
1312: fprintf (file, "\tstq $26,%d($30)\n", reg_offset);
1313: reg_offset += 8;
1314: }
1315:
1316: /* Now save any other used register that are required to be saved. */
1317: for (i = 0; i < 32; i++)
1318: if (! fixed_regs[i] && ! call_used_regs[i] && regs_ever_live[i] && i != 26)
1319: {
1320: reg_mask |= 1 << i;
1321: fprintf (file, "\tstq $%d,%d($30)\n", i, reg_offset);
1322: reg_offset += 8;
1323: }
1324:
1325: /* Print the register mask and do floating-point saves. */
1326: if (reg_mask)
1327: fprintf (file, "\t.mask 0x%x,%d\n", reg_mask,
1328: start_reg_offset - frame_size);
1329:
1330: start_reg_offset = reg_offset;
1331: reg_mask = 0;
1332:
1333: for (i = 0; i < 32; i++)
1334: if (! fixed_regs[i + 32] && ! call_used_regs[i + 32]
1335: && regs_ever_live[i + 32])
1336: {
1337: reg_mask |= 1 << i;
1338: fprintf (file, "\tstt $f%d,%d($30)\n", i, reg_offset);
1339: reg_offset += 8;
1340: }
1341:
1342: /* Print the floating-point mask, if we've saved any fp register. */
1343: if (reg_mask)
1344: fprintf (file, "\t.fmask 0x%x,%d\n", reg_mask, start_reg_offset);
1345:
1346: /* If we need a frame pointer, set it to the value of incoming stack
1347: which we compute by adding back the frame size pointer. Because we
1348: can subtract one more than we can add, we have to special-case
1349: frame sizes of 32K. Note that there is no restriction that the frame
1350: pointer be updated in one instruction. */
1351:
1352: if (frame_pointer_needed)
1353: {
1354: if (frame_size == 32768)
1355: fprintf (file, "\tlda $15,16384($30)\n\tlda $15,16384($15)\n");
1356: else if (frame_size > 32768)
1357: fprintf (file, "\taddq $30,$28,$15\n");
1358: else
1359: fprintf (file, "\tlda $15,%d($30)\n", frame_size);
1360: }
1361: }
1362:
1363: /* Write function epilogue. */
1364:
1365: void
1366: output_epilog (file, size)
1367: FILE *file;
1368: int size;
1369: {
1370: rtx insn = get_last_insn ();
1371: HOST_WIDE_INT frame_size = ((size + current_function_outgoing_args_size
1372: + current_function_pretend_args_size
1373: + alpha_sa_size () + 15) & ~15);
1374: int reg_offset = current_function_outgoing_args_size;
1375: int reg_offset_from = STACK_POINTER_REGNUM;
1376: int i;
1377:
1378: /* If the last insn was a BARRIER, we don't have to write anything except
1379: the .end pseudo-op. */
1380: if (GET_CODE (insn) == NOTE)
1381: insn = prev_nonnote_insn (insn);
1382: if (insn == 0 || GET_CODE (insn) != BARRIER)
1383: {
1384: /* If we have a frame pointer, we restore the registers from an
1385: offset from it, assuming that we can reach the offset. If not,
1386: we have to compute the address using a scratch register. This is
1387: messy, but should not be common. We have to copy the frame
1388: pointer elsewhere here since we will be restoring it before we can
1389: use it to restore the stack pointer. We use $25. */
1390:
1391: if (frame_pointer_needed)
1392: {
1393: fprintf (file, "\tbis $15,$15,$25\n");
1394:
1395: if (frame_size < 32768)
1396: reg_offset -= frame_size, reg_offset_from = 25;
1397: else
1398: {
1399: HOST_WIDE_INT low
1400: = (frame_size & 0xffff) - 2 * (frame_size & 0x8000);
1401: HOST_WIDE_INT tmp1 = frame_size - low;
1402: HOST_WIDE_INT high
1403: = ((tmp1 >> 16) & 0xffff) - 2 * ((tmp1 >> 16) & 0x8000);
1404: HOST_WIDE_INT tmp2 = frame_size - (high << 16) - low;
1405: int extra = 0;
1406: int in_reg = 31;
1407:
1408: if (tmp2)
1409: {
1410: extra = 0x4000;
1411: tmp1 -= 0x40000000;
1412: high = ((tmp1 >> 16) & 0xffff) - 2 * ((tmp1 >> 16) & 0x8000);
1413: }
1414:
1415: if (low != 0)
1416: {
1417: fprintf (file, "\tlda $28,%d($%d)\n", low, in_reg);
1418: in_reg = 28;
1419: }
1420:
1421: if (extra)
1422: {
1423: fprintf (file, "\tldah $28,%d($%d)\n", extra, in_reg);
1424: in_reg = 28;
1425: }
1426:
1427: fprintf (file, "\tldah $28,%d($%d)\n", high, in_reg);
1428:
1429: fprintf (file, "\tsubq $25,$28,$28\n");
1430:
1431: reg_offset_from = 28;
1432: }
1433: }
1434:
1435: /* Restore all the registers, starting with the return address
1436: register. */
1437: if (regs_ever_live[26])
1438: {
1439: fprintf (file, "\tldq $26,%d($%d)\n", reg_offset, reg_offset_from);
1440: reg_offset += 8;
1441: }
1442:
1443: /* Now restore any other used register that that we saved. */
1444: for (i = 0; i < 32; i++)
1445: if (! fixed_regs[i] && ! call_used_regs[i] && regs_ever_live[i]
1446: && i != 26)
1447: {
1448: fprintf (file, "\tldq $%d,%d($%d)\n",
1449: i, reg_offset, reg_offset_from);
1450: reg_offset += 8;
1451: }
1452:
1453: for (i = 0; i < 32; i++)
1454: if (! fixed_regs[i + 32] && ! call_used_regs[i + 32]
1455: && regs_ever_live[i + 32])
1456: {
1457: fprintf (file, "\tldt $f%d,%d($%d)\n",
1458: i, reg_offset, reg_offset_from);
1459: reg_offset += 8;
1460: }
1461:
1462: /* Restore the stack. If we have a frame pointer, use it. Otherwise,
1463: add the size back into the stack, handling the large frame size. */
1464:
1465: if (frame_pointer_needed)
1466: fprintf (file, "\tbis $25,$25,$30\n");
1467: else if (frame_size > 32767)
1468: {
1469: HOST_WIDE_INT low
1470: = (frame_size & 0xffff) - 2 * (frame_size & 0x8000);
1471: HOST_WIDE_INT tmp1 = frame_size - low;
1472: HOST_WIDE_INT high
1473: = ((tmp1 >> 16) & 0xffff) - 2 * ((tmp1 >> 16) & 0x8000);
1474: HOST_WIDE_INT tmp2 = frame_size - (high << 16) - low;
1475: HOST_WIDE_INT extra = 0;
1476: int in_reg = 31;
1477:
1478: /* We haven't written code to handle frames > 4GB. */
1479: #if HOST_BITS_PER_LONG_INT == 64
1480: if ((unsigned HOST_WIDE_INT) frame_size >> 32 != 0)
1481: abort ();
1482: #endif
1483:
1484: if (tmp2)
1485: {
1486: extra = 0x4000;
1487: tmp1 -= 0x40000000;
1488: high = ((tmp1 >> 16) & 0xffff) - 2 * ((tmp1 >> 16) & 0x8000);
1489: }
1490:
1491: if (low != 0)
1492: {
1493: fprintf (file, "\tlda $28,%d($%d)\n", low, in_reg);
1494: in_reg = 28;
1495: }
1496:
1497: if (extra)
1498: {
1499: fprintf (file, "\tldah $28,%d($%d)\n", extra, in_reg);
1500: in_reg = 28;
1501: }
1502:
1503: fprintf (file, "\tldah $28,%d($%d)\n", high, in_reg);
1504:
1505: fprintf (file, "\taddq $30,$28,$30\n");
1506: }
1507: else if (frame_size)
1508: fprintf (file, "\tlda $30,%d($30)\n", frame_size);
1509:
1510: /* Now return to the caller. */
1511: fprintf (file, "\tret $31,($26),1\n");
1512: }
1513:
1514: /* End the function. */
1515: fprintf (file, "\t.end %s\n", alpha_function_name);
1516: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.