|
|
1.1 root 1: /* Subroutines for insn-output.c for Sun SPARC.
2: Copyright (C) 1987, 1988, 1989, 1992 Free Software Foundation, Inc.
3: Contributed by Michael Tiemann ([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: #include <stdio.h>
22: #include "config.h"
1.1.1.3 root 23: #include "tree.h"
1.1 root 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 "expr.h"
35: #include "recog.h"
36:
37: /* Global variables for machine-dependent things. */
38:
39: /* Save the operands last given to a compare for use when we
40: generate a scc or bcc insn. */
41:
42: rtx sparc_compare_op0, sparc_compare_op1;
43:
44: /* We may need an epilogue if we spill too many registers.
45: If this is non-zero, then we branch here for the epilogue. */
46: static rtx leaf_label;
47:
48: #ifdef LEAF_REGISTERS
49:
50: /* Vector to say how input registers are mapped to output
51: registers. FRAME_POINTER_REGNUM cannot be remapped by
52: this function to eliminate it. You must use -fomit-frame-pointer
53: to get that. */
54: char leaf_reg_remap[] =
55: { 0, 1, 2, 3, 4, 5, 6, 7,
56: -1, -1, -1, -1, -1, -1, 14, -1,
57: -1, -1, -1, -1, -1, -1, -1, -1,
58: 8, 9, 10, 11, 12, 13, -1, 15,
59:
60: 32, 33, 34, 35, 36, 37, 38, 39,
61: 40, 41, 42, 43, 44, 45, 46, 47,
62: 48, 49, 50, 51, 52, 53, 54, 55,
63: 56, 57, 58, 59, 60, 61, 62, 63};
64:
65: char leaf_reg_backmap[] =
66: { 0, 1, 2, 3, 4, 5, 6, 7,
67: 24, 25, 26, 27, 28, 29, 14, 31,
68: -1, -1, -1, -1, -1, -1, -1, -1,
69: -1, -1, -1, -1, -1, -1, -1, -1,
70:
71: 32, 33, 34, 35, 36, 37, 38, 39,
72: 40, 41, 42, 43, 44, 45, 46, 47,
73: 48, 49, 50, 51, 52, 53, 54, 55,
74: 56, 57, 58, 59, 60, 61, 62, 63};
75: #endif
76:
77: /* Global variables set by FUNCTION_PROLOGUE. */
78: /* Size of frame. Need to know this to emit return insns from
79: leaf procedures. */
80: int apparent_fsize;
81: int actual_fsize;
82:
83: /* Name of where we pretend to think the frame pointer points.
84: Normally, this is "%fp", but if we are in a leaf procedure,
85: this is "%sp+something". */
86: char *frame_base_name;
87:
88: static rtx find_addr_reg ();
89:
90: /* Return non-zero only if OP is a register of mode MODE,
91: or const0_rtx. */
92: int
93: reg_or_0_operand (op, mode)
94: rtx op;
95: enum machine_mode mode;
96: {
97: if (op == const0_rtx || register_operand (op, mode))
98: return 1;
99: if (GET_CODE (op) == CONST_DOUBLE
100: && CONST_DOUBLE_HIGH (op) == 0
101: && CONST_DOUBLE_LOW (op) == 0)
102: return 1;
103: return 0;
104: }
105:
106: /* Nonzero if OP can appear as the dest of a RESTORE insn. */
107: int
108: restore_operand (op, mode)
109: rtx op;
110: enum machine_mode mode;
111: {
112: return (GET_CODE (op) == REG && GET_MODE (op) == mode
113: && (REGNO (op) < 8 || (REGNO (op) >= 24 && REGNO (op) < 32)));
114: }
115:
116: /* PC-relative call insn on SPARC is independent of `memory_operand'. */
117:
118: int
119: call_operand (op, mode)
120: rtx op;
121: enum machine_mode mode;
122: {
123: if (GET_CODE (op) != MEM)
124: abort ();
125: op = XEXP (op, 0);
126: return (REG_P (op) || CONSTANT_P (op));
127: }
128:
129: int
130: call_operand_address (op, mode)
131: rtx op;
132: enum machine_mode mode;
133: {
134: return (REG_P (op) || CONSTANT_P (op));
135: }
136:
137: /* Returns 1 if OP is either a symbol reference or a sum of a symbol
138: reference and a constant. */
139:
140: int
141: symbolic_operand (op, mode)
142: register rtx op;
143: enum machine_mode mode;
144: {
145: switch (GET_CODE (op))
146: {
147: case SYMBOL_REF:
148: case LABEL_REF:
149: return 1;
150:
151: case CONST:
152: op = XEXP (op, 0);
153: return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
154: || GET_CODE (XEXP (op, 0)) == LABEL_REF)
155: && GET_CODE (XEXP (op, 1)) == CONST_INT);
156:
157: /* This clause seems to be irrelevant. */
158: case CONST_DOUBLE:
159: return GET_MODE (op) == mode;
160:
161: default:
162: return 0;
163: }
164: }
165:
166: /* Return truth value of statement that OP is a symbolic memory
167: operand of mode MODE. */
168:
169: int
170: symbolic_memory_operand (op, mode)
171: rtx op;
172: enum machine_mode mode;
173: {
174: if (GET_CODE (op) == SUBREG)
175: op = SUBREG_REG (op);
176: if (GET_CODE (op) != MEM)
177: return 0;
178: op = XEXP (op, 0);
179: return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST
180: || GET_CODE (op) == HIGH || GET_CODE (op) == LABEL_REF);
181: }
182:
183: /* Return 1 if the operand is either a register or a memory operand that is
184: not symbolic. */
185:
186: int
187: reg_or_nonsymb_mem_operand (op, mode)
188: register rtx op;
189: enum machine_mode mode;
190: {
191: if (register_operand (op, mode))
192: return 1;
193:
194: if (memory_operand (op, mode) && ! symbolic_memory_operand (op, mode))
195: return 1;
196:
197: return 0;
198: }
199:
200: int
201: sparc_operand (op, mode)
202: rtx op;
203: enum machine_mode mode;
204: {
205: if (register_operand (op, mode))
206: return 1;
207: if (GET_CODE (op) == CONST_INT)
208: return SMALL_INT (op);
209: if (GET_MODE (op) != mode)
210: return 0;
211: if (GET_CODE (op) == SUBREG)
212: op = SUBREG_REG (op);
213: if (GET_CODE (op) != MEM)
214: return 0;
215:
216: op = XEXP (op, 0);
217: if (GET_CODE (op) == LO_SUM)
218: return (GET_CODE (XEXP (op, 0)) == REG
219: && symbolic_operand (XEXP (op, 1), Pmode));
220: return memory_address_p (mode, op);
221: }
222:
223: int
224: move_operand (op, mode)
225: rtx op;
226: enum machine_mode mode;
227: {
228: if (mode == DImode && arith_double_operand (op, mode))
229: return 1;
230: if (register_operand (op, mode))
231: return 1;
232: if (GET_CODE (op) == CONST_INT)
233: return (SMALL_INT (op) || (INTVAL (op) & 0x3ff) == 0);
234:
235: if (GET_MODE (op) != mode)
236: return 0;
237: if (GET_CODE (op) == SUBREG)
238: op = SUBREG_REG (op);
239: if (GET_CODE (op) != MEM)
240: return 0;
241: op = XEXP (op, 0);
242: if (GET_CODE (op) == LO_SUM)
243: return (register_operand (XEXP (op, 0), Pmode)
244: && CONSTANT_P (XEXP (op, 1)));
245: return memory_address_p (mode, op);
246: }
247:
248: int
249: move_pic_label (op, mode)
250: rtx op;
251: enum machine_mode mode;
252: {
253: /* Special case for PIC. */
254: if (flag_pic && GET_CODE (op) == LABEL_REF)
255: return 1;
256: return 0;
257: }
258:
259: /* The rtx for the global offset table which is a special form
260: that *is* a position independent symbolic constant. */
261: rtx pic_pc_rtx;
262:
263: /* Ensure that we are not using patterns that are not OK with PIC. */
264:
265: int
266: check_pic (i)
267: int i;
268: {
269: switch (flag_pic)
270: {
271: case 1:
272: if (GET_CODE (recog_operand[i]) == SYMBOL_REF
273: || (GET_CODE (recog_operand[i]) == CONST
274: && ! rtx_equal_p (pic_pc_rtx, recog_operand[i])))
275: abort ();
276: case 2:
277: default:
278: return 1;
279: }
280: }
281:
282: /* Return true if X is an address which needs a temporary register when
283: reloaded while generating PIC code. */
284:
285: int
286: pic_address_needs_scratch (x)
287: rtx x;
288: {
289: /* An address which is a symbolic plus a non SMALL_INT needs a temp reg. */
290: if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS
291: && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
292: && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
293: && ! SMALL_INT (XEXP (XEXP (x, 0), 1)))
294: return 1;
295:
296: return 0;
297: }
298:
299: int
300: memop (op, mode)
301: rtx op;
302: enum machine_mode mode;
303: {
304: if (GET_CODE (op) == MEM)
305: return (mode == VOIDmode || mode == GET_MODE (op));
306: return 0;
307: }
308:
309: /* Return truth value of whether OP is EQ or NE. */
310:
311: int
312: eq_or_neq (op, mode)
313: rtx op;
314: enum machine_mode mode;
315: {
316: return (GET_CODE (op) == EQ || GET_CODE (op) == NE);
317: }
318:
319: /* Return 1 if this is a comparison operator, but not an EQ, NE, GEU,
320: or LTU for non-floating-point. We handle those specially. */
321:
322: int
323: normal_comp_operator (op, mode)
324: rtx op;
325: enum machine_mode mode;
326: {
327: enum rtx_code code = GET_CODE (op);
328:
329: if (GET_RTX_CLASS (code) != '<')
330: return 0;
331:
1.1.1.3 root 332: if (GET_MODE (XEXP (op, 0)) == CCFPmode
333: || GET_MODE (XEXP (op, 0)) == CCFPEmode)
1.1 root 334: return 1;
335:
336: return (code != NE && code != EQ && code != GEU && code != LTU);
337: }
338:
339: /* Return 1 if this is a comparison operator. This allows the use of
340: MATCH_OPERATOR to recognize all the branch insns. */
341:
342: int
343: noov_compare_op (op, mode)
344: register rtx op;
345: enum machine_mode mode;
346: {
347: enum rtx_code code = GET_CODE (op);
348:
349: if (GET_RTX_CLASS (code) != '<')
350: return 0;
351:
352: if (GET_MODE (XEXP (op, 0)) == CC_NOOVmode)
353: /* These are the only branches which work with CC_NOOVmode. */
354: return (code == EQ || code == NE || code == GE || code == LT);
355: return 1;
356: }
357:
358: /* Return 1 if this is a SIGN_EXTEND or ZERO_EXTEND operation. */
359:
360: int
361: extend_op (op, mode)
362: rtx op;
363: enum machine_mode mode;
364: {
365: return GET_CODE (op) == SIGN_EXTEND || GET_CODE (op) == ZERO_EXTEND;
366: }
367:
368: /* Return nonzero if OP is an operator of mode MODE which can set
369: the condition codes explicitly. We do not include PLUS and MINUS
370: because these require CC_NOOVmode, which we handle explicitly. */
371:
372: int
373: cc_arithop (op, mode)
374: rtx op;
375: enum machine_mode mode;
376: {
377: if (GET_CODE (op) == AND
378: || GET_CODE (op) == IOR
379: || GET_CODE (op) == XOR)
380: return 1;
381:
382: return 0;
383: }
384:
385: /* Return nonzero if OP is an operator of mode MODE which can bitwise
386: complement its second operand and set the condition codes explicitly. */
387:
388: int
389: cc_arithopn (op, mode)
390: rtx op;
391: enum machine_mode mode;
392: {
393: /* XOR is not here because combine canonicalizes (xor (not ...) ...)
394: and (xor ... (not ...)) to (not (xor ...)). */
395: return (GET_CODE (op) == AND
396: || GET_CODE (op) == IOR);
397: }
398:
399: /* Return truth value of whether OP can be used as an operands in a three
400: address arithmetic insn (such as add %o1,7,%l2) of mode MODE. */
401:
402: int
403: arith_operand (op, mode)
404: rtx op;
405: enum machine_mode mode;
406: {
407: return (register_operand (op, mode)
408: || (GET_CODE (op) == CONST_INT && SMALL_INT (op)));
409: }
410:
411: /* Return truth value of whether OP is a register or a CONST_DOUBLE. */
412:
413: int
414: arith_double_operand (op, mode)
415: rtx op;
416: enum machine_mode mode;
417: {
418: return (register_operand (op, mode)
419: || (GET_CODE (op) == CONST_DOUBLE
420: && (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
421: && (unsigned) (CONST_DOUBLE_LOW (op) + 0x1000) < 0x2000
422: && ((CONST_DOUBLE_HIGH (op) == -1
423: && (CONST_DOUBLE_LOW (op) & 0x1000) == 0x1000)
424: || (CONST_DOUBLE_HIGH (op) == 0
425: && (CONST_DOUBLE_LOW (op) & 0x1000) == 0)))
426: || (GET_CODE (op) == CONST_INT
427: && (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
428: && (unsigned) (INTVAL (op) + 0x1000) < 0x2000));
429: }
430:
431: /* Return truth value of whether OP is a integer which fits the
432: range constraining immediate operands in three-address insns. */
433:
434: int
435: small_int (op, mode)
436: rtx op;
437: enum machine_mode mode;
438: {
439: return (GET_CODE (op) == CONST_INT && SMALL_INT (op));
440: }
441:
442: /* Return truth value of statement that OP is a call-clobbered register. */
443: int
444: clobbered_register (op, mode)
445: rtx op;
446: enum machine_mode mode;
447: {
448: return (GET_CODE (op) == REG && call_used_regs[REGNO (op)]);
449: }
450:
451: /* X and Y are two things to compare using CODE. Emit the compare insn and
452: return the rtx for register 0 in the proper mode. */
453:
454: rtx
455: gen_compare_reg (code, x, y)
456: enum rtx_code code;
457: rtx x, y;
458: {
1.1.1.4 ! root 459: enum machine_mode mode = SELECT_CC_MODE (code, x, y);
1.1 root 460: rtx cc_reg = gen_rtx (REG, mode, 0);
461:
462: emit_insn (gen_rtx (SET, VOIDmode, cc_reg,
463: gen_rtx (COMPARE, mode, x, y)));
464:
465: return cc_reg;
466: }
467:
468: /* Return nonzero if a return peephole merging return with
469: setting of output register is ok. */
470: int
471: leaf_return_peephole_ok ()
472: {
473: return (actual_fsize == 0);
474: }
475:
476: /* Return nonzero if TRIAL can go into the function epilogue's
477: delay slot. SLOT is the slot we are trying to fill. */
478:
479: int
480: eligible_for_epilogue_delay (trial, slot)
481: rtx trial;
482: int slot;
483: {
484: static char *this_function_name;
485: rtx pat, src;
486:
487: if (slot >= 1)
488: return 0;
489: if (GET_CODE (trial) != INSN
490: || GET_CODE (PATTERN (trial)) != SET)
491: return 0;
492: if (get_attr_length (trial) != 1)
493: return 0;
494:
1.1.1.3 root 495: /* In the case of a true leaf function, anything can go into the delay slot.
496: A delay slot only exists however if the frame size is zero, otherwise
497: we will put an insn to adjust the stack after the return. */
1.1 root 498: if (leaf_function)
499: {
500: if (leaf_return_peephole_ok ())
1.1.1.4 ! root 501: return (get_attr_in_uncond_branch_delay (trial) == IN_BRANCH_DELAY_TRUE);
1.1 root 502: return 0;
503: }
504:
505: /* Otherwise, only operations which can be done in tandem with
506: a `restore' insn can go into the delay slot. */
507: pat = PATTERN (trial);
508: if (GET_CODE (SET_DEST (pat)) != REG
509: || REGNO (SET_DEST (pat)) == 0
1.1.1.3 root 510: || REGNO (SET_DEST (pat)) >= 32
511: || REGNO (SET_DEST (pat)) < 24)
1.1 root 512: return 0;
1.1.1.3 root 513:
1.1 root 514: src = SET_SRC (pat);
515: if (arith_operand (src, GET_MODE (src)))
516: return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (SImode);
517: if (arith_double_operand (src, GET_MODE (src)))
518: return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (DImode);
519: if (GET_CODE (src) == PLUS)
520: {
521: if (register_operand (XEXP (src, 0), SImode)
522: && arith_operand (XEXP (src, 1), SImode))
523: return 1;
524: if (register_operand (XEXP (src, 1), SImode)
525: && arith_operand (XEXP (src, 0), SImode))
526: return 1;
527: if (register_operand (XEXP (src, 0), DImode)
528: && arith_double_operand (XEXP (src, 1), DImode))
529: return 1;
530: if (register_operand (XEXP (src, 1), DImode)
531: && arith_double_operand (XEXP (src, 0), DImode))
532: return 1;
533: }
534: if (GET_CODE (src) == MINUS
535: && register_operand (XEXP (src, 0), SImode)
536: && small_int (XEXP (src, 1), VOIDmode))
537: return 1;
538: if (GET_CODE (src) == MINUS
539: && register_operand (XEXP (src, 0), DImode)
540: && !register_operand (XEXP (src, 1), DImode)
541: && arith_double_operand (XEXP (src, 1), DImode))
542: return 1;
543: return 0;
544: }
545:
546: int
547: short_branch (uid1, uid2)
548: int uid1, uid2;
549: {
550: unsigned int delta = insn_addresses[uid1] - insn_addresses[uid2];
551: if (delta + 1024 < 2048)
552: return 1;
553: /* warning ("long branch, distance %d", delta); */
554: return 0;
555: }
556:
557: /* Return non-zero if REG is not used after INSN.
558: We assume REG is a reload reg, and therefore does
559: not live past labels or calls or jumps. */
560: int
561: reg_unused_after (reg, insn)
562: rtx reg;
563: rtx insn;
564: {
565: enum rtx_code code, prev_code = UNKNOWN;
566:
567: while (insn = NEXT_INSN (insn))
568: {
569: if (prev_code == CALL_INSN && call_used_regs[REGNO (reg)])
570: return 1;
571:
572: code = GET_CODE (insn);
573: if (GET_CODE (insn) == CODE_LABEL)
574: return 1;
575:
576: if (GET_RTX_CLASS (code) == 'i')
577: {
578: rtx set = single_set (insn);
579: int in_src = set && reg_overlap_mentioned_p (reg, SET_SRC (set));
580: if (set && in_src)
581: return 0;
582: if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
583: return 1;
584: if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
585: return 0;
586: }
587: prev_code = code;
588: }
589: return 1;
590: }
591:
592: /* Legitimize PIC addresses. If the address is already position-independent,
593: we return ORIG. Newly generated position-independent addresses go into a
594: reg. This is REG if non zero, otherwise we allocate register(s) as
595: necessary. If this is called during reload, and we need a second temp
596: register, then we use SCRATCH, which is provided via the
597: SECONDARY_INPUT_RELOAD_CLASS mechanism. */
598:
599: rtx
600: legitimize_pic_address (orig, mode, reg, scratch)
601: rtx orig;
602: enum machine_mode mode;
603: rtx reg, scratch;
604: {
605: if (GET_CODE (orig) == SYMBOL_REF)
606: {
607: rtx pic_ref, address;
608: rtx insn;
609:
610: if (reg == 0)
611: {
1.1.1.2 root 612: if (reload_in_progress || reload_completed)
1.1 root 613: abort ();
614: else
615: reg = gen_reg_rtx (Pmode);
616: }
617:
618: if (flag_pic == 2)
619: {
620: /* If not during reload, allocate another temp reg here for loading
621: in the address, so that these instructions can be optimized
622: properly. */
1.1.1.2 root 623: rtx temp_reg = ((reload_in_progress || reload_completed)
624: ? reg : gen_reg_rtx (Pmode));
1.1 root 625:
1.1.1.2 root 626: /* Must put the SYMBOL_REF inside an UNSPEC here so that cse
627: won't get confused into thinking that these two instructions
628: are loading in the true address of the symbol. If in the
629: future a PIC rtx exists, that should be used instead. */
1.1 root 630: emit_insn (gen_rtx (SET, VOIDmode, temp_reg,
1.1.1.2 root 631: gen_rtx (HIGH, Pmode,
632: gen_rtx (UNSPEC, Pmode,
633: gen_rtvec (1, orig),
634: 0))));
1.1 root 635: emit_insn (gen_rtx (SET, VOIDmode, temp_reg,
1.1.1.2 root 636: gen_rtx (LO_SUM, Pmode, temp_reg,
637: gen_rtx (UNSPEC, Pmode,
638: gen_rtvec (1, orig),
639: 0))));
1.1 root 640: address = temp_reg;
641: }
642: else
643: address = orig;
644:
645: pic_ref = gen_rtx (MEM, Pmode,
646: gen_rtx (PLUS, Pmode,
647: pic_offset_table_rtx, address));
648: current_function_uses_pic_offset_table = 1;
649: RTX_UNCHANGING_P (pic_ref) = 1;
650: insn = emit_move_insn (reg, pic_ref);
651: /* Put a REG_EQUAL note on this insn, so that it can be optimized
652: by loop. */
653: REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL, orig,
654: REG_NOTES (insn));
655: return reg;
656: }
657: else if (GET_CODE (orig) == CONST)
658: {
659: rtx base, offset;
660:
661: if (GET_CODE (XEXP (orig, 0)) == PLUS
662: && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
663: return orig;
664:
665: if (reg == 0)
666: {
1.1.1.2 root 667: if (reload_in_progress || reload_completed)
1.1 root 668: abort ();
669: else
670: reg = gen_reg_rtx (Pmode);
671: }
672:
673: if (GET_CODE (XEXP (orig, 0)) == PLUS)
674: {
675: base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode,
676: reg, 0);
677: offset = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
678: base == reg ? 0 : reg, 0);
679: }
680: else
681: abort ();
682:
683: if (GET_CODE (offset) == CONST_INT)
684: {
685: if (SMALL_INT (offset))
686: return plus_constant_for_output (base, INTVAL (offset));
1.1.1.2 root 687: else if (! reload_in_progress && ! reload_completed)
1.1 root 688: offset = force_reg (Pmode, offset);
689: /* We can't create any new registers during reload, so use the
690: SCRATCH reg provided by the reload_insi pattern. */
691: else if (scratch)
692: {
693: emit_move_insn (scratch, offset);
694: offset = scratch;
695: }
696: else
697: /* If we reach here, then the SECONDARY_INPUT_RELOAD_CLASS
698: macro needs to be adjusted so that a scratch reg is provided
699: for this address. */
700: abort ();
701: }
702: return gen_rtx (PLUS, Pmode, base, offset);
703: }
704: else if (GET_CODE (orig) == LABEL_REF)
705: current_function_uses_pic_offset_table = 1;
706:
707: return orig;
708: }
709:
710: /* Set up PIC-specific rtl. This should not cause any insns
711: to be emitted. */
712:
713: void
714: initialize_pic ()
715: {
716: }
717:
718: /* Emit special PIC prologues and epilogues. */
719:
720: void
721: finalize_pic ()
722: {
723: /* The table we use to reference PIC data. */
724: rtx global_offset_table;
725: /* Labels to get the PC in the prologue of this function. */
726: rtx l1, l2;
727: rtx seq;
728: int orig_flag_pic = flag_pic;
729:
730: if (current_function_uses_pic_offset_table == 0)
731: return;
732:
733: if (! flag_pic)
734: abort ();
735:
736: flag_pic = 0;
737: l1 = gen_label_rtx ();
738: l2 = gen_label_rtx ();
739:
740: start_sequence ();
741:
742: emit_label (l1);
743: /* Note that we pun calls and jumps here! */
744: emit_jump_insn (gen_rtx (PARALLEL, VOIDmode,
745: gen_rtvec (2,
746: gen_rtx (SET, VOIDmode, pc_rtx, gen_rtx (LABEL_REF, VOIDmode, l2)),
747: gen_rtx (SET, VOIDmode, gen_rtx (REG, SImode, 15), gen_rtx (LABEL_REF, VOIDmode, l2)))));
748: emit_label (l2);
749:
750: /* Initialize every time through, since we can't easily
751: know this to be permanent. */
1.1.1.4 ! root 752: global_offset_table = gen_rtx (SYMBOL_REF, Pmode, "_GLOBAL_OFFSET_TABLE_");
1.1 root 753: pic_pc_rtx = gen_rtx (CONST, Pmode,
754: gen_rtx (MINUS, Pmode,
755: global_offset_table,
756: gen_rtx (CONST, Pmode,
757: gen_rtx (MINUS, Pmode,
758: gen_rtx (LABEL_REF, VOIDmode, l1),
759: pc_rtx))));
760:
761: emit_insn (gen_rtx (SET, VOIDmode, pic_offset_table_rtx,
762: gen_rtx (HIGH, Pmode, pic_pc_rtx)));
763: emit_insn (gen_rtx (SET, VOIDmode,
764: pic_offset_table_rtx,
765: gen_rtx (LO_SUM, Pmode,
766: pic_offset_table_rtx, pic_pc_rtx)));
767: emit_insn (gen_rtx (SET, VOIDmode,
768: pic_offset_table_rtx,
769: gen_rtx (PLUS, Pmode,
770: pic_offset_table_rtx, gen_rtx (REG, Pmode, 15))));
771: /* emit_insn (gen_rtx (ASM_INPUT, VOIDmode, "!#PROLOGUE# 1")); */
772: LABEL_PRESERVE_P (l1) = 1;
773: LABEL_PRESERVE_P (l2) = 1;
774: flag_pic = orig_flag_pic;
775:
776: seq = gen_sequence ();
777: end_sequence ();
778: emit_insn_after (seq, get_insns ());
779:
780: /* Need to emit this whether or not we obey regdecls,
781: since setjmp/longjmp can cause life info to screw up. */
782: emit_insn (gen_rtx (USE, VOIDmode, pic_offset_table_rtx));
783: }
784:
785: /* For the SPARC, REG and REG+CONST is cost 0, REG+REG is cost 1,
786: and addresses involving symbolic constants are cost 2.
787:
788: We make REG+REG slightly more expensive because it might keep
789: a register live for longer than we might like.
790:
791: PIC addresses are very expensive.
792:
793: It is no coincidence that this has the same structure
794: as GO_IF_LEGITIMATE_ADDRESS. */
795: int
796: sparc_address_cost (X)
797: rtx X;
798: {
799: #if 0
800: /* Handled before calling here. */
801: if (GET_CODE (X) == REG)
802: { return 1; }
803: #endif
804: if (GET_CODE (X) == PLUS)
805: {
806: if (GET_CODE (XEXP (X, 0)) == REG
807: && GET_CODE (XEXP (X, 1)) == REG)
808: return 2;
809: return 1;
810: }
811: else if (GET_CODE (X) == LO_SUM)
812: return 1;
813: else if (GET_CODE (X) == HIGH)
814: return 2;
815: return 4;
816: }
817:
818: /* Emit insns to move operands[1] into operands[0].
819:
820: Return 1 if we have written out everything that needs to be done to
821: do the move. Otherwise, return 0 and the caller will emit the move
822: normally.
823:
824: SCRATCH_REG if non zero can be used as a scratch register for the move
825: operation. It is provided by a SECONDARY_RELOAD_* macro if needed. */
826:
827: int
828: emit_move_sequence (operands, mode, scratch_reg)
829: rtx *operands;
830: enum machine_mode mode;
831: rtx scratch_reg;
832: {
833: register rtx operand0 = operands[0];
834: register rtx operand1 = operands[1];
835:
836: /* Handle most common case first: storing into a register. */
837: if (register_operand (operand0, mode))
838: {
839: if (register_operand (operand1, mode)
840: || (GET_CODE (operand1) == CONST_INT && SMALL_INT (operand1))
841: || (GET_CODE (operand1) == CONST_DOUBLE
842: && arith_double_operand (operand1, DImode))
843: || (GET_CODE (operand1) == HIGH && GET_MODE (operand1) != DImode)
844: /* Only `general_operands' can come here, so MEM is ok. */
845: || GET_CODE (operand1) == MEM)
846: {
847: /* Run this case quickly. */
848: emit_insn (gen_rtx (SET, VOIDmode, operand0, operand1));
849: return 1;
850: }
851: }
852: else if (GET_CODE (operand0) == MEM)
853: {
854: if (register_operand (operand1, mode) || operand1 == const0_rtx)
855: {
856: /* Run this case quickly. */
857: emit_insn (gen_rtx (SET, VOIDmode, operand0, operand1));
858: return 1;
859: }
860: if (! reload_in_progress)
861: {
862: operands[0] = validize_mem (operand0);
863: operands[1] = operand1 = force_reg (mode, operand1);
864: }
865: }
866:
867: /* Simplify the source if we need to. Must handle DImode HIGH operators
868: here because such a move needs a clobber added. */
869: if ((GET_CODE (operand1) != HIGH && immediate_operand (operand1, mode))
870: || (GET_CODE (operand1) == HIGH && GET_MODE (operand1) == DImode))
871: {
872: if (flag_pic && symbolic_operand (operand1, mode))
873: {
874: rtx temp_reg = reload_in_progress ? operand0 : 0;
875:
876: operands[1] = legitimize_pic_address (operand1, mode, temp_reg,
877: scratch_reg);
878: }
879: else if (GET_CODE (operand1) == CONST_INT
880: ? (! SMALL_INT (operand1)
881: && (INTVAL (operand1) & 0x3ff) != 0)
882: : (GET_CODE (operand1) == CONST_DOUBLE
883: ? ! arith_double_operand (operand1, DImode)
884: : 1))
885: {
886: /* For DImode values, temp must be operand0 because of the way
887: HI and LO_SUM work. The LO_SUM operator only copies half of
888: the LSW from the dest of the HI operator. If the LO_SUM dest is
889: not the same as the HI dest, then the MSW of the LO_SUM dest will
890: never be set.
891:
892: ??? The real problem here is that the ...(HI:DImode pattern emits
893: multiple instructions, and the ...(LO_SUM:DImode pattern emits
894: one instruction. This fails, because the compiler assumes that
895: LO_SUM copies all bits of the first operand to its dest. Better
896: would be to have the HI pattern emit one instruction and the
897: LO_SUM pattern multiple instructions. Even better would be
898: to use four rtl insns. */
899: rtx temp = ((reload_in_progress || mode == DImode)
900: ? operand0 : gen_reg_rtx (mode));
901:
902: emit_insn (gen_rtx (SET, VOIDmode, temp,
903: gen_rtx (HIGH, mode, operand1)));
904: operands[1] = gen_rtx (LO_SUM, mode, temp, operand1);
905: }
906: }
907:
908: if (GET_CODE (operand1) == LABEL_REF && flag_pic)
909: {
910: /* The procedure for doing this involves using a call instruction to
911: get the pc into o7. We need to indicate this explicitly because
912: the tablejump pattern assumes that it can use this value also. */
913: emit_insn (gen_rtx (PARALLEL, VOIDmode,
914: gen_rtvec (2,
915: gen_rtx (SET, VOIDmode, operand0,
916: operand1),
917: gen_rtx (SET, VOIDmode,
918: gen_rtx (REG, mode, 15),
919: pc_rtx))));
920: return 1;
921: }
922:
923: /* Now have insn-emit do whatever it normally does. */
924: return 0;
925: }
926:
927: /* Return the best assembler insn template
928: for moving operands[1] into operands[0] as a fullword. */
929:
930: char *
931: singlemove_string (operands)
932: rtx *operands;
933: {
934: if (GET_CODE (operands[0]) == MEM)
935: {
936: if (GET_CODE (operands[1]) != MEM)
937: return "st %r1,%0";
938: else
939: abort ();
940: }
1.1.1.3 root 941: else if (GET_CODE (operands[1]) == MEM)
1.1 root 942: return "ld %1,%0";
1.1.1.3 root 943: else if (GET_CODE (operands[1]) == CONST_DOUBLE)
944: {
945: int i;
946: union real_extract u;
947: union float_extract { float f; int i; } v;
948:
949: /* Must be SFmode, otherwise this doesn't make sense. */
950: if (GET_MODE (operands[1]) != SFmode)
951: abort ();
952:
953: bcopy (&CONST_DOUBLE_LOW (operands[1]), &u, sizeof u);
954: v.f = REAL_VALUE_TRUNCATE (SFmode, u.d);
955: i = v.i;
956:
957: operands[1] = gen_rtx (CONST_INT, VOIDmode, i);
958:
959: if (CONST_OK_FOR_LETTER_P (i, 'I'))
960: return "mov %1,%0";
961: else if ((i & 0x000003FF) != 0)
962: return "sethi %%hi(%a1),%0\n\tor %0,%%lo(%a1),%0";
963: else
964: return "sethi %%hi(%a1),%0";
965: }
966: else if (GET_CODE (operands[1]) == CONST_INT
967: && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
1.1 root 968: {
969: int i = INTVAL (operands[1]);
970:
1.1.1.3 root 971: /* If all low order 10 bits are clear, then we only need a single
1.1 root 972: sethi insn to load the constant. */
1.1.1.3 root 973: if ((i & 0x000003FF) != 0)
1.1 root 974: return "sethi %%hi(%a1),%0\n\tor %0,%%lo(%a1),%0";
975: else
976: return "sethi %%hi(%a1),%0";
977: }
1.1.1.3 root 978: /* Operand 1 must be a register, or a 'I' type CONST_INT. */
1.1 root 979: return "mov %1,%0";
980: }
981:
1.1.1.3 root 982: /* Return non-zero if it is OK to assume that the given memory operand is
983: aligned at least to a 8-byte boundary. This should only be called
984: for memory accesses whose size is 8 bytes or larger. */
985:
1.1.1.4 ! root 986: int
1.1.1.3 root 987: mem_aligned_8 (mem)
988: register rtx mem;
989: {
990: register rtx addr;
991: register rtx base;
992: register rtx offset;
993:
994: if (GET_CODE (mem) != MEM)
1.1.1.4 ! root 995: return 0; /* It's gotta be a MEM! */
1.1.1.3 root 996:
997: addr = XEXP (mem, 0);
998:
999: #if 1
1000: /* Now that all misaligned double parms are copied on function entry,
1001: we can assume any 64-bit object is 64-bit aligned. */
1002:
1003: /* See what register we use in the address. */
1004: base = 0;
1005: if (GET_CODE (addr) == PLUS)
1006: {
1007: if (GET_CODE (XEXP (addr, 0)) == REG
1008: && GET_CODE (XEXP (addr, 1)) == CONST_INT)
1009: {
1010: base = XEXP (addr, 0);
1011: offset = XEXP (addr, 1);
1012: }
1013: }
1014: else if (GET_CODE (addr) == REG)
1015: {
1016: base = addr;
1017: offset = const0_rtx;
1018: }
1019:
1020: /* If it's the stack or frame pointer, check offset alignment.
1.1.1.4 ! root 1021: We can have improper alignment in the function entry code. */
1.1.1.3 root 1022: if (base
1023: && (REGNO (base) == FRAME_POINTER_REGNUM
1024: || REGNO (base) == STACK_POINTER_REGNUM))
1025: {
1026: if ((INTVAL (offset) & 0x7) == 0)
1027: return 1;
1028: }
1029: else
1030: /* Anything else, we know is properly aligned. */
1031: return 1;
1032: #else
1033: /* If the operand is known to have been allocated in static storage, then
1034: it must be aligned. */
1035:
1036: if (CONSTANT_P (addr) || GET_CODE (addr) == LO_SUM)
1037: return 1;
1038:
1039: base = 0;
1040: if (GET_CODE (addr) == PLUS)
1041: {
1042: if (GET_CODE (XEXP (addr, 0)) == REG
1043: && GET_CODE (XEXP (addr, 1)) == CONST_INT)
1044: {
1045: base = XEXP (addr, 0);
1046: offset = XEXP (addr, 1);
1047: }
1048: }
1049: else if (GET_CODE (addr) == REG)
1050: {
1051: base = addr;
1052: offset = const0_rtx;
1053: }
1054:
1055: /* Trust round enough offsets from the stack or frame pointer.
1056: If TARGET_HOPE_ALIGN, trust round enough offset from any register.
1057: If it is obviously unaligned, don't ever return true. */
1058: if (base
1059: && (REGNO (base) == FRAME_POINTER_REGNUM
1060: || REGNO (base) == STACK_POINTER_REGNUM
1061: || TARGET_HOPE_ALIGN))
1062: {
1063: if ((INTVAL (offset) & 0x7) == 0)
1064: return 1;
1065: }
1066: /* Otherwise, we can assume that an access is aligned if it is to an
1067: aggregate. Also, if TARGET_HOPE_ALIGN, then assume everything that isn't
1068: obviously unaligned is aligned. */
1069: else if (MEM_IN_STRUCT_P (mem) || TARGET_HOPE_ALIGN)
1070: return 1;
1071: #endif
1072:
1073: /* An obviously unaligned address. */
1074: return 0;
1075: }
1076:
1077: enum optype { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP };
1078:
1.1 root 1079: /* Output assembler code to perform a doubleword move insn
1.1.1.3 root 1080: with operands OPERANDS. This is very similar to the following
1081: output_move_quad function. */
1.1 root 1082:
1083: char *
1084: output_move_double (operands)
1085: rtx *operands;
1086: {
1.1.1.3 root 1087: register rtx op0 = operands[0];
1088: register rtx op1 = operands[1];
1089: register enum optype optype0;
1090: register enum optype optype1;
1.1 root 1091: rtx latehalf[2];
1.1.1.3 root 1092: rtx addreg0 = 0;
1093: rtx addreg1 = 0;
1.1 root 1094:
1095: /* First classify both operands. */
1096:
1.1.1.3 root 1097: if (REG_P (op0))
1.1 root 1098: optype0 = REGOP;
1.1.1.3 root 1099: else if (offsettable_memref_p (op0))
1.1 root 1100: optype0 = OFFSOP;
1.1.1.3 root 1101: else if (GET_CODE (op0) == MEM)
1.1 root 1102: optype0 = MEMOP;
1103: else
1104: optype0 = RNDOP;
1105:
1.1.1.3 root 1106: if (REG_P (op1))
1.1 root 1107: optype1 = REGOP;
1.1.1.3 root 1108: else if (CONSTANT_P (op1))
1.1 root 1109: optype1 = CNSTOP;
1.1.1.3 root 1110: else if (offsettable_memref_p (op1))
1.1 root 1111: optype1 = OFFSOP;
1.1.1.3 root 1112: else if (GET_CODE (op1) == MEM)
1.1 root 1113: optype1 = MEMOP;
1114: else
1115: optype1 = RNDOP;
1116:
1117: /* Check for the cases that the operand constraints are not
1118: supposed to allow to happen. Abort if we get one,
1119: because generating code for these cases is painful. */
1120:
1.1.1.3 root 1121: if (optype0 == RNDOP || optype1 == RNDOP
1122: || (optype0 == MEM && optype1 == MEM))
1.1 root 1123: abort ();
1124:
1125: /* If an operand is an unoffsettable memory ref, find a register
1126: we can increment temporarily to make it refer to the second word. */
1127:
1128: if (optype0 == MEMOP)
1.1.1.3 root 1129: addreg0 = find_addr_reg (XEXP (op0, 0));
1.1 root 1130:
1131: if (optype1 == MEMOP)
1.1.1.3 root 1132: addreg1 = find_addr_reg (XEXP (op1, 0));
1.1 root 1133:
1134: /* Ok, we can do one word at a time.
1.1.1.3 root 1135: Set up in LATEHALF the operands to use for the
1.1 root 1136: high-numbered (least significant) word and in some cases alter the
1137: operands in OPERANDS to be suitable for the low-numbered word. */
1138:
1139: if (optype0 == REGOP)
1.1.1.3 root 1140: latehalf[0] = gen_rtx (REG, SImode, REGNO (op0) + 1);
1.1 root 1141: else if (optype0 == OFFSOP)
1.1.1.3 root 1142: latehalf[0] = adj_offsettable_operand (op0, 4);
1.1 root 1143: else
1.1.1.3 root 1144: latehalf[0] = op0;
1.1 root 1145:
1146: if (optype1 == REGOP)
1.1.1.3 root 1147: latehalf[1] = gen_rtx (REG, SImode, REGNO (op1) + 1);
1.1 root 1148: else if (optype1 == OFFSOP)
1.1.1.3 root 1149: latehalf[1] = adj_offsettable_operand (op1, 4);
1.1 root 1150: else if (optype1 == CNSTOP)
1.1.1.3 root 1151: split_double (op1, &operands[1], &latehalf[1]);
1.1 root 1152: else
1.1.1.3 root 1153: latehalf[1] = op1;
1.1 root 1154:
1.1.1.3 root 1155: /* Easy case: try moving both words at once. Check for moving between
1156: an even/odd register pair and a memory location. */
1.1 root 1157: if ((optype0 == REGOP && optype1 != REGOP && optype1 != CNSTOP
1.1.1.3 root 1158: && (REGNO (op0) & 1) == 0)
1.1 root 1159: || (optype0 != REGOP && optype0 != CNSTOP && optype1 == REGOP
1.1.1.3 root 1160: && (REGNO (op1) & 1) == 0))
1.1 root 1161: {
1.1.1.3 root 1162: register rtx mem;
1.1 root 1163:
1164: if (optype0 == REGOP)
1.1.1.3 root 1165: mem = op1;
1.1 root 1166: else
1.1.1.3 root 1167: mem = op0;
1.1 root 1168:
1.1.1.3 root 1169: if (mem_aligned_8 (mem))
1170: return (mem == op1 ? "ldd %1,%0" : "std %1,%0");
1.1 root 1171: }
1172:
1.1.1.3 root 1173: /* If the first move would clobber the source of the second one,
1174: do them in the other order. */
1175:
1176: /* Overlapping registers. */
1.1 root 1177: if (optype0 == REGOP && optype1 == REGOP
1.1.1.3 root 1178: && REGNO (op0) == REGNO (latehalf[1]))
1.1 root 1179: {
1180: /* Do that word. */
1181: output_asm_insn (singlemove_string (latehalf), latehalf);
1182: /* Do low-numbered word. */
1183: return singlemove_string (operands);
1184: }
1.1.1.3 root 1185: /* Loading into a register which overlaps a register used in the address. */
1.1 root 1186: else if (optype0 == REGOP && optype1 != REGOP
1.1.1.3 root 1187: && reg_overlap_mentioned_p (op0, op1))
1.1 root 1188: {
1.1.1.3 root 1189: /* ??? This fails if the address is a double register address, each
1190: of which is clobbered by operand 0. */
1.1 root 1191: /* Do the late half first. */
1192: output_asm_insn (singlemove_string (latehalf), latehalf);
1193: /* Then clobber. */
1194: return singlemove_string (operands);
1195: }
1196:
1197: /* Normal case: do the two words, low-numbered first. */
1198:
1199: output_asm_insn (singlemove_string (operands), operands);
1200:
1201: /* Make any unoffsettable addresses point at high-numbered word. */
1202: if (addreg0)
1203: output_asm_insn ("add %0,0x4,%0", &addreg0);
1204: if (addreg1)
1205: output_asm_insn ("add %0,0x4,%0", &addreg1);
1206:
1207: /* Do that word. */
1208: output_asm_insn (singlemove_string (latehalf), latehalf);
1209:
1210: /* Undo the adds we just did. */
1211: if (addreg0)
1212: output_asm_insn ("add %0,-0x4,%0", &addreg0);
1213: if (addreg1)
1214: output_asm_insn ("add %0,-0x4,%0", &addreg1);
1215:
1216: return "";
1217: }
1.1.1.3 root 1218:
1219: /* Output assembler code to perform a quadword move insn
1.1.1.4 ! root 1220: with operands OPERANDS. This is very similar to the preceding
1.1.1.3 root 1221: output_move_double function. */
1222:
1223: char *
1224: output_move_quad (operands)
1225: rtx *operands;
1226: {
1227: register rtx op0 = operands[0];
1228: register rtx op1 = operands[1];
1229: register enum optype optype0;
1230: register enum optype optype1;
1231: rtx wordpart[4][2];
1232: rtx addreg0 = 0;
1233: rtx addreg1 = 0;
1234:
1235: /* First classify both operands. */
1236:
1237: if (REG_P (op0))
1238: optype0 = REGOP;
1239: else if (offsettable_memref_p (op0))
1240: optype0 = OFFSOP;
1241: else if (GET_CODE (op0) == MEM)
1242: optype0 = MEMOP;
1243: else
1244: optype0 = RNDOP;
1245:
1246: if (REG_P (op1))
1247: optype1 = REGOP;
1248: else if (CONSTANT_P (op1))
1249: optype1 = CNSTOP;
1250: else if (offsettable_memref_p (op1))
1251: optype1 = OFFSOP;
1252: else if (GET_CODE (op1) == MEM)
1253: optype1 = MEMOP;
1254: else
1255: optype1 = RNDOP;
1256:
1257: /* Check for the cases that the operand constraints are not
1258: supposed to allow to happen. Abort if we get one,
1259: because generating code for these cases is painful. */
1260:
1261: if (optype0 == RNDOP || optype1 == RNDOP
1262: || (optype0 == MEM && optype1 == MEM))
1263: abort ();
1264:
1265: /* If an operand is an unoffsettable memory ref, find a register
1266: we can increment temporarily to make it refer to the later words. */
1267:
1268: if (optype0 == MEMOP)
1269: addreg0 = find_addr_reg (XEXP (op0, 0));
1270:
1271: if (optype1 == MEMOP)
1272: addreg1 = find_addr_reg (XEXP (op1, 0));
1273:
1274: /* Ok, we can do one word at a time.
1275: Set up in wordpart the operands to use for each word of the arguments. */
1276:
1277: if (optype0 == REGOP)
1278: {
1279: wordpart[0][0] = gen_rtx (REG, SImode, REGNO (op0) + 0);
1280: wordpart[1][0] = gen_rtx (REG, SImode, REGNO (op0) + 1);
1281: wordpart[2][0] = gen_rtx (REG, SImode, REGNO (op0) + 2);
1282: wordpart[3][0] = gen_rtx (REG, SImode, REGNO (op0) + 3);
1283: }
1284: else if (optype0 == OFFSOP)
1285: {
1286: wordpart[0][0] = adj_offsettable_operand (op0, 0);
1287: wordpart[1][0] = adj_offsettable_operand (op0, 4);
1288: wordpart[2][0] = adj_offsettable_operand (op0, 8);
1289: wordpart[3][0] = adj_offsettable_operand (op0, 12);
1290: }
1291: else
1292: {
1293: wordpart[0][0] = op0;
1294: wordpart[1][0] = op0;
1295: wordpart[2][0] = op0;
1296: wordpart[3][0] = op0;
1297: }
1298:
1299: if (optype1 == REGOP)
1300: {
1301: wordpart[0][1] = gen_rtx (REG, SImode, REGNO (op1) + 0);
1302: wordpart[1][1] = gen_rtx (REG, SImode, REGNO (op1) + 1);
1303: wordpart[2][1] = gen_rtx (REG, SImode, REGNO (op1) + 2);
1304: wordpart[3][1] = gen_rtx (REG, SImode, REGNO (op1) + 3);
1305: }
1306: else if (optype1 == OFFSOP)
1307: {
1308: wordpart[0][1] = adj_offsettable_operand (op1, 0);
1309: wordpart[1][1] = adj_offsettable_operand (op1, 4);
1310: wordpart[2][1] = adj_offsettable_operand (op1, 8);
1311: wordpart[3][1] = adj_offsettable_operand (op1, 12);
1312: }
1313: else if (optype1 == CNSTOP)
1314: {
1315: /* This case isn't implemented yet, because there is no internal
1316: representation for quad-word constants, and there is no split_quad
1317: function. */
1318: #if 0
1319: split_quad (op1, &wordpart[0][1], &wordpart[1][1],
1320: &wordpart[2][1], &wordpart[3][1]);
1321: #else
1322: abort ();
1323: #endif
1324: }
1325: else
1326: {
1327: wordpart[0][1] = op1;
1328: wordpart[1][1] = op1;
1329: wordpart[2][1] = op1;
1330: wordpart[3][1] = op1;
1331: }
1332:
1333: /* Easy case: try moving the quad as two pairs. Check for moving between
1334: an even/odd register pair and a memory location. */
1335: /* ??? Should also handle the case of non-offsettable addresses here.
1336: We can at least do the first pair as a ldd/std, and then do the third
1337: and fourth words individually. */
1338: if ((optype0 == REGOP && optype1 == OFFSOP && (REGNO (op0) & 1) == 0)
1339: || (optype0 == OFFSOP && optype1 == REGOP && (REGNO (op1) & 1) == 0))
1340: {
1341: rtx mem;
1342:
1343: if (optype0 == REGOP)
1344: mem = op1;
1345: else
1346: mem = op0;
1347:
1348: if (mem_aligned_8 (mem))
1349: {
1350: operands[2] = adj_offsettable_operand (mem, 8);
1351: if (mem == op1)
1352: return "ldd %1,%0;ldd %2,%S0";
1353: else
1354: return "std %1,%0;std %S1,%2";
1355: }
1356: }
1357:
1358: /* If the first move would clobber the source of the second one,
1359: do them in the other order. */
1360:
1361: /* Overlapping registers. */
1362: if (optype0 == REGOP && optype1 == REGOP
1363: && (REGNO (op0) == REGNO (wordpart[1][3])
1364: || REGNO (op0) == REGNO (wordpart[1][2])
1365: || REGNO (op0) == REGNO (wordpart[1][1])))
1366: {
1367: /* Do fourth word. */
1368: output_asm_insn (singlemove_string (wordpart[3]), wordpart[3]);
1369: /* Do the third word. */
1370: output_asm_insn (singlemove_string (wordpart[2]), wordpart[2]);
1371: /* Do the second word. */
1372: output_asm_insn (singlemove_string (wordpart[1]), wordpart[1]);
1373: /* Do lowest-numbered word. */
1374: return singlemove_string (wordpart[0]);
1375: }
1376: /* Loading into a register which overlaps a register used in the address. */
1377: if (optype0 == REGOP && optype1 != REGOP
1378: && reg_overlap_mentioned_p (op0, op1))
1379: {
1380: /* ??? Not implemented yet. This is a bit complicated, because we
1381: must load which ever part overlaps the address last. If the address
1382: is a double-reg address, then there are two parts which need to
1383: be done last, which is impossible. We would need a scratch register
1384: in that case. */
1385: abort ();
1386: }
1387:
1388: /* Normal case: move the four words in lowest to higest address order. */
1389:
1390: output_asm_insn (singlemove_string (wordpart[0]), wordpart[0]);
1391:
1392: /* Make any unoffsettable addresses point at the second word. */
1393: if (addreg0)
1394: output_asm_insn ("add %0,0x4,%0", &addreg0);
1395: if (addreg1)
1396: output_asm_insn ("add %0,0x4,%0", &addreg1);
1397:
1398: /* Do the second word. */
1399: output_asm_insn (singlemove_string (wordpart[1]), wordpart[1]);
1400:
1401: /* Make any unoffsettable addresses point at the third word. */
1402: if (addreg0)
1403: output_asm_insn ("add %0,0x4,%0", &addreg0);
1404: if (addreg1)
1405: output_asm_insn ("add %0,0x4,%0", &addreg1);
1406:
1407: /* Do the third word. */
1408: output_asm_insn (singlemove_string (wordpart[2]), wordpart[2]);
1409:
1410: /* Make any unoffsettable addresses point at the fourth word. */
1411: if (addreg0)
1412: output_asm_insn ("add %0,0x4,%0", &addreg0);
1413: if (addreg1)
1414: output_asm_insn ("add %0,0x4,%0", &addreg1);
1415:
1416: /* Do the fourth word. */
1417: output_asm_insn (singlemove_string (wordpart[3]), wordpart[3]);
1418:
1419: /* Undo the adds we just did. */
1420: if (addreg0)
1421: output_asm_insn ("add %0,-0xc,%0", &addreg0);
1422: if (addreg1)
1423: output_asm_insn ("add %0,-0xc,%0", &addreg1);
1424:
1425: return "";
1426: }
1.1 root 1427:
1.1.1.3 root 1428: /* Output assembler code to perform a doubleword move insn with operands
1429: OPERANDS, one of which must be a floating point register. */
1430:
1.1 root 1431: char *
1432: output_fp_move_double (operands)
1433: rtx *operands;
1434: {
1435: rtx addr;
1436:
1437: if (FP_REG_P (operands[0]))
1438: {
1439: if (FP_REG_P (operands[1]))
1440: return "fmovs %1,%0\n\tfmovs %R1,%R0";
1.1.1.3 root 1441: else if (GET_CODE (operands[1]) == REG)
1.1 root 1442: {
1443: if ((REGNO (operands[1]) & 1) == 0)
1444: return "std %1,[%@-8]\n\tldd [%@-8],%0";
1445: else
1446: return "st %R1,[%@-4]\n\tst %1,[%@-8]\n\tldd [%@-8],%0";
1447: }
1.1.1.3 root 1448: else
1449: return output_move_double (operands);
1.1 root 1450: }
1451: else if (FP_REG_P (operands[1]))
1452: {
1453: if (GET_CODE (operands[0]) == REG)
1454: {
1455: if ((REGNO (operands[0]) & 1) == 0)
1456: return "std %1,[%@-8]\n\tldd [%@-8],%0";
1457: else
1458: return "std %1,[%@-8]\n\tld [%@-4],%R0\n\tld [%@-8],%0";
1459: }
1.1.1.3 root 1460: else
1461: return output_move_double (operands);
1.1 root 1462: }
1463: else abort ();
1464: }
1.1.1.3 root 1465:
1466: /* Output assembler code to perform a quadword move insn with operands
1467: OPERANDS, one of which must be a floating point register. */
1468:
1469: char *
1470: output_fp_move_quad (operands)
1471: rtx *operands;
1472: {
1473: register rtx op0 = operands[0];
1474: register rtx op1 = operands[1];
1475: register rtx addr;
1476:
1477: if (FP_REG_P (op0))
1478: {
1479: if (FP_REG_P (op1))
1480: return "fmovs %1,%0\n\tfmovs %R1,%R0\n\tfmovs %S1,%S0\n\tfmovs %T1,%T0";
1481: if (GET_CODE (op1) == REG)
1482: {
1483: if ((REGNO (op1) & 1) == 0)
1484: return "std %1,[%@-8]\n\tldd [%@-8],%0\n\tstd %S1,[%@-8]\n\tldd [%@-8],%S0";
1485: else
1486: return "st %R1,[%@-4]\n\tst %1,[%@-8]\n\tldd [%@-8],%0\n\tst %T1,[%@-4]\n\tst %S1,[%@-8]\n\tldd [%@-8],%S0";
1487: }
1488: else
1489: return output_move_quad (operands);
1490: }
1491: else if (FP_REG_P (op1))
1492: {
1493: if (GET_CODE (op0) == REG)
1494: {
1495: if ((REGNO (op0) & 1) == 0)
1496: return "std %1,[%@-8]\n\tldd [%@-8],%0\n\tstd %S1,[%@-8]\n\tldd [%@-8],%S0";
1497: else
1498: return "std %S1,[%@-8]\n\tld [%@-4],%T0\n\tld [%@-8],%S0\n\tstd %1,[%@-8]\n\tld [%@-4],%R0\n\tld [%@-8],%0";
1499: }
1500: else
1501: return output_move_quad (operands);
1502: }
1503: else
1504: abort ();
1505: }
1.1 root 1506:
1507: /* Return a REG that occurs in ADDR with coefficient 1.
1508: ADDR can be effectively incremented by incrementing REG. */
1509:
1510: static rtx
1511: find_addr_reg (addr)
1512: rtx addr;
1513: {
1514: while (GET_CODE (addr) == PLUS)
1515: {
1516: /* We absolutely can not fudge the frame pointer here, because the
1517: frame pointer must always be 8 byte aligned. It also confuses
1518: debuggers. */
1519: if (GET_CODE (XEXP (addr, 0)) == REG
1520: && REGNO (XEXP (addr, 0)) != FRAME_POINTER_REGNUM)
1521: addr = XEXP (addr, 0);
1522: else if (GET_CODE (XEXP (addr, 1)) == REG
1523: && REGNO (XEXP (addr, 1)) != FRAME_POINTER_REGNUM)
1524: addr = XEXP (addr, 1);
1525: else if (CONSTANT_P (XEXP (addr, 0)))
1526: addr = XEXP (addr, 1);
1527: else if (CONSTANT_P (XEXP (addr, 1)))
1528: addr = XEXP (addr, 0);
1529: else
1530: abort ();
1531: }
1532: if (GET_CODE (addr) == REG)
1533: return addr;
1534: abort ();
1535: }
1536:
1537: void
1538: output_sized_memop (opname, mode, signedp)
1539: char *opname;
1540: enum machine_mode mode;
1541: int signedp;
1542: {
1543: static char *ld_size_suffix_u[] = { "ub", "uh", "", "?", "d" };
1544: static char *ld_size_suffix_s[] = { "sb", "sh", "", "?", "d" };
1545: static char *st_size_suffix[] = { "b", "h", "", "?", "d" };
1546: char **opnametab, *modename;
1547:
1548: if (opname[0] == 'l')
1549: if (signedp)
1550: opnametab = ld_size_suffix_s;
1551: else
1552: opnametab = ld_size_suffix_u;
1553: else
1554: opnametab = st_size_suffix;
1555: modename = opnametab[GET_MODE_SIZE (mode) >> 1];
1556:
1557: fprintf (asm_out_file, "\t%s%s", opname, modename);
1558: }
1559:
1560: void
1561: output_move_with_extension (operands)
1562: rtx *operands;
1563: {
1564: if (GET_MODE (operands[2]) == HImode)
1565: output_asm_insn ("sll %2,0x10,%0", operands);
1566: else if (GET_MODE (operands[2]) == QImode)
1567: output_asm_insn ("sll %2,0x18,%0", operands);
1568: else
1569: abort ();
1570: }
1571:
1572: /* Load the address specified by OPERANDS[3] into the register
1573: specified by OPERANDS[0].
1574:
1575: OPERANDS[3] may be the result of a sum, hence it could either be:
1576:
1577: (1) CONST
1578: (2) REG
1579: (2) REG + CONST_INT
1580: (3) REG + REG + CONST_INT
1581: (4) REG + REG (special case of 3).
1582:
1583: Note that (3) is not a legitimate address.
1584: All cases are handled here. */
1585:
1586: void
1587: output_load_address (operands)
1588: rtx *operands;
1589: {
1590: rtx base, offset;
1591:
1592: if (CONSTANT_P (operands[3]))
1593: {
1594: output_asm_insn ("set %3,%0", operands);
1595: return;
1596: }
1597:
1598: if (REG_P (operands[3]))
1599: {
1600: if (REGNO (operands[0]) != REGNO (operands[3]))
1601: output_asm_insn ("mov %3,%0", operands);
1602: return;
1603: }
1604:
1605: if (GET_CODE (operands[3]) != PLUS)
1606: abort ();
1607:
1608: base = XEXP (operands[3], 0);
1609: offset = XEXP (operands[3], 1);
1610:
1611: if (GET_CODE (base) == CONST_INT)
1612: {
1613: rtx tmp = base;
1614: base = offset;
1615: offset = tmp;
1616: }
1617:
1618: if (GET_CODE (offset) != CONST_INT)
1619: {
1620: /* Operand is (PLUS (REG) (REG)). */
1621: base = operands[3];
1622: offset = const0_rtx;
1623: }
1624:
1625: if (REG_P (base))
1626: {
1627: operands[6] = base;
1628: operands[7] = offset;
1629: if (SMALL_INT (offset))
1630: output_asm_insn ("add %6,%7,%0", operands);
1631: else
1632: output_asm_insn ("set %7,%0\n\tadd %0,%6,%0", operands);
1633: }
1634: else if (GET_CODE (base) == PLUS)
1635: {
1636: operands[6] = XEXP (base, 0);
1637: operands[7] = XEXP (base, 1);
1638: operands[8] = offset;
1639:
1640: if (SMALL_INT (offset))
1641: output_asm_insn ("add %6,%7,%0\n\tadd %0,%8,%0", operands);
1642: else
1643: output_asm_insn ("set %8,%0\n\tadd %0,%6,%0\n\tadd %0,%7,%0", operands);
1644: }
1645: else
1646: abort ();
1647: }
1648:
1649: /* Output code to place a size count SIZE in register REG.
1650: ALIGN is the size of the unit of transfer.
1651:
1652: Because block moves are pipelined, we don't include the
1653: first element in the transfer of SIZE to REG. */
1654:
1655: static void
1656: output_size_for_block_move (size, reg, align)
1657: rtx size, reg;
1658: rtx align;
1659: {
1660: rtx xoperands[3];
1661:
1662: xoperands[0] = reg;
1663: xoperands[1] = size;
1664: xoperands[2] = align;
1665: if (GET_CODE (size) == REG)
1666: output_asm_insn ("sub %1,%2,%0", xoperands);
1667: else
1668: {
1669: xoperands[1]
1670: = gen_rtx (CONST_INT, VOIDmode, INTVAL (size) - INTVAL (align));
1671: output_asm_insn ("set %1,%0", xoperands);
1672: }
1673: }
1674:
1675: /* Emit code to perform a block move.
1676:
1677: OPERANDS[0] is the destination.
1678: OPERANDS[1] is the source.
1679: OPERANDS[2] is the size.
1680: OPERANDS[3] is the alignment safe to use.
1681: OPERANDS[4] is a register we can safely clobber as a temp. */
1682:
1683: char *
1684: output_block_move (operands)
1685: rtx *operands;
1686: {
1687: /* A vector for our computed operands. Note that load_output_address
1688: makes use of (and can clobber) up to the 8th element of this vector. */
1689: rtx xoperands[10];
1690: rtx zoperands[10];
1691: static int movstrsi_label = 0;
1692: int i;
1693: rtx temp1 = operands[4];
1694: rtx sizertx = operands[2];
1695: rtx alignrtx = operands[3];
1696: int align = INTVAL (alignrtx);
1.1.1.3 root 1697: char label3[30], label5[30];
1.1 root 1698:
1699: xoperands[0] = operands[0];
1700: xoperands[1] = operands[1];
1701: xoperands[2] = temp1;
1702:
1.1.1.2 root 1703: /* We can't move more than this many bytes at a time because we have only
1704: one register, %g1, to move them through. */
1705: if (align > UNITS_PER_WORD)
1706: {
1707: align = UNITS_PER_WORD;
1708: alignrtx = gen_rtx (CONST_INT, VOIDmode, UNITS_PER_WORD);
1709: }
1710:
1711: /* We consider 8 ld/st pairs, for a total of 16 inline insns to be
1712: reasonable here. (Actually will emit a maximum of 18 inline insns for
1713: the case of size == 31 and align == 4). */
1714:
1715: if (GET_CODE (sizertx) == CONST_INT && (INTVAL (sizertx) / align) <= 8
1716: && memory_address_p (QImode, plus_constant_for_output (xoperands[0],
1717: INTVAL (sizertx)))
1718: && memory_address_p (QImode, plus_constant_for_output (xoperands[1],
1719: INTVAL (sizertx))))
1.1 root 1720: {
1.1.1.2 root 1721: int size = INTVAL (sizertx);
1722: int offset = 0;
1723:
1724: /* We will store different integers into this particular RTX. */
1725: xoperands[2] = rtx_alloc (CONST_INT);
1726: PUT_MODE (xoperands[2], VOIDmode);
1727:
1728: /* This case is currently not handled. Abort instead of generating
1729: bad code. */
1730: if (align > 4)
1731: abort ();
1732:
1733: if (align >= 4)
1734: {
1735: for (i = (size >> 2) - 1; i >= 0; i--)
1736: {
1737: INTVAL (xoperands[2]) = (i << 2) + offset;
1738: output_asm_insn ("ld [%a1+%2],%%g1\n\tst %%g1,[%a0+%2]",
1739: xoperands);
1740: }
1741: offset += (size & ~0x3);
1742: size = size & 0x3;
1743: if (size == 0)
1744: return "";
1745: }
1746:
1747: if (align >= 2)
1748: {
1749: for (i = (size >> 1) - 1; i >= 0; i--)
1750: {
1751: INTVAL (xoperands[2]) = (i << 1) + offset;
1752: output_asm_insn ("lduh [%a1+%2],%%g1\n\tsth %%g1,[%a0+%2]",
1753: xoperands);
1754: }
1755: offset += (size & ~0x1);
1756: size = size & 0x1;
1757: if (size == 0)
1758: return "";
1759: }
1760:
1761: if (align >= 1)
1762: {
1763: for (i = size - 1; i >= 0; i--)
1764: {
1765: INTVAL (xoperands[2]) = i + offset;
1766: output_asm_insn ("ldub [%a1+%2],%%g1\n\tstb %%g1,[%a0+%2]",
1767: xoperands);
1768: }
1769: return "";
1770: }
1771:
1772: /* We should never reach here. */
1773: abort ();
1.1 root 1774: }
1775:
1776: /* If the size isn't known to be a multiple of the alignment,
1777: we have to do it in smaller pieces. If we could determine that
1778: the size was a multiple of 2 (or whatever), we could be smarter
1779: about this. */
1780: if (GET_CODE (sizertx) != CONST_INT)
1781: align = 1;
1782: else
1783: {
1784: int size = INTVAL (sizertx);
1785: while (size % align)
1786: align >>= 1;
1787: }
1788:
1789: if (align != INTVAL (alignrtx))
1790: alignrtx = gen_rtx (CONST_INT, VOIDmode, align);
1791:
1792: xoperands[3] = gen_rtx (CONST_INT, VOIDmode, movstrsi_label++);
1793: xoperands[4] = gen_rtx (CONST_INT, VOIDmode, align);
1794: xoperands[5] = gen_rtx (CONST_INT, VOIDmode, movstrsi_label++);
1795:
1.1.1.3 root 1796: ASM_GENERATE_INTERNAL_LABEL (label3, "Lm", INTVAL (xoperands[3]));
1797: ASM_GENERATE_INTERNAL_LABEL (label5, "Lm", INTVAL (xoperands[5]));
1798:
1.1.1.2 root 1799: /* This is the size of the transfer. Emit code to decrement the size
1800: value by ALIGN, and store the result in the temp1 register. */
1.1 root 1801: output_size_for_block_move (sizertx, temp1, alignrtx);
1802:
1803: /* Must handle the case when the size is zero or negative, so the first thing
1804: we do is compare the size against zero, and only copy bytes if it is
1805: zero or greater. Note that we have already subtracted off the alignment
1806: once, so we must copy 1 alignment worth of bytes if the size is zero
1807: here.
1808:
1809: The SUN assembler complains about labels in branch delay slots, so we
1.1.1.2 root 1810: do this before outputting the load address, so that there will always
1.1 root 1811: be a harmless insn between the branch here and the next label emitted
1812: below. */
1813:
1.1.1.3 root 1814: {
1815: char pattern[100];
1816:
1817: sprintf (pattern, "cmp %%2,0\n\tbl %s", &label5[1]);
1818: output_asm_insn (pattern, xoperands);
1819: }
1.1 root 1820:
1821: zoperands[0] = operands[0];
1822: zoperands[3] = plus_constant_for_output (operands[0], align);
1823: output_load_address (zoperands);
1824:
1825: /* ??? This might be much faster if the loops below were preconditioned
1826: and unrolled.
1827:
1828: That is, at run time, copy enough bytes one at a time to ensure that the
1829: target and source addresses are aligned to the the largest possible
1830: alignment. Then use a preconditioned unrolled loop to copy say 16
1831: bytes at a time. Then copy bytes one at a time until finish the rest. */
1832:
1833: /* Output the first label separately, so that it is spaced properly. */
1834:
1835: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "Lm", INTVAL (xoperands[3]));
1836:
1.1.1.3 root 1837: {
1838: char pattern[200];
1839: register char *ld_suffix = (align == 1) ? "ub" : (align == 2) ? "uh" : "";
1840: register char *st_suffix = (align == 1) ? "b" : (align == 2) ? "h" : "";
1841:
1842: sprintf (pattern, "ld%s [%%1+%%2],%%%%g1\n\tsubcc %%2,%%4,%%2\n\tbge %s\n\tst%s %%%%g1,[%%0+%%2]\n%s:", ld_suffix, &label3[1], st_suffix, &label5[1]);
1843: output_asm_insn (pattern, xoperands);
1844: }
1845:
1.1 root 1846: return "";
1847: }
1848:
1849: /* Output reasonable peephole for set-on-condition-code insns.
1850: Note that these insns assume a particular way of defining
1851: labels. Therefore, *both* sparc.h and this function must
1852: be changed if a new syntax is needed. */
1853:
1854: char *
1855: output_scc_insn (operands, insn)
1856: rtx operands[];
1857: rtx insn;
1858: {
1859: static char string[100];
1860: rtx label = 0, next = insn;
1861: int need_label = 0;
1862:
1863: /* Try doing a jump optimization which jump.c can't do for us
1864: because we did not expose that setcc works by using branches.
1865:
1866: If this scc insn is followed by an unconditional branch, then have
1867: the jump insn emitted here jump to that location, instead of to
1868: the end of the scc sequence as usual. */
1869:
1870: do
1871: {
1872: if (GET_CODE (next) == CODE_LABEL)
1873: label = next;
1874: next = NEXT_INSN (next);
1875: if (next == 0)
1876: break;
1877: }
1878: while (GET_CODE (next) == NOTE || GET_CODE (next) == CODE_LABEL);
1879:
1880: /* If we are in a sequence, and the following insn is a sequence also,
1881: then just following the current insn's next field will take us to the
1882: first insn of the next sequence, which is the wrong place. We don't
1883: want to optimize with a branch that has had its delay slot filled.
1884: Avoid this by verifying that NEXT_INSN (PREV_INSN (next)) == next
1885: which fails only if NEXT is such a branch. */
1886:
1887: if (next && GET_CODE (next) == JUMP_INSN && simplejump_p (next)
1888: && (! final_sequence || NEXT_INSN (PREV_INSN (next)) == next))
1889: label = JUMP_LABEL (next);
1890: /* If not optimizing, jump label fields are not set. To be safe, always
1891: check here to whether label is still zero. */
1892: if (label == 0)
1893: {
1894: label = gen_label_rtx ();
1895: need_label = 1;
1896: }
1897:
1898: LABEL_NUSES (label) += 1;
1899:
1900: operands[2] = label;
1901:
1902: /* If we are in a delay slot, assume it is the delay slot of an fpcc
1903: insn since our type isn't allowed anywhere else. */
1904:
1905: /* ??? Fpcc instructions no longer have delay slots, so this code is
1906: probably obsolete. */
1907:
1908: /* The fastest way to emit code for this is an annulled branch followed
1909: by two move insns. This will take two cycles if the branch is taken,
1910: and three cycles if the branch is not taken.
1911:
1912: However, if we are in the delay slot of another branch, this won't work,
1913: because we can't put a branch in the delay slot of another branch.
1914: The above sequence would effectively take 3 or 4 cycles respectively
1915: since a no op would have be inserted between the two branches.
1916: In this case, we want to emit a move, annulled branch, and then the
1917: second move. This sequence always takes 3 cycles, and hence is faster
1918: when we are in a branch delay slot. */
1919:
1920: if (final_sequence)
1921: {
1922: strcpy (string, "mov 0,%0\n\t");
1923: strcat (string, output_cbranch (operands[1], 2, 0, 1, 0));
1924: strcat (string, "\n\tmov 1,%0");
1925: }
1926: else
1927: {
1928: strcpy (string, output_cbranch (operands[1], 2, 0, 1, 0));
1929: strcat (string, "\n\tmov 1,%0\n\tmov 0,%0");
1930: }
1931:
1932: if (need_label)
1933: strcat (string, "\n%l2:");
1934:
1935: return string;
1936: }
1937:
1938: /* Vectors to keep interesting information about registers where
1939: it can easily be got. */
1940:
1941: /* Modes for condition codes. */
1.1.1.3 root 1942: #define C_MODES \
1943: ((1 << (int) CCmode) | (1 << (int) CC_NOOVmode) \
1944: | (1 << (int) CCFPmode) | (1 << (int) CCFPEmode))
1.1 root 1945:
1946: /* Modes for single-word (and smaller) quantities. */
1947: #define S_MODES \
1948: (~C_MODES \
1949: & ~ ((1 << (int) DImode) | (1 << (int) TImode) \
1950: | (1 << (int) DFmode) | (1 << (int) TFmode)))
1951:
1952: /* Modes for double-word (and smaller) quantities. */
1953: #define D_MODES \
1954: (~C_MODES \
1955: & ~ ((1 << (int) TImode) | (1 << (int) TFmode)))
1956:
1957: /* Modes for quad-word quantities. */
1958: #define T_MODES (~C_MODES)
1959:
1.1.1.4 ! root 1960: /* Modes for single-float quantities. We must allow any single word or
! 1961: smaller quantity. This is because the fix/float conversion instructions
! 1962: take integer inputs/outputs from the float registers. */
! 1963: #define SF_MODES (S_MODES)
1.1 root 1964:
1965: /* Modes for double-float quantities. */
1966: #define DF_MODES (SF_MODES | (1 << (int) DFmode) | (1 << (int) SCmode))
1967:
1968: /* Modes for quad-float quantities. */
1969: #define TF_MODES (DF_MODES | (1 << (int) TFmode) | (1 << (int) DCmode))
1970:
1971: /* Value is 1 if register/mode pair is acceptable on sparc.
1972: The funny mixture of D and T modes is because integer operations
1973: do not specially operate on tetra quantities, so non-quad-aligned
1974: registers can hold quadword quantities (except %o4 and %i4 because
1975: they cross fixed registers. */
1976:
1977: int hard_regno_mode_ok[] = {
1978: C_MODES, S_MODES, T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES,
1979: T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES, D_MODES, S_MODES,
1980: T_MODES, S_MODES, T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES,
1981: T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES, D_MODES, S_MODES,
1982:
1983: TF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES,
1984: TF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES,
1985: TF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES,
1986: TF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES};
1987:
1988: #ifdef __GNUC__
1989: inline
1990: #endif
1991: static int
1992: save_regs (file, low, high, base, offset, n_fregs)
1993: FILE *file;
1994: int low, high;
1995: char *base;
1996: int offset;
1997: int n_fregs;
1998: {
1999: int i;
2000:
2001: for (i = low; i < high; i += 2)
2002: {
2003: if (regs_ever_live[i] && ! call_used_regs[i])
2004: if (regs_ever_live[i+1] && ! call_used_regs[i+1])
2005: fprintf (file, "\tstd %s,[%s+%d]\n",
2006: reg_names[i], base, offset + 4 * n_fregs),
2007: n_fregs += 2;
2008: else
2009: fprintf (file, "\tst %s,[%s+%d]\n",
2010: reg_names[i], base, offset + 4 * n_fregs),
2011: n_fregs += 2;
2012: else if (regs_ever_live[i+1] && ! call_used_regs[i+1])
2013: fprintf (file, "\tst %s,[%s+%d]\n",
2014: reg_names[i+1], base, offset + 4 * n_fregs),
2015: n_fregs += 2;
2016: }
2017: return n_fregs;
2018: }
2019:
2020: #ifdef __GNUC__
2021: inline
2022: #endif
2023: static int
2024: restore_regs (file, low, high, base, offset, n_fregs)
2025: FILE *file;
2026: int low, high;
2027: char *base;
2028: int offset;
2029: {
2030: int i;
2031:
2032: for (i = low; i < high; i += 2)
2033: {
2034: if (regs_ever_live[i] && ! call_used_regs[i])
2035: if (regs_ever_live[i+1] && ! call_used_regs[i+1])
2036: fprintf (file, "\tldd [%s+%d], %s\n",
2037: base, offset + 4 * n_fregs, reg_names[i]),
2038: n_fregs += 2;
2039: else
2040: fprintf (file, "\tld [%s+%d],%s\n",
2041: base, offset + 4 * n_fregs, reg_names[i]),
2042: n_fregs += 2;
2043: else if (regs_ever_live[i+1] && ! call_used_regs[i+1])
2044: fprintf (file, "\tld [%s+%d],%s\n",
2045: base, offset + 4 * n_fregs, reg_names[i+1]),
2046: n_fregs += 2;
2047: }
2048: return n_fregs;
2049: }
2050:
2051: /* Static variables we want to share between prologue and epilogue. */
2052:
2053: /* Number of live floating point registers needed to be saved. */
2054: static int num_fregs;
2055:
2056: /* Nonzero if any floating point register was ever used. */
2057: static int fregs_ever_live;
2058:
2059: int
2060: compute_frame_size (size, leaf_function)
2061: int size;
2062: int leaf_function;
2063: {
2064: int fregs_ever_live = 0;
2065: int n_fregs = 0, i;
2066: int outgoing_args_size = (current_function_outgoing_args_size
2067: + REG_PARM_STACK_SPACE (current_function_decl));
2068:
2069: apparent_fsize = ((size) + 7 - STARTING_FRAME_OFFSET) & -8;
2070: for (i = 32; i < FIRST_PSEUDO_REGISTER; i += 2)
2071: fregs_ever_live |= regs_ever_live[i]|regs_ever_live[i+1];
2072:
2073: if (TARGET_EPILOGUE && fregs_ever_live)
2074: {
2075: for (i = 32; i < FIRST_PSEUDO_REGISTER; i += 2)
2076: if ((regs_ever_live[i] && ! call_used_regs[i])
2077: || (regs_ever_live[i+1] && ! call_used_regs[i+1]))
2078: n_fregs += 2;
2079: }
2080:
2081: /* Set up values for use in `function_epilogue'. */
2082: num_fregs = n_fregs;
2083:
2084: apparent_fsize += (outgoing_args_size+7) & -8;
2085: if (leaf_function && n_fregs == 0
2086: && apparent_fsize == (REG_PARM_STACK_SPACE (current_function_decl)
2087: - STARTING_FRAME_OFFSET))
2088: apparent_fsize = 0;
2089:
2090: actual_fsize = apparent_fsize + n_fregs*4;
2091:
2092: /* Make sure nothing can clobber our register windows.
2093: If a SAVE must be done, or there is a stack-local variable,
2094: the register window area must be allocated. */
2095: if (leaf_function == 0 || size > 0)
2096: actual_fsize += (16 * UNITS_PER_WORD)+8;
2097:
2098: return actual_fsize;
2099: }
2100:
1.1.1.3 root 2101: /* Output code for the function prologue. */
2102:
1.1 root 2103: void
2104: output_function_prologue (file, size, leaf_function)
2105: FILE *file;
2106: int size;
1.1.1.3 root 2107: int leaf_function;
1.1 root 2108: {
2109: if (leaf_function)
2110: frame_base_name = "%sp+80";
2111: else
2112: frame_base_name = "%fp";
2113:
1.1.1.3 root 2114: /* Need to use actual_fsize, since we are also allocating
2115: space for our callee (and our own register save area). */
1.1 root 2116: actual_fsize = compute_frame_size (size, leaf_function);
2117:
2118: fprintf (file, "\t!#PROLOGUE# 0\n");
1.1.1.3 root 2119: if (actual_fsize == 0)
2120: /* do nothing. */ ;
2121: else if (actual_fsize <= 4096)
1.1 root 2122: {
2123: if (! leaf_function)
2124: fprintf (file, "\tsave %%sp,-%d,%%sp\n", actual_fsize);
2125: else
2126: fprintf (file, "\tadd %%sp,-%d,%%sp\n", actual_fsize);
2127: }
1.1.1.3 root 2128: else if (actual_fsize <= 8192)
1.1 root 2129: {
1.1.1.3 root 2130: /* For frames in the range 4097..8192, we can use just two insns. */
2131: if (! leaf_function)
2132: {
2133: fprintf (file, "\tsave %%sp,-4096,%%sp\n");
2134: fprintf (file, "\tadd %%sp,-%d,%%sp\n", actual_fsize - 4096);
2135: }
2136: else
2137: {
2138: fprintf (file, "\tadd %%sp,-4096,%%sp\n");
2139: fprintf (file, "\tadd %%sp,-%d,%%sp\n", actual_fsize - 4096);
2140: }
1.1 root 2141: }
2142: else
2143: {
1.1.1.3 root 2144: if (! leaf_function)
2145: {
2146: fprintf (file, "\tsethi %%hi(-%d),%%g1\n", actual_fsize);
2147: if ((actual_fsize & 0x3ff) != 0)
2148: fprintf (file, "\tor %%g1,%%lo(-%d),%%g1\n", actual_fsize);
2149: fprintf (file, "\tsave %%sp,%%g1,%%sp\n");
2150: }
2151: else
2152: {
2153: fprintf (file, "\tsethi %%hi(-%d),%%g1\n", actual_fsize);
2154: if ((actual_fsize & 0x3ff) != 0)
2155: fprintf (file, "\tor %%g1,%%lo(-%d),%%g1\n", actual_fsize);
2156: fprintf (file, "\tadd %%sp,%%g1,%%sp\n");
2157: }
1.1 root 2158: }
2159:
2160: /* If doing anything with PIC, do it now. */
2161: if (! flag_pic)
2162: fprintf (file, "\t!#PROLOGUE# 1\n");
2163:
2164: /* Figure out where to save any special registers. */
2165: if (num_fregs)
2166: {
2167: int offset, n_fregs = num_fregs;
2168:
2169: if (! leaf_function)
2170: offset = -apparent_fsize;
2171: else
2172: offset = 0;
2173:
2174: if (TARGET_EPILOGUE && ! leaf_function)
2175: n_fregs = save_regs (file, 0, 16, frame_base_name, offset, 0);
2176: else if (leaf_function)
2177: n_fregs = save_regs (file, 0, 32, frame_base_name, offset, 0);
2178: if (TARGET_EPILOGUE)
2179: save_regs (file, 32, FIRST_PSEUDO_REGISTER,
2180: frame_base_name, offset, n_fregs);
2181: }
2182:
2183: if (regs_ever_live[62])
2184: fprintf (file, "\tst %s,[%s-16]\n\tst %s,[%s-12]\n",
2185: reg_names[0], frame_base_name,
2186: reg_names[0], frame_base_name);
2187:
2188: leaf_label = 0;
2189: if (leaf_function && actual_fsize != 0)
2190: {
2191: /* warning ("leaf procedure with frame size %d", actual_fsize); */
2192: if (! TARGET_EPILOGUE)
2193: leaf_label = gen_label_rtx ();
2194: }
2195: }
2196:
1.1.1.3 root 2197: /* Output code for the function epilogue. */
2198:
1.1 root 2199: void
1.1.1.3 root 2200: output_function_epilogue (file, size, leaf_function)
1.1 root 2201: FILE *file;
2202: int size;
1.1.1.3 root 2203: int leaf_function;
1.1 root 2204: {
2205: int n_fregs, i;
2206: char *ret;
2207:
2208: if (leaf_label)
2209: {
2210: emit_label_after (leaf_label, get_last_insn ());
2211: final_scan_insn (get_last_insn (), file, 0, 0, 1);
2212: }
2213:
2214: if (num_fregs)
2215: {
2216: int offset, n_fregs = num_fregs;
2217:
2218: if (! leaf_function)
2219: offset = -apparent_fsize;
2220: else
2221: offset = 0;
2222:
2223: if (TARGET_EPILOGUE && ! leaf_function)
2224: n_fregs = restore_regs (file, 0, 16, frame_base_name, offset, 0);
2225: else if (leaf_function)
2226: n_fregs = restore_regs (file, 0, 32, frame_base_name, offset, 0);
2227: if (TARGET_EPILOGUE)
2228: restore_regs (file, 32, FIRST_PSEUDO_REGISTER,
2229: frame_base_name, offset, n_fregs);
2230: }
2231:
2232: /* Work out how to skip the caller's unimp instruction if required. */
2233: if (leaf_function)
2234: ret = (current_function_returns_struct ? "jmp %o7+12" : "retl");
2235: else
2236: ret = (current_function_returns_struct ? "jmp %i7+12" : "ret");
2237:
1.1.1.3 root 2238: if (TARGET_EPILOGUE || leaf_label)
1.1 root 2239: {
1.1.1.3 root 2240: int old_target_epilogue = TARGET_EPILOGUE;
2241: target_flags &= ~old_target_epilogue;
1.1 root 2242:
1.1.1.3 root 2243: if (! leaf_function)
2244: {
2245: /* If we wound up with things in our delay slot, flush them here. */
2246: if (current_function_epilogue_delay_list)
1.1 root 2247: {
1.1.1.3 root 2248: rtx insn = emit_jump_insn_after (gen_rtx (RETURN, VOIDmode),
2249: get_last_insn ());
2250: PATTERN (insn) = gen_rtx (PARALLEL, VOIDmode,
2251: gen_rtvec (2,
2252: PATTERN (XEXP (current_function_epilogue_delay_list, 0)),
2253: PATTERN (insn)));
2254: final_scan_insn (insn, file, 1, 0, 1);
1.1 root 2255: }
2256: else
1.1.1.3 root 2257: fprintf (file, "\t%s\n\trestore\n", ret);
1.1 root 2258: }
1.1.1.3 root 2259: /* All of the following cases are for leaf functions. */
2260: else if (current_function_epilogue_delay_list)
1.1 root 2261: {
1.1.1.3 root 2262: /* eligible_for_epilogue_delay_slot ensures that if this is a
2263: leaf function, then we will only have insn in the delay slot
2264: if the frame size is zero, thus no adjust for the stack is
2265: needed here. */
2266: if (actual_fsize != 0)
2267: abort ();
2268: fprintf (file, "\t%s\n", ret);
2269: final_scan_insn (XEXP (current_function_epilogue_delay_list, 0),
2270: file, 1, 0, 1);
2271: }
2272: else if (actual_fsize <= 4096)
2273: fprintf (file, "\t%s\n\tsub %%sp,-%d,%%sp\n", ret, actual_fsize);
2274: else if (actual_fsize <= 8192)
2275: fprintf (file, "\tsub %%sp,-4096,%%sp\n\t%s\n\tsub %%sp,-%d,%%sp\n",
2276: ret, actual_fsize - 4096);
2277: else if ((actual_fsize & 0x3ff) == 0)
2278: fprintf (file, "\tsethi %%hi(%d),%%g1\n\t%s\n\tadd %%sp,%%g1,%%sp\n",
2279: actual_fsize, ret);
2280: else
2281: fprintf (file, "\tsethi %%hi(%d),%%g1\n\tor %%g1,%%lo(%d),%%g1\n\t%s\n\tadd %%sp,%%g1,%%sp\n",
2282: actual_fsize, actual_fsize, ret);
2283: target_flags |= old_target_epilogue;
1.1 root 2284: }
2285: }
2286:
2287: /* Return the string to output a conditional branch to LABEL, which is
2288: the operand number of the label. OP is the conditional expression. The
2289: mode of register 0 says what kind of comparison we made.
2290:
2291: REVERSED is non-zero if we should reverse the sense of the comparison.
2292:
2293: ANNUL is non-zero if we should generate an annulling branch.
2294:
2295: NOOP is non-zero if we have to follow this branch by a noop. */
2296:
2297: char *
2298: output_cbranch (op, label, reversed, annul, noop)
2299: rtx op;
2300: int label;
2301: int reversed, annul, noop;
2302: {
2303: static char string[20];
2304: enum rtx_code code = GET_CODE (op);
2305: enum machine_mode mode = GET_MODE (XEXP (op, 0));
2306: static char labelno[] = " %lX";
2307:
1.1.1.2 root 2308: /* ??? FP branches can not be preceded by another floating point insn.
1.1 root 2309: Because there is currently no concept of pre-delay slots, we can fix
2310: this only by always emitting a nop before a floating point branch. */
2311:
1.1.1.3 root 2312: if (mode == CCFPmode || mode == CCFPEmode)
1.1 root 2313: strcpy (string, "nop\n\t");
2314:
2315: /* If not floating-point or if EQ or NE, we can just reverse the code. */
1.1.1.3 root 2316: if (reversed
2317: && ((mode != CCFPmode && mode != CCFPEmode) || code == EQ || code == NE))
1.1 root 2318: code = reverse_condition (code), reversed = 0;
2319:
2320: /* Start by writing the branch condition. */
2321: switch (code)
2322: {
2323: case NE:
1.1.1.3 root 2324: if (mode == CCFPmode || mode == CCFPEmode)
1.1 root 2325: strcat (string, "fbne");
2326: else
2327: strcpy (string, "bne");
2328: break;
2329:
2330: case EQ:
1.1.1.3 root 2331: if (mode == CCFPmode || mode == CCFPEmode)
1.1 root 2332: strcat (string, "fbe");
2333: else
2334: strcpy (string, "be");
2335: break;
2336:
2337: case GE:
1.1.1.3 root 2338: if (mode == CCFPmode || mode == CCFPEmode)
1.1 root 2339: {
2340: if (reversed)
2341: strcat (string, "fbul");
2342: else
2343: strcat (string, "fbge");
2344: }
2345: else if (mode == CC_NOOVmode)
2346: strcpy (string, "bpos");
2347: else
2348: strcpy (string, "bge");
2349: break;
2350:
2351: case GT:
1.1.1.3 root 2352: if (mode == CCFPmode || mode == CCFPEmode)
1.1 root 2353: {
2354: if (reversed)
2355: strcat (string, "fbule");
2356: else
2357: strcat (string, "fbg");
2358: }
2359: else
2360: strcpy (string, "bg");
2361: break;
2362:
2363: case LE:
1.1.1.3 root 2364: if (mode == CCFPmode || mode == CCFPEmode)
1.1 root 2365: {
2366: if (reversed)
2367: strcat (string, "fbug");
2368: else
2369: strcat (string, "fble");
2370: }
2371: else
2372: strcpy (string, "ble");
2373: break;
2374:
2375: case LT:
1.1.1.3 root 2376: if (mode == CCFPmode || mode == CCFPEmode)
1.1 root 2377: {
2378: if (reversed)
2379: strcat (string, "fbuge");
2380: else
2381: strcat (string, "fbl");
2382: }
2383: else if (mode == CC_NOOVmode)
2384: strcpy (string, "bneg");
2385: else
2386: strcpy (string, "bl");
2387: break;
2388:
2389: case GEU:
2390: strcpy (string, "bgeu");
2391: break;
2392:
2393: case GTU:
2394: strcpy (string, "bgu");
2395: break;
2396:
2397: case LEU:
2398: strcpy (string, "bleu");
2399: break;
2400:
2401: case LTU:
2402: strcpy (string, "blu");
2403: break;
2404: }
2405:
2406: /* Now add the annulling, the label, and a possible noop. */
2407: if (annul)
2408: strcat (string, ",a");
2409:
2410: labelno[3] = label + '0';
2411: strcat (string, labelno);
2412:
2413: if (noop)
2414: strcat (string, "\n\tnop");
2415:
2416: return string;
2417: }
2418:
1.1.1.3 root 2419: /* Output assembler code to return from a function. */
2420:
1.1 root 2421: char *
2422: output_return (operands)
2423: rtx *operands;
2424: {
2425: if (leaf_label)
2426: {
2427: operands[0] = leaf_label;
2428: return "b,a %l0";
2429: }
2430: else if (leaf_function)
2431: {
1.1.1.3 root 2432: /* If we didn't allocate a frame pointer for the current function,
2433: the stack pointer might have been adjusted. Output code to
2434: restore it now. */
2435:
1.1 root 2436: operands[0] = gen_rtx (CONST_INT, VOIDmode, actual_fsize);
1.1.1.3 root 2437:
2438: /* Use sub of negated value in first two cases instead of add to
2439: allow actual_fsize == 4096. */
2440:
2441: if (actual_fsize <= 4096)
1.1 root 2442: {
2443: if (current_function_returns_struct)
1.1.1.3 root 2444: return "jmp %%o7+12\n\tsub %%sp,-%0,%%sp";
1.1 root 2445: else
1.1.1.3 root 2446: return "retl\n\tsub %%sp,-%0,%%sp";
1.1 root 2447: }
1.1.1.3 root 2448: else if (actual_fsize <= 8192)
1.1 root 2449: {
1.1.1.3 root 2450: operands[0] = gen_rtx (CONST_INT, VOIDmode, actual_fsize - 4096);
1.1 root 2451: if (current_function_returns_struct)
1.1.1.3 root 2452: return "sub %%sp,-4096,%%sp\n\tjmp %%o7+12\n\tsub %%sp,-%0,%%sp";
2453: else
2454: return "sub %%sp,-4096,%%sp\n\tretl\n\tsub %%sp,-%0,%%sp";
2455: }
2456: else if (current_function_returns_struct)
2457: {
2458: if ((actual_fsize & 0x3ff) != 0)
1.1 root 2459: return "sethi %%hi(%a0),%%g1\n\tor %%g1,%%lo(%a0),%%g1\n\tjmp %%o7+12\n\tadd %%sp,%%g1,%%sp";
2460: else
1.1.1.3 root 2461: return "sethi %%hi(%a0),%%g1\n\tjmp %%o7+12\n\tadd %%sp,%%g1,%%sp";
2462: }
2463: else
2464: {
2465: if ((actual_fsize & 0x3ff) != 0)
1.1 root 2466: return "sethi %%hi(%a0),%%g1\n\tor %%g1,%%lo(%a0),%%g1\n\tretl\n\tadd %%sp,%%g1,%%sp";
1.1.1.3 root 2467: else
2468: return "sethi %%hi(%a0),%%g1\n\tretl\n\tadd %%sp,%%g1,%%sp";
1.1 root 2469: }
2470: }
2471: else
2472: {
2473: if (current_function_returns_struct)
2474: return "jmp %%i7+12\n\trestore";
2475: else
2476: return "ret\n\trestore";
2477: }
2478: }
2479:
2480: /* Leaf functions and non-leaf functions have different needs. */
2481:
2482: static int
2483: reg_leaf_alloc_order[] = REG_LEAF_ALLOC_ORDER;
2484:
2485: static int
2486: reg_nonleaf_alloc_order[] = REG_ALLOC_ORDER;
2487:
2488: static int *reg_alloc_orders[] = {
2489: reg_leaf_alloc_order,
2490: reg_nonleaf_alloc_order};
2491:
2492: void
2493: order_regs_for_local_alloc ()
2494: {
2495: static int last_order_nonleaf = 1;
2496:
2497: if (regs_ever_live[15] != last_order_nonleaf)
2498: {
2499: last_order_nonleaf = !last_order_nonleaf;
2500: bcopy (reg_alloc_orders[last_order_nonleaf], reg_alloc_order,
2501: FIRST_PSEUDO_REGISTER * sizeof (int));
2502: }
2503: }
2504:
2505: /* Machine dependent routines for the branch probability, arc profiling
2506: code. */
2507:
2508: /* The label used by the arc profiling code. */
2509:
2510: static rtx profiler_label;
2511:
2512: void
2513: init_arc_profiler ()
2514: {
2515: /* Generate and save a copy of this so it can be shared. */
2516: profiler_label = gen_rtx (SYMBOL_REF, Pmode, "*LPBX2");
2517: }
2518:
2519: void
2520: output_arc_profiler (arcno, insert_after)
2521: int arcno;
2522: rtx insert_after;
2523: {
2524: rtx profiler_target_addr
2525: = gen_rtx (CONST, Pmode,
2526: gen_rtx (PLUS, Pmode, profiler_label,
2527: gen_rtx (CONST_INT, VOIDmode, 4 * arcno)));
2528: register rtx profiler_reg = gen_reg_rtx (SImode);
1.1.1.2 root 2529: register rtx address_reg = gen_reg_rtx (Pmode);
2530: rtx mem_ref;
2531:
2532: insert_after = emit_insn_after (gen_rtx (SET, VOIDmode, address_reg,
2533: gen_rtx (HIGH, Pmode,
2534: profiler_target_addr)),
2535: insert_after);
2536:
2537: mem_ref = gen_rtx (MEM, SImode, gen_rtx (LO_SUM, Pmode, address_reg,
2538: profiler_target_addr));
2539: insert_after = emit_insn_after (gen_rtx (SET, VOIDmode, profiler_reg,
2540: mem_ref),
2541: insert_after);
2542:
2543: insert_after = emit_insn_after (gen_rtx (SET, VOIDmode, profiler_reg,
2544: gen_rtx (PLUS, SImode, profiler_reg,
2545: const1_rtx)),
2546: insert_after);
2547:
2548: /* This is the same rtx as above, but it is not legal to share this rtx. */
2549: mem_ref = gen_rtx (MEM, SImode, gen_rtx (LO_SUM, Pmode, address_reg,
2550: profiler_target_addr));
2551: emit_insn_after (gen_rtx (SET, VOIDmode, mem_ref, profiler_reg),
1.1 root 2552: insert_after);
2553: }
1.1.1.3 root 2554:
2555: /* Return 1 if REGNO (reg1) is even and REGNO (reg1) == REGNO (reg2) - 1.
2556: This makes them candidates for using ldd and std insns.
2557:
2558: Note reg1 and reg2 *must* be hard registers. To be sure we will
2559: abort if we are passed pseudo registers. */
2560:
2561: int
1.1.1.4 ! root 2562: registers_ok_for_ldd_peep (reg1, reg2)
1.1.1.3 root 2563: rtx reg1, reg2;
1.1 root 2564: {
2565:
1.1.1.3 root 2566: /* We might have been passed a SUBREG. */
2567: if (GET_CODE (reg1) != REG || GET_CODE (reg2) != REG)
2568: return 0;
2569:
2570: /* Should never happen. */
2571: if (REGNO (reg1) > FIRST_PSEUDO_REGISTER
2572: || REGNO (reg2) > FIRST_PSEUDO_REGISTER)
2573: abort ();
2574:
2575: if (REGNO (reg1) % 2 != 0)
2576: return 0;
2577:
2578: return (REGNO (reg1) == REGNO (reg2) - 1);
2579:
2580: }
2581:
2582: /* Return 1 if addr1 and addr2 are suitable for use in an ldd or
2583: std insn.
1.1 root 2584:
1.1.1.3 root 2585: This can only happen when addr1 and addr2 are consecutive memory
2586: locations (addr1 + 4 == addr2). addr1 must also be aligned on a
2587: 64 bit boundary (addr1 % 8 == 0).
1.1 root 2588:
1.1.1.3 root 2589: We know %sp and %fp are kept aligned on a 64 bit boundary. Other
2590: registers are assumed to *never* be properly aligned and are
2591: rejected.
1.1 root 2592:
1.1.1.3 root 2593: Knowing %sp and %fp are kept aligned on a 64 bit boundary, we
2594: need only check that the offset for addr1 % 8 == 0. */
2595:
2596: int
1.1.1.4 ! root 2597: addrs_ok_for_ldd_peep (addr1, addr2)
1.1.1.3 root 2598: rtx addr1, addr2;
2599: {
2600: int reg1, offset1;
1.1 root 2601:
1.1.1.3 root 2602: /* Extract a register number and offset (if used) from the first addr. */
2603: if (GET_CODE (addr1) == PLUS)
1.1 root 2604: {
1.1.1.3 root 2605: /* If not a REG, return zero. */
2606: if (GET_CODE (XEXP (addr1, 0)) != REG)
2607: return 0;
1.1 root 2608: else
1.1.1.3 root 2609: {
2610: reg1 = REGNO (XEXP (addr1, 0));
2611: /* The offset must be constant! */
2612: if (GET_CODE (XEXP (addr1, 1)) != CONST_INT)
2613: return 0;
2614: offset1 = INTVAL (XEXP (addr1, 1));
2615: }
1.1 root 2616: }
1.1.1.3 root 2617: else if (GET_CODE (addr1) != REG)
2618: return 0;
1.1 root 2619: else
2620: {
1.1.1.3 root 2621: reg1 = REGNO (addr1);
2622: /* This was a simple (mem (reg)) expression. Offset is 0. */
2623: offset1 = 0;
1.1 root 2624: }
1.1.1.3 root 2625:
2626: /* Make sure the second address is a (mem (plus (reg) (const_int). */
2627: if (GET_CODE (addr2) != PLUS)
2628: return 0;
2629:
2630: if (GET_CODE (XEXP (addr2, 0)) != REG
2631: || GET_CODE (XEXP (addr2, 1)) != CONST_INT)
2632: return 0;
2633:
2634: /* Only %fp and %sp are allowed. Additionally both addresses must
2635: use the same register. */
2636: if (reg1 != FRAME_POINTER_REGNUM && reg1 != STACK_POINTER_REGNUM)
2637: return 0;
2638:
2639: if (reg1 != REGNO (XEXP (addr2, 0)))
2640: return 0;
2641:
1.1.1.4 ! root 2642: /* The first offset must be evenly divisible by 8 to ensure the
1.1.1.3 root 2643: address is 64 bit aligned. */
2644: if (offset1 % 8 != 0)
2645: return 0;
2646:
2647: /* The offset for the second addr must be 4 more than the first addr. */
2648: if (INTVAL (XEXP (addr2, 1)) != offset1 + 4)
2649: return 0;
2650:
2651: /* All the tests passed. addr1 and addr2 are valid for ldd and std
2652: instructions. */
2653: return 1;
1.1 root 2654: }
1.1.1.4 ! root 2655:
! 2656: /* Return 1 if reg is a pseudo, or is the first register in
! 2657: a hard register pair. This makes it a candidate for use in
! 2658: ldd and std insns. */
! 2659:
! 2660: int
! 2661: register_ok_for_ldd (reg)
! 2662: rtx reg;
! 2663: {
! 2664:
! 2665: /* We might have been passed a SUBREG. */
! 2666: if (GET_CODE (reg) != REG)
! 2667: return 0;
! 2668:
! 2669: if (REGNO (reg) < FIRST_PSEUDO_REGISTER)
! 2670: return (REGNO (reg) % 2 == 0);
! 2671: else
! 2672: return 1;
! 2673:
! 2674: }
1.1 root 2675:
2676: /* Print operand X (an rtx) in assembler syntax to file FILE.
2677: CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
2678: For `%' followed by punctuation, CODE is the punctuation and X is null. */
2679:
2680: void
2681: print_operand (file, x, code)
2682: FILE *file;
2683: rtx x;
2684: int code;
2685: {
2686: switch (code)
2687: {
2688: case '#':
2689: /* Output a 'nop' if there's nothing for the delay slot. */
2690: if (dbr_sequence_length () == 0)
2691: fputs ("\n\tnop", file);
2692: return;
2693: case '*':
1.1.1.4 ! root 2694: /* Output an annul flag if there's nothing for the delay slot and we
! 2695: are optimizing. This is always used with '(' below. */
! 2696: /* Sun OS 4.1.1 dbx can't handle an annulled unconditional branch;
! 2697: this is a dbx bug. So, we only do this when optimizing. */
! 2698: if (dbr_sequence_length () == 0 && optimize)
! 2699: fputs (",a", file);
! 2700: return;
! 2701: case '(':
! 2702: /* Output a 'nop' if there's nothing for the delay slot and we are
! 2703: not optimizing. This is always used with '*' above. */
! 2704: if (dbr_sequence_length () == 0 && ! optimize)
! 2705: fputs ("\n\tnop", file);
1.1 root 2706: return;
2707: case 'Y':
2708: /* Adjust the operand to take into account a RESTORE operation. */
2709: if (GET_CODE (x) != REG)
2710: abort ();
2711: if (REGNO (x) < 8)
2712: fputs (reg_names[REGNO (x)], file);
2713: else if (REGNO (x) >= 24 && REGNO (x) < 32)
2714: fputs (reg_names[REGNO (x)-16], file);
2715: else
2716: abort ();
2717: return;
2718: case '@':
2719: /* Print out what we are using as the frame pointer. This might
2720: be %fp, or might be %sp+offset. */
2721: fputs (frame_base_name, file);
2722: return;
2723: case 'R':
1.1.1.3 root 2724: /* Print out the second register name of a register pair or quad.
1.1 root 2725: I.e., R (%o0) => %o1. */
2726: fputs (reg_names[REGNO (x)+1], file);
2727: return;
1.1.1.3 root 2728: case 'S':
2729: /* Print out the third register name of a register quad.
2730: I.e., S (%o0) => %o2. */
2731: fputs (reg_names[REGNO (x)+2], file);
2732: return;
2733: case 'T':
2734: /* Print out the fourth register name of a register quad.
2735: I.e., T (%o0) => %o3. */
2736: fputs (reg_names[REGNO (x)+3], file);
2737: return;
1.1 root 2738: case 'm':
2739: /* Print the operand's address only. */
2740: output_address (XEXP (x, 0));
2741: return;
2742: case 'r':
2743: /* In this case we need a register. Use %g0 if the
1.1.1.3 root 2744: operand is const0_rtx. */
2745: if (x == const0_rtx
2746: || (GET_MODE (x) != VOIDmode && x == CONST0_RTX (GET_MODE (x))))
1.1 root 2747: {
2748: fputs ("%g0", file);
2749: return;
2750: }
2751: else
2752: break;
2753:
2754: case 'A':
2755: switch (GET_CODE (x))
2756: {
2757: case IOR: fputs ("or", file); break;
2758: case AND: fputs ("and", file); break;
2759: case XOR: fputs ("xor", file); break;
2760: default: abort ();
2761: }
2762: return;
2763:
2764: case 'B':
2765: switch (GET_CODE (x))
2766: {
2767: case IOR: fputs ("orn", file); break;
2768: case AND: fputs ("andn", file); break;
2769: case XOR: fputs ("xnor", file); break;
2770: default: abort ();
2771: }
2772: return;
2773:
2774: case 'b':
2775: {
2776: /* Print a sign-extended character. */
2777: int i = INTVAL (x) & 0xff;
2778: if (i & 0x80)
2779: i |= 0xffffff00;
2780: fprintf (file, "%d", i);
2781: return;
2782: }
2783:
2784: case 0:
2785: /* Do nothing special. */
2786: break;
2787:
2788: default:
2789: /* Undocumented flag. */
1.1.1.4 ! root 2790: output_operand_lossage ("invalid operand output code");
1.1 root 2791: }
2792:
2793: if (GET_CODE (x) == REG)
2794: fputs (reg_names[REGNO (x)], file);
2795: else if (GET_CODE (x) == MEM)
2796: {
2797: fputc ('[', file);
2798: if (CONSTANT_P (XEXP (x, 0)))
2799: /* Poor Sun assembler doesn't understand absolute addressing. */
2800: fputs ("%g0+", file);
2801: output_address (XEXP (x, 0));
2802: fputc (']', file);
2803: }
2804: else if (GET_CODE (x) == HIGH)
2805: {
2806: fputs ("%hi(", file);
2807: output_addr_const (file, XEXP (x, 0));
2808: fputc (')', file);
2809: }
2810: else if (GET_CODE (x) == LO_SUM)
2811: {
2812: print_operand (file, XEXP (x, 0), 0);
2813: fputs ("+%lo(", file);
2814: output_addr_const (file, XEXP (x, 1));
2815: fputc (')', file);
2816: }
2817: else if (GET_CODE (x) == CONST_DOUBLE)
2818: {
2819: if (CONST_DOUBLE_HIGH (x) == 0)
2820: fprintf (file, "%u", CONST_DOUBLE_LOW (x));
2821: else if (CONST_DOUBLE_HIGH (x) == -1
2822: && CONST_DOUBLE_LOW (x) < 0)
2823: fprintf (file, "%d", CONST_DOUBLE_LOW (x));
2824: else
2825: abort ();
2826: }
2827: else { output_addr_const (file, x); }
2828: }
2829:
2830: /* This function outputs assembler code for VALUE to FILE, where VALUE is
2831: a 64 bit (DImode) value. */
2832:
2833: /* ??? If there is a 64 bit counterpart to .word that the assembler
2834: understands, then using that would simply this code greatly. */
2835:
2836: void
2837: output_double_int (file, value)
2838: FILE *file;
2839: rtx value;
2840: {
2841: if (GET_CODE (value) == CONST_INT)
2842: {
2843: if (INTVAL (value) < 0)
2844: ASM_OUTPUT_INT (file, constm1_rtx);
2845: else
2846: ASM_OUTPUT_INT (file, const0_rtx);
2847: ASM_OUTPUT_INT (file, value);
2848: }
2849: else if (GET_CODE (value) == CONST_DOUBLE)
2850: {
2851: ASM_OUTPUT_INT (file, gen_rtx (CONST_INT, VOIDmode,
2852: CONST_DOUBLE_HIGH (value)));
2853: ASM_OUTPUT_INT (file, gen_rtx (CONST_INT, VOIDmode,
2854: CONST_DOUBLE_LOW (value)));
2855: }
2856: else if (GET_CODE (value) == SYMBOL_REF
2857: || GET_CODE (value) == CONST
2858: || GET_CODE (value) == PLUS)
2859: {
2860: /* Addresses are only 32 bits. */
2861: ASM_OUTPUT_INT (file, const0_rtx);
2862: ASM_OUTPUT_INT (file, value);
2863: }
2864: else
2865: abort ();
2866: }
1.1.1.3 root 2867:
2868: #ifndef CHAR_TYPE_SIZE
2869: #define CHAR_TYPE_SIZE BITS_PER_UNIT
2870: #endif
2871:
2872: #ifndef SHORT_TYPE_SIZE
2873: #define SHORT_TYPE_SIZE (BITS_PER_UNIT * 2)
2874: #endif
2875:
2876: #ifndef INT_TYPE_SIZE
2877: #define INT_TYPE_SIZE BITS_PER_WORD
2878: #endif
2879:
2880: #ifndef LONG_TYPE_SIZE
2881: #define LONG_TYPE_SIZE BITS_PER_WORD
2882: #endif
2883:
2884: #ifndef LONG_LONG_TYPE_SIZE
2885: #define LONG_LONG_TYPE_SIZE (BITS_PER_WORD * 2)
2886: #endif
2887:
2888: #ifndef FLOAT_TYPE_SIZE
2889: #define FLOAT_TYPE_SIZE BITS_PER_WORD
2890: #endif
2891:
2892: #ifndef DOUBLE_TYPE_SIZE
2893: #define DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
2894: #endif
2895:
2896: #ifndef LONG_DOUBLE_TYPE_SIZE
2897: #define LONG_DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
2898: #endif
2899:
2900: unsigned long
2901: sparc_type_code (type)
2902: register tree type;
2903: {
2904: register unsigned long qualifiers = 0;
2905: register unsigned shift = 6;
2906:
2907: for (;;)
2908: {
2909: switch (TREE_CODE (type))
2910: {
2911: case ERROR_MARK:
2912: return qualifiers;
2913:
2914: case ARRAY_TYPE:
2915: qualifiers |= (3 << shift);
2916: shift += 2;
2917: type = TREE_TYPE (type);
2918: break;
2919:
2920: case FUNCTION_TYPE:
2921: case METHOD_TYPE:
2922: qualifiers |= (2 << shift);
2923: shift += 2;
2924: type = TREE_TYPE (type);
2925: break;
2926:
2927: case POINTER_TYPE:
2928: case REFERENCE_TYPE:
2929: case OFFSET_TYPE:
2930: qualifiers |= (1 << shift);
2931: shift += 2;
2932: type = TREE_TYPE (type);
2933: break;
2934:
2935: case RECORD_TYPE:
2936: return (qualifiers | 8);
2937:
2938: case UNION_TYPE:
2939: return (qualifiers | 9);
2940:
2941: case ENUMERAL_TYPE:
2942: return (qualifiers | 10);
1.1 root 2943:
1.1.1.3 root 2944: case VOID_TYPE:
2945: return (qualifiers | 16);
2946:
2947: case INTEGER_TYPE:
2948: /* Carefully distinguish all the standard types of C,
2949: without messing up if the language is not C.
2950: Note that we check only for the names that contain spaces;
2951: other names might occur by coincidence in other languages. */
2952: if (TYPE_NAME (type) != 0
2953: && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
2954: && DECL_NAME (TYPE_NAME (type)) != 0
2955: && TREE_CODE (DECL_NAME (TYPE_NAME (type))) == IDENTIFIER_NODE)
2956: {
2957: char *name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
2958:
2959: if (!strcmp (name, "unsigned char"))
2960: return (qualifiers | 12);
2961: if (!strcmp (name, "signed char"))
2962: return (qualifiers | 2);
2963: if (!strcmp (name, "unsigned int"))
2964: return (qualifiers | 14);
2965: if (!strcmp (name, "short int"))
2966: return (qualifiers | 3);
2967: if (!strcmp (name, "short unsigned int"))
2968: return (qualifiers | 13);
2969: if (!strcmp (name, "long int"))
2970: return (qualifiers | 5);
2971: if (!strcmp (name, "long unsigned int"))
2972: return (qualifiers | 15);
2973: if (!strcmp (name, "long long int"))
2974: return (qualifiers | 5); /* Who knows? */
2975: if (!strcmp (name, "long long unsigned int"))
2976: return (qualifiers | 15); /* Who knows? */
2977: }
2978:
2979: /* Most integer types will be sorted out above, however, for the
2980: sake of special `array index' integer types, the following code
2981: is also provided. */
2982:
2983: if (TYPE_PRECISION (type) == INT_TYPE_SIZE)
2984: return (qualifiers | (TREE_UNSIGNED (type) ? 14 : 4));
2985:
2986: if (TYPE_PRECISION (type) == LONG_TYPE_SIZE)
2987: return (qualifiers | (TREE_UNSIGNED (type) ? 15 : 5));
2988:
2989: if (TYPE_PRECISION (type) == LONG_LONG_TYPE_SIZE)
2990: return (qualifiers | (TREE_UNSIGNED (type) ? 15 : 5));
2991:
2992: if (TYPE_PRECISION (type) == SHORT_TYPE_SIZE)
2993: return (qualifiers | (TREE_UNSIGNED (type) ? 13 : 3));
2994:
2995: if (TYPE_PRECISION (type) == CHAR_TYPE_SIZE)
2996: return (qualifiers | (TREE_UNSIGNED (type) ? 12 : 2));
2997:
2998: abort ();
2999:
3000: case REAL_TYPE:
3001: /* Carefully distinguish all the standard types of C,
3002: without messing up if the language is not C. */
3003: if (TYPE_NAME (type) != 0
3004: && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
3005: && DECL_NAME (TYPE_NAME (type)) != 0
3006: && TREE_CODE (DECL_NAME (TYPE_NAME (type))) == IDENTIFIER_NODE)
3007: {
3008: char *name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
3009:
3010: if (!strcmp (name, "long double"))
3011: return (qualifiers | 7); /* Who knows? */
3012: }
3013:
3014: if (TYPE_PRECISION (type) == DOUBLE_TYPE_SIZE)
3015: return (qualifiers | 7);
3016: if (TYPE_PRECISION (type) == FLOAT_TYPE_SIZE)
3017: return (qualifiers | 6);
3018: if (TYPE_PRECISION (type) == LONG_DOUBLE_TYPE_SIZE)
3019: return (qualifiers | 7); /* Who knows? */
3020: abort ();
3021:
3022: case COMPLEX_TYPE: /* GNU Fortran COMPLEX type. */
1.1.1.4 ! root 3023: /* ??? We need to dinguish between double and float complex types,
! 3024: but I don't know how yet because I can't reach this code from
! 3025: existing front-ends. */
! 3026: return (qualifiers | 7); /* Who knows? */
! 3027:
1.1.1.3 root 3028: case CHAR_TYPE: /* GNU Pascal CHAR type. Not used in C. */
3029: case BOOLEAN_TYPE: /* GNU Fortran BOOLEAN type. */
3030: case FILE_TYPE: /* GNU Pascal FILE type. */
3031: case STRING_TYPE: /* GNU Fortran STRING type. */
3032: case LANG_TYPE: /* ? */
3033: abort ();
3034:
3035: default:
3036: abort (); /* Not a type! */
3037: }
3038: }
3039: }
3040:
1.1.1.4 ! root 3041: /* Subroutines to support a flat (single) register window calling
! 3042: convention. */
! 3043:
! 3044: /* Single-register window sparc stack frames look like:
! 3045:
! 3046: Before call After call
! 3047: +-----------------------+ +-----------------------+
! 3048: high | | | |
! 3049: mem. | | | |
! 3050: | caller's temps. | | caller's temps. |
! 3051: | | | |
! 3052: +-----------------------+ +-----------------------+
! 3053: | | | |
! 3054: | arguments on stack. | | arguments on stack. |
! 3055: | |FP+92->| |
! 3056: +-----------------------+ +-----------------------+
! 3057: | 6 words to save | | 6 words to save |
! 3058: | arguments passed | | arguments passed |
! 3059: | in registers, even | | in registers, even |
! 3060: SP+68->| if not passed. |FP+68->| if not passed. |
! 3061: +-----------------------+ +-----------------------+
! 3062: | 1 word struct addr |FP+64->| 1 word struct addr |
! 3063: +-----------------------+ +-----------------------+
! 3064: | | | |
! 3065: | 16 word reg save area | | 16 word reg save area |
! 3066: SP->| | FP->| |
! 3067: +-----------------------+ +-----------------------+
! 3068: | 4 word area for |
! 3069: FP-16->| fp/alu reg moves |
! 3070: +-----------------------+
! 3071: | |
! 3072: | local variables |
! 3073: | |
! 3074: +-----------------------+
! 3075: | |
! 3076: | fp register save |
! 3077: | |
! 3078: +-----------------------+
! 3079: | |
! 3080: | gp register save |
! 3081: | |
! 3082: +-----------------------+
! 3083: | |
! 3084: | alloca allocations |
! 3085: | |
! 3086: +-----------------------+
! 3087: | |
! 3088: | arguments on stack |
! 3089: SP+92->| |
! 3090: +-----------------------+
! 3091: | 6 words to save |
! 3092: | arguments passed |
! 3093: | in registers, even |
! 3094: low SP+68->| if not passed. |
! 3095: memory +-----------------------+
! 3096: SP+64->| 1 word struct addr |
! 3097: +-----------------------+
! 3098: | |
! 3099: I 16 word reg save area |
! 3100: SP->| |
! 3101: +-----------------------+ */
! 3102:
! 3103: /* Structure to be filled in by sparc_frw_compute_frame_size with register
! 3104: save masks, and offsets for the current function. */
! 3105:
! 3106: struct sparc_frame_info
! 3107: {
! 3108: unsigned long total_size; /* # bytes that the entire frame takes up. */
! 3109: unsigned long var_size; /* # bytes that variables take up. */
! 3110: unsigned long args_size; /* # bytes that outgoing arguments take up. */
! 3111: unsigned long extra_size; /* # bytes of extra gunk. */
! 3112: unsigned int gp_reg_size; /* # bytes needed to store gp regs. */
! 3113: unsigned int fp_reg_size; /* # bytes needed to store fp regs. */
! 3114: unsigned long mask; /* Mask of saved gp registers. */
! 3115: unsigned long fmask; /* Mask of saved fp registers. */
! 3116: unsigned long gp_sp_offset; /* Offset from new sp to store gp regs. */
! 3117: unsigned long fp_sp_offset; /* Offset from new sp to store fp regs. */
! 3118: int initialized; /* Nonzero if frame size already calculated. */
! 3119: };
! 3120:
! 3121: /* Current frame information calculated by sparc_frw_compute_frame_size. */
! 3122: struct sparc_frame_info current_frame_info;
! 3123:
! 3124: /* Zero structure to initialize current_frame_info. */
! 3125: struct sparc_frame_info zero_frame_info;
! 3126:
! 3127: /* Tell prologue and epilogue if register REGNO should be saved / restored. */
! 3128:
! 3129: #define MUST_SAVE_REGISTER(regno) \
! 3130: ((regs_ever_live[regno] && !call_used_regs[regno]) \
! 3131: || (regno == FRAME_POINTER_REGNUM && frame_pointer_needed) \
! 3132: || (regno == 15 && regs_ever_live[15]))
! 3133:
! 3134: #ifndef SPARC_STACK_ALIGN
! 3135: #define STACK_BYTES (STACK_BOUNDARY / 8)
! 3136: #define SPARC_STACK_ALIGN(X) (((X) + STACK_BYTES - 1) & -STACK_BYTES)
! 3137: #endif
1.1.1.3 root 3138:
1.1.1.4 ! root 3139: /* Return the bytes needed to compute the frame pointer from the current
! 3140: stack pointer. */
! 3141:
! 3142: unsigned long
! 3143: sparc_frw_compute_frame_size (size)
! 3144: int size; /* # of var. bytes allocated. */
! 3145: {
! 3146: int regno;
! 3147: unsigned long total_size; /* # bytes that the entire frame takes up. */
! 3148: unsigned long var_size; /* # bytes that variables take up. */
! 3149: unsigned long args_size; /* # bytes that outgoing arguments take up. */
! 3150: unsigned long extra_size; /* # extra bytes. */
! 3151: unsigned int gp_reg_size; /* # bytes needed to store gp regs. */
! 3152: unsigned int fp_reg_size; /* # bytes needed to store fp regs. */
! 3153: unsigned long mask; /* Mask of saved gp registers. */
! 3154: unsigned long fmask; /* Mask of saved fp registers. */
! 3155:
! 3156: /* This is the size of the 16 word reg save area, 1 word struct addr
! 3157: area, and 4 word fp/alu register copy area. */
! 3158: extra_size = -STARTING_FRAME_OFFSET + FIRST_PARM_OFFSET(0);
! 3159: var_size = size;
! 3160: /* Also include the size needed for the 6 parameter registers. */
! 3161: args_size = current_function_outgoing_args_size + 24;
! 3162: total_size = var_size + args_size + extra_size;
! 3163: gp_reg_size = 0;
! 3164: fp_reg_size = 0;
! 3165: mask = 0;
! 3166: fmask = 0;
! 3167:
! 3168: /* Calculate space needed for gp registers. */
! 3169: for (regno = 1; regno <= 31; regno++)
! 3170: {
! 3171: if (MUST_SAVE_REGISTER (regno))
! 3172: {
! 3173: if ((regno & 0x1) == 0 && MUST_SAVE_REGISTER (regno+1))
! 3174: {
! 3175: if (gp_reg_size % 8 != 0)
! 3176: gp_reg_size += UNITS_PER_WORD;
! 3177: gp_reg_size += 2 * UNITS_PER_WORD;
! 3178: mask |= 3 << regno;
! 3179: regno++;
! 3180: }
! 3181: else
! 3182: {
! 3183: gp_reg_size += UNITS_PER_WORD;
! 3184: mask |= 1 << regno;
! 3185: }
! 3186: }
! 3187: }
! 3188: /* Add extra word in case we have to align the space to a double word
! 3189: boundary. */
! 3190: if (gp_reg_size != 0)
! 3191: gp_reg_size += UNITS_PER_WORD;
! 3192:
! 3193: /* Calculate space needed for fp registers. */
! 3194: for (regno = 32; regno <= 63; regno++)
! 3195: {
! 3196: if (regs_ever_live[regno] && !call_used_regs[regno])
! 3197: {
! 3198: fp_reg_size += UNITS_PER_WORD;
! 3199: fmask |= 1 << (regno - 32);
! 3200: }
! 3201: }
! 3202:
! 3203: total_size += gp_reg_size + fp_reg_size;
! 3204:
! 3205: if (total_size == extra_size)
! 3206: total_size = extra_size = 0;
! 3207:
! 3208: total_size = SPARC_STACK_ALIGN (total_size);
! 3209:
! 3210: /* Save other computed information. */
! 3211: current_frame_info.total_size = total_size;
! 3212: current_frame_info.var_size = var_size;
! 3213: current_frame_info.args_size = args_size;
! 3214: current_frame_info.extra_size = extra_size;
! 3215: current_frame_info.gp_reg_size = gp_reg_size;
! 3216: current_frame_info.fp_reg_size = fp_reg_size;
! 3217: current_frame_info.mask = mask;
! 3218: current_frame_info.fmask = fmask;
! 3219: current_frame_info.initialized = reload_completed;
! 3220:
! 3221: if (mask)
! 3222: {
! 3223: unsigned long offset = args_size;
! 3224: if (extra_size)
! 3225: offset += FIRST_PARM_OFFSET(0);
! 3226: current_frame_info.gp_sp_offset = offset;
! 3227: }
! 3228:
! 3229: if (fmask)
! 3230: {
! 3231: unsigned long offset = args_size + gp_reg_size;
! 3232: if (extra_size)
! 3233: offset += FIRST_PARM_OFFSET(0);
! 3234: current_frame_info.fp_sp_offset = offset;
! 3235: }
! 3236:
! 3237: /* Ok, we're done. */
! 3238: return total_size;
! 3239: }
! 3240:
! 3241: /* Common code to save/restore registers. */
1.1.1.3 root 3242:
3243: void
1.1.1.4 ! root 3244: sparc_frw_save_restore (file, word_op, doubleword_op)
! 3245: FILE *file; /* Stream to write to. */
! 3246: char *word_op; /* Operation to do for one word. */
! 3247: char *doubleword_op; /* Operation to do for doubleword. */
! 3248: {
! 3249: int regno;
! 3250: unsigned long mask = current_frame_info.mask;
! 3251: unsigned long fmask = current_frame_info.fmask;
! 3252: unsigned long gp_offset;
! 3253: unsigned long fp_offset;
! 3254: unsigned long max_offset;
! 3255: char *base_reg;
1.1.1.3 root 3256:
1.1.1.4 ! root 3257: if (mask == 0 && fmask == 0)
! 3258: return;
! 3259:
! 3260: base_reg = reg_names[STACK_POINTER_REGNUM];
! 3261: gp_offset = current_frame_info.gp_sp_offset;
! 3262: fp_offset = current_frame_info.fp_sp_offset;
! 3263: max_offset = (gp_offset > fp_offset) ? gp_offset : fp_offset;
! 3264:
! 3265: /* Deal with calling functions with a large structure. */
! 3266: if (max_offset >= 4096)
! 3267: {
! 3268: char *temp = "%g2";
! 3269: fprintf (file, "\tset %ld,%s\n", max_offset, temp);
! 3270: fprintf (file, "\tadd %s,%s,%s\n", temp, base_reg, temp);
! 3271: base_reg = temp;
! 3272: gp_offset = max_offset - gp_offset;
! 3273: fp_offset = max_offset - fp_offset;
! 3274: }
! 3275:
! 3276: /* Save registers starting from high to low. The debuggers prefer
! 3277: at least the return register be stored at func+4, and also it
! 3278: allows us not to need a nop in the epilog if at least one
! 3279: register is reloaded in addition to return address. */
! 3280:
! 3281: if (mask || frame_pointer_needed)
1.1.1.3 root 3282: {
1.1.1.4 ! root 3283: for (regno = 1; regno <= 31; regno++)
1.1.1.3 root 3284: {
1.1.1.4 ! root 3285: if ((mask & (1L << regno)) != 0
! 3286: || (regno == FRAME_POINTER_REGNUM && frame_pointer_needed))
1.1.1.3 root 3287: {
1.1.1.4 ! root 3288: if ((regno & 0x1) == 0 && ((mask & (1L << regno+1)) != 0))
1.1.1.3 root 3289: {
1.1.1.4 ! root 3290: if (gp_offset % 8 != 0)
! 3291: gp_offset += UNITS_PER_WORD;
! 3292:
! 3293: if (word_op[0] == 's')
! 3294: fprintf (file, "\t%s %s,[%s+%d]\n",
! 3295: doubleword_op, reg_names[regno],
! 3296: base_reg, gp_offset);
! 3297: else
! 3298: fprintf (file, "\t%s [%s+%d],%s\n",
! 3299: doubleword_op, base_reg, gp_offset,
! 3300: reg_names[regno]);
! 3301:
! 3302: gp_offset += 2 * UNITS_PER_WORD;
! 3303: regno++;
! 3304: }
! 3305: else
! 3306: {
! 3307: if (word_op[0] == 's')
! 3308: fprintf (file, "\t%s %s,[%s+%d]\n",
! 3309: word_op, reg_names[regno],
! 3310: base_reg, gp_offset);
! 3311: else
! 3312: fprintf (file, "\t%s [%s+%d],%s\n",
! 3313: word_op, base_reg, gp_offset, reg_names[regno]);
! 3314:
! 3315: gp_offset += UNITS_PER_WORD;
1.1.1.3 root 3316: }
3317: }
3318: }
3319: }
3320:
1.1.1.4 ! root 3321: if (fmask)
1.1.1.3 root 3322: {
1.1.1.4 ! root 3323: for (regno = 32; regno <= 63; regno++)
1.1.1.3 root 3324: {
1.1.1.4 ! root 3325: if ((fmask & (1L << (regno - 32))) != 0)
! 3326: {
! 3327: if (word_op[0] == 's')
! 3328: fprintf (file, "\t%s %s,[%s+%d]\n",
! 3329: word_op, reg_names[regno],
! 3330: base_reg, gp_offset);
! 3331: else
! 3332: fprintf (file, "\t%s [%s+%d],%s\n",
! 3333: word_op, base_reg, gp_offset, reg_names[regno]);
! 3334:
! 3335: fp_offset += UNITS_PER_WORD;
! 3336: }
1.1.1.3 root 3337: }
1.1.1.4 ! root 3338: }
! 3339: }
! 3340:
! 3341: /* Set up the stack and frame (if desired) for the function. */
! 3342:
! 3343: void
! 3344: sparc_frw_output_function_prologue (file, size, ignored)
! 3345: FILE *file;
! 3346: int size;
! 3347: {
! 3348: extern char call_used_regs[];
! 3349: int regno;
! 3350: int tsize;
! 3351: char *sp_str = reg_names[STACK_POINTER_REGNUM];
! 3352: frame_base_name
! 3353: = (!frame_pointer_needed) ? "%sp+80" : reg_names[FRAME_POINTER_REGNUM];
! 3354:
! 3355: fprintf (file, "\t!#PROLOGUE# 0\n");
! 3356:
! 3357: size = SPARC_STACK_ALIGN (size);
! 3358: tsize = (! current_frame_info.initialized
! 3359: ? sparc_frw_compute_frame_size (size)
! 3360: : current_frame_info.total_size);
! 3361:
! 3362: if (tsize > 0)
! 3363: {
! 3364: if (tsize <= 4095)
! 3365: fprintf (file,
! 3366: "\tsub %s,%d,%s\t\t!# vars= %d, regs= %d/%d, args = %d, extra= %d\n",
! 3367: sp_str, tsize, sp_str, current_frame_info.var_size,
! 3368: current_frame_info.gp_reg_size / 4,
! 3369: current_frame_info.fp_reg_size / 8,
! 3370: current_function_outgoing_args_size,
! 3371: current_frame_info.extra_size);
! 3372: else
! 3373: fprintf (file,
! 3374: "\tset %d,%s\n\tsub\t%s,%s,%s\t\t!# vars= %d, regs= %d/%d, args = %d, sfo= %d\n",
! 3375: tsize, "%g1", sp_str, "%g1",
! 3376: sp_str, current_frame_info.var_size,
! 3377: current_frame_info.gp_reg_size / 4,
! 3378: current_frame_info.fp_reg_size / 8,
! 3379: current_function_outgoing_args_size,
! 3380: current_frame_info.extra_size);
! 3381: }
! 3382:
! 3383: sparc_frw_save_restore (file, "st", "std");
! 3384:
! 3385: if (frame_pointer_needed)
! 3386: {
! 3387: if (tsize <= 4095)
! 3388: fprintf (file, "\tadd %s,%d,%s\t!# set up frame pointer\n", sp_str,
! 3389: tsize, frame_base_name);
1.1.1.3 root 3390: else
1.1.1.4 ! root 3391: fprintf (file, "\tadd %s,%s,%s\t!# set up frame pointer\n", sp_str,
! 3392: "%g1", frame_base_name);
! 3393: }
! 3394: }
! 3395:
! 3396: /* Do any necessary cleanup after a function to restore stack, frame,
! 3397: and regs. */
1.1.1.3 root 3398:
1.1.1.4 ! root 3399: void
! 3400: sparc_frw_output_function_epilogue (file, size, ignored1, ignored2)
! 3401: FILE *file;
! 3402: int size;
! 3403: {
! 3404: extern FILE *asm_out_data_file, *asm_out_file;
! 3405: extern char call_used_regs[];
! 3406: extern int frame_pointer_needed;
! 3407: int tsize;
! 3408: char *sp_str = reg_names[STACK_POINTER_REGNUM];
! 3409: char *t1_str = "%g1";
! 3410: rtx epilogue_delay = current_function_epilogue_delay_list;
! 3411: int noepilogue = FALSE;
! 3412: int load_nop = FALSE;
! 3413: int load_only_r15;
! 3414:
! 3415: /* The epilogue does not depend on any registers, but the stack
! 3416: registers, so we assume that if we have 1 pending nop, it can be
! 3417: ignored, and 2 it must be filled (2 nops occur for integer
! 3418: multiply and divide). */
! 3419:
! 3420: size = SPARC_STACK_ALIGN (size);
! 3421: tsize = (!current_frame_info.initialized
! 3422: ? sparc_frw_compute_frame_size (size)
! 3423: : current_frame_info.total_size);
! 3424:
! 3425: if (tsize == 0 && epilogue_delay == 0)
! 3426: {
! 3427: rtx insn = get_last_insn ();
! 3428:
! 3429: /* If the last insn was a BARRIER, we don't have to write any code
! 3430: because a jump (aka return) was put there. */
! 3431: if (GET_CODE (insn) == NOTE)
! 3432: insn = prev_nonnote_insn (insn);
! 3433: if (insn && GET_CODE (insn) == BARRIER)
! 3434: noepilogue = TRUE;
! 3435: }
! 3436:
! 3437: if (!noepilogue)
! 3438: {
! 3439: /* In the reload sequence, we don't need to fill the load delay
! 3440: slots for most of the loads, also see if we can fill the final
! 3441: delay slot if not otherwise filled by the reload sequence. */
! 3442:
! 3443: if (tsize > 4095)
! 3444: fprintf (file, "\tset %d,%s\n", tsize, t1_str);
! 3445:
! 3446: if (frame_pointer_needed)
! 3447: {
! 3448: char *fp_str = reg_names[FRAME_POINTER_REGNUM];
! 3449: if (tsize > 4095)
! 3450: fprintf (file,"\tsub %s,%s,%s\t\t!# sp not trusted here\n",
! 3451: fp_str, t1_str, sp_str);
! 3452: else
! 3453: fprintf (file,"\tsub %s,%d,%s\t\t!# sp not trusted here\n",
! 3454: fp_str, tsize, sp_str);
1.1.1.3 root 3455: }
1.1.1.4 ! root 3456:
! 3457: sparc_frw_save_restore (file, "ld", "ldd");
! 3458:
! 3459: load_only_r15 = (current_frame_info.mask == (1 << 15)
! 3460: && current_frame_info.fmask == 0);
! 3461:
! 3462: if (current_function_returns_struct)
! 3463: fprintf (file, "\tjmp %%o7+12\n");
1.1.1.3 root 3464: else
1.1.1.4 ! root 3465: fprintf (file, "\tretl\n");
1.1.1.3 root 3466:
1.1.1.4 ! root 3467: /* If the only register saved is the return address, we need a
! 3468: nop, unless we have an instruction to put into it. Otherwise
! 3469: we don't since reloading multiple registers doesn't reference
! 3470: the register being loaded. */
1.1.1.3 root 3471:
1.1.1.4 ! root 3472: if (epilogue_delay)
1.1.1.3 root 3473: {
1.1.1.4 ! root 3474: if (tsize)
! 3475: abort ();
! 3476: final_scan_insn (XEXP (epilogue_delay, 0), file, 1, -2, 1);
1.1.1.3 root 3477: }
3478:
1.1.1.4 ! root 3479: else if (tsize > 4095)
! 3480: fprintf (file, "\tadd %s,%s,%s\n", sp_str, t1_str, sp_str);
1.1.1.3 root 3481:
1.1.1.4 ! root 3482: else if (tsize > 0)
! 3483: fprintf (file, "\tadd %s,%d,%s\n", sp_str, tsize, sp_str);
1.1.1.3 root 3484:
1.1.1.4 ! root 3485: else
! 3486: fprintf (file, "\tnop\n");
1.1.1.3 root 3487: }
1.1.1.4 ! root 3488:
! 3489: /* Reset state info for each function. */
! 3490: current_frame_info = zero_frame_info;
! 3491: }
! 3492:
! 3493: /* Define the number of delay slots needed for the function epilogue.
! 3494:
! 3495: On the sparc, we need a slot if either no stack has been allocated,
! 3496: or the only register saved is the return register. */
! 3497:
! 3498: int
! 3499: sparc_frw_epilogue_delay_slots ()
! 3500: {
! 3501: if (!current_frame_info.initialized)
! 3502: (void) sparc_frw_compute_frame_size (get_frame_size ());
! 3503:
! 3504: if (current_frame_info.total_size == 0)
! 3505: return 1;
! 3506:
! 3507: if (current_frame_info.mask == (1 << 15) && current_frame_info.fmask == 0)
! 3508: return 1;
! 3509:
! 3510: return 0;
! 3511: }
! 3512:
! 3513: /* Return true is TRIAL is a valid insn for the epilogue delay slot.
! 3514: Any single length instruction which doesn't reference the stack or frame
! 3515: pointer is OK. */
! 3516:
! 3517: int
! 3518: sparc_frw_eligible_for_epilogue_delay (trial, slot)
! 3519: rtx trial;
! 3520: int slot;
! 3521: {
! 3522: if (get_attr_length (trial) == 1
! 3523: && ! reg_mentioned_p (stack_pointer_rtx, PATTERN (trial))
! 3524: && ! reg_mentioned_p (frame_pointer_rtx, PATTERN (trial)))
! 3525: return 1;
! 3526: return 0;
1.1.1.3 root 3527: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.