|
|
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"
23: #include "rtl.h"
24: #include "regs.h"
25: #include "hard-reg-set.h"
26: #include "real.h"
27: #include "insn-config.h"
28: #include "conditions.h"
29: #include "insn-flags.h"
30: #include "output.h"
31: #include "insn-attr.h"
32: #include "flags.h"
33: #include "expr.h"
34: #include "recog.h"
35:
36: /* Global variables for machine-dependent things. */
37:
38: /* Save the operands last given to a compare for use when we
39: generate a scc or bcc insn. */
40:
41: rtx sparc_compare_op0, sparc_compare_op1;
42:
43: /* We may need an epilogue if we spill too many registers.
44: If this is non-zero, then we branch here for the epilogue. */
45: static rtx leaf_label;
46:
47: #ifdef LEAF_REGISTERS
48:
49: /* Vector to say how input registers are mapped to output
50: registers. FRAME_POINTER_REGNUM cannot be remapped by
51: this function to eliminate it. You must use -fomit-frame-pointer
52: to get that. */
53: char leaf_reg_remap[] =
54: { 0, 1, 2, 3, 4, 5, 6, 7,
55: -1, -1, -1, -1, -1, -1, 14, -1,
56: -1, -1, -1, -1, -1, -1, -1, -1,
57: 8, 9, 10, 11, 12, 13, -1, 15,
58:
59: 32, 33, 34, 35, 36, 37, 38, 39,
60: 40, 41, 42, 43, 44, 45, 46, 47,
61: 48, 49, 50, 51, 52, 53, 54, 55,
62: 56, 57, 58, 59, 60, 61, 62, 63};
63:
64: char leaf_reg_backmap[] =
65: { 0, 1, 2, 3, 4, 5, 6, 7,
66: 24, 25, 26, 27, 28, 29, 14, 31,
67: -1, -1, -1, -1, -1, -1, -1, -1,
68: -1, -1, -1, -1, -1, -1, -1, -1,
69:
70: 32, 33, 34, 35, 36, 37, 38, 39,
71: 40, 41, 42, 43, 44, 45, 46, 47,
72: 48, 49, 50, 51, 52, 53, 54, 55,
73: 56, 57, 58, 59, 60, 61, 62, 63};
74: #endif
75:
76: /* Global variables set by FUNCTION_PROLOGUE. */
77: /* Size of frame. Need to know this to emit return insns from
78: leaf procedures. */
79: int apparent_fsize;
80: int actual_fsize;
81:
82: /* Name of where we pretend to think the frame pointer points.
83: Normally, this is "%fp", but if we are in a leaf procedure,
84: this is "%sp+something". */
85: char *frame_base_name;
86:
87: static rtx find_addr_reg ();
88:
89: /* Return non-zero only if OP is a register of mode MODE,
90: or const0_rtx. */
91: int
92: reg_or_0_operand (op, mode)
93: rtx op;
94: enum machine_mode mode;
95: {
96: if (op == const0_rtx || register_operand (op, mode))
97: return 1;
98: if (GET_CODE (op) == CONST_DOUBLE
99: && CONST_DOUBLE_HIGH (op) == 0
100: && CONST_DOUBLE_LOW (op) == 0)
101: return 1;
102: return 0;
103: }
104:
105: /* Nonzero if OP can appear as the dest of a RESTORE insn. */
106: int
107: restore_operand (op, mode)
108: rtx op;
109: enum machine_mode mode;
110: {
111: return (GET_CODE (op) == REG && GET_MODE (op) == mode
112: && (REGNO (op) < 8 || (REGNO (op) >= 24 && REGNO (op) < 32)));
113: }
114:
115: /* PC-relative call insn on SPARC is independent of `memory_operand'. */
116:
117: int
118: call_operand (op, mode)
119: rtx op;
120: enum machine_mode mode;
121: {
122: if (GET_CODE (op) != MEM)
123: abort ();
124: op = XEXP (op, 0);
125: return (REG_P (op) || CONSTANT_P (op));
126: }
127:
128: int
129: call_operand_address (op, mode)
130: rtx op;
131: enum machine_mode mode;
132: {
133: return (REG_P (op) || CONSTANT_P (op));
134: }
135:
136: /* Returns 1 if OP is either a symbol reference or a sum of a symbol
137: reference and a constant. */
138:
139: int
140: symbolic_operand (op, mode)
141: register rtx op;
142: enum machine_mode mode;
143: {
144: switch (GET_CODE (op))
145: {
146: case SYMBOL_REF:
147: case LABEL_REF:
148: return 1;
149:
150: case CONST:
151: op = XEXP (op, 0);
152: return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
153: || GET_CODE (XEXP (op, 0)) == LABEL_REF)
154: && GET_CODE (XEXP (op, 1)) == CONST_INT);
155:
156: /* This clause seems to be irrelevant. */
157: case CONST_DOUBLE:
158: return GET_MODE (op) == mode;
159:
160: default:
161: return 0;
162: }
163: }
164:
165: /* Return truth value of statement that OP is a symbolic memory
166: operand of mode MODE. */
167:
168: int
169: symbolic_memory_operand (op, mode)
170: rtx op;
171: enum machine_mode mode;
172: {
173: if (GET_CODE (op) == SUBREG)
174: op = SUBREG_REG (op);
175: if (GET_CODE (op) != MEM)
176: return 0;
177: op = XEXP (op, 0);
178: return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST
179: || GET_CODE (op) == HIGH || GET_CODE (op) == LABEL_REF);
180: }
181:
182: /* Return 1 if the operand is either a register or a memory operand that is
183: not symbolic. */
184:
185: int
186: reg_or_nonsymb_mem_operand (op, mode)
187: register rtx op;
188: enum machine_mode mode;
189: {
190: if (register_operand (op, mode))
191: return 1;
192:
193: if (memory_operand (op, mode) && ! symbolic_memory_operand (op, mode))
194: return 1;
195:
196: return 0;
197: }
198:
199: int
200: sparc_operand (op, mode)
201: rtx op;
202: enum machine_mode mode;
203: {
204: if (register_operand (op, mode))
205: return 1;
206: if (GET_CODE (op) == CONST_INT)
207: return SMALL_INT (op);
208: if (GET_MODE (op) != mode)
209: return 0;
210: if (GET_CODE (op) == SUBREG)
211: op = SUBREG_REG (op);
212: if (GET_CODE (op) != MEM)
213: return 0;
214:
215: op = XEXP (op, 0);
216: if (GET_CODE (op) == LO_SUM)
217: return (GET_CODE (XEXP (op, 0)) == REG
218: && symbolic_operand (XEXP (op, 1), Pmode));
219: return memory_address_p (mode, op);
220: }
221:
222: int
223: move_operand (op, mode)
224: rtx op;
225: enum machine_mode mode;
226: {
227: if (mode == DImode && arith_double_operand (op, mode))
228: return 1;
229: if (register_operand (op, mode))
230: return 1;
231: if (GET_CODE (op) == CONST_INT)
232: return (SMALL_INT (op) || (INTVAL (op) & 0x3ff) == 0);
233:
234: if (GET_MODE (op) != mode)
235: return 0;
236: if (GET_CODE (op) == SUBREG)
237: op = SUBREG_REG (op);
238: if (GET_CODE (op) != MEM)
239: return 0;
240: op = XEXP (op, 0);
241: if (GET_CODE (op) == LO_SUM)
242: return (register_operand (XEXP (op, 0), Pmode)
243: && CONSTANT_P (XEXP (op, 1)));
244: return memory_address_p (mode, op);
245: }
246:
247: int
248: move_pic_label (op, mode)
249: rtx op;
250: enum machine_mode mode;
251: {
252: /* Special case for PIC. */
253: if (flag_pic && GET_CODE (op) == LABEL_REF)
254: return 1;
255: return 0;
256: }
257:
258: /* The rtx for the global offset table which is a special form
259: that *is* a position independent symbolic constant. */
260: rtx pic_pc_rtx;
261:
262: /* Ensure that we are not using patterns that are not OK with PIC. */
263:
264: int
265: check_pic (i)
266: int i;
267: {
268: switch (flag_pic)
269: {
270: case 1:
271: if (GET_CODE (recog_operand[i]) == SYMBOL_REF
272: || (GET_CODE (recog_operand[i]) == CONST
273: && ! rtx_equal_p (pic_pc_rtx, recog_operand[i])))
274: abort ();
275: case 2:
276: default:
277: return 1;
278: }
279: }
280:
281: /* Return true if X is an address which needs a temporary register when
282: reloaded while generating PIC code. */
283:
284: int
285: pic_address_needs_scratch (x)
286: rtx x;
287: {
288: /* An address which is a symbolic plus a non SMALL_INT needs a temp reg. */
289: if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS
290: && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
291: && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
292: && ! SMALL_INT (XEXP (XEXP (x, 0), 1)))
293: return 1;
294:
295: return 0;
296: }
297:
298: int
299: memop (op, mode)
300: rtx op;
301: enum machine_mode mode;
302: {
303: if (GET_CODE (op) == MEM)
304: return (mode == VOIDmode || mode == GET_MODE (op));
305: return 0;
306: }
307:
308: /* Return truth value of whether OP is EQ or NE. */
309:
310: int
311: eq_or_neq (op, mode)
312: rtx op;
313: enum machine_mode mode;
314: {
315: return (GET_CODE (op) == EQ || GET_CODE (op) == NE);
316: }
317:
318: /* Return 1 if this is a comparison operator, but not an EQ, NE, GEU,
319: or LTU for non-floating-point. We handle those specially. */
320:
321: int
322: normal_comp_operator (op, mode)
323: rtx op;
324: enum machine_mode mode;
325: {
326: enum rtx_code code = GET_CODE (op);
327:
328: if (GET_RTX_CLASS (code) != '<')
329: return 0;
330:
331: if (GET_MODE (XEXP (op, 0)) == CCFPmode)
332: return 1;
333:
334: return (code != NE && code != EQ && code != GEU && code != LTU);
335: }
336:
337: /* Return 1 if this is a comparison operator. This allows the use of
338: MATCH_OPERATOR to recognize all the branch insns. */
339:
340: int
341: noov_compare_op (op, mode)
342: register rtx op;
343: enum machine_mode mode;
344: {
345: enum rtx_code code = GET_CODE (op);
346:
347: if (GET_RTX_CLASS (code) != '<')
348: return 0;
349:
350: if (GET_MODE (XEXP (op, 0)) == CC_NOOVmode)
351: /* These are the only branches which work with CC_NOOVmode. */
352: return (code == EQ || code == NE || code == GE || code == LT);
353: return 1;
354: }
355:
356: /* Return 1 if this is a SIGN_EXTEND or ZERO_EXTEND operation. */
357:
358: int
359: extend_op (op, mode)
360: rtx op;
361: enum machine_mode mode;
362: {
363: return GET_CODE (op) == SIGN_EXTEND || GET_CODE (op) == ZERO_EXTEND;
364: }
365:
366: /* Return nonzero if OP is an operator of mode MODE which can set
367: the condition codes explicitly. We do not include PLUS and MINUS
368: because these require CC_NOOVmode, which we handle explicitly. */
369:
370: int
371: cc_arithop (op, mode)
372: rtx op;
373: enum machine_mode mode;
374: {
375: if (GET_CODE (op) == AND
376: || GET_CODE (op) == IOR
377: || GET_CODE (op) == XOR)
378: return 1;
379:
380: return 0;
381: }
382:
383: /* Return nonzero if OP is an operator of mode MODE which can bitwise
384: complement its second operand and set the condition codes explicitly. */
385:
386: int
387: cc_arithopn (op, mode)
388: rtx op;
389: enum machine_mode mode;
390: {
391: /* XOR is not here because combine canonicalizes (xor (not ...) ...)
392: and (xor ... (not ...)) to (not (xor ...)). */
393: return (GET_CODE (op) == AND
394: || GET_CODE (op) == IOR);
395: }
396:
397: /* Return truth value of whether OP can be used as an operands in a three
398: address arithmetic insn (such as add %o1,7,%l2) of mode MODE. */
399:
400: int
401: arith_operand (op, mode)
402: rtx op;
403: enum machine_mode mode;
404: {
405: return (register_operand (op, mode)
406: || (GET_CODE (op) == CONST_INT && SMALL_INT (op)));
407: }
408:
409: /* Return truth value of whether OP is a register or a CONST_DOUBLE. */
410:
411: int
412: arith_double_operand (op, mode)
413: rtx op;
414: enum machine_mode mode;
415: {
416: return (register_operand (op, mode)
417: || (GET_CODE (op) == CONST_DOUBLE
418: && (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
419: && (unsigned) (CONST_DOUBLE_LOW (op) + 0x1000) < 0x2000
420: && ((CONST_DOUBLE_HIGH (op) == -1
421: && (CONST_DOUBLE_LOW (op) & 0x1000) == 0x1000)
422: || (CONST_DOUBLE_HIGH (op) == 0
423: && (CONST_DOUBLE_LOW (op) & 0x1000) == 0)))
424: || (GET_CODE (op) == CONST_INT
425: && (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
426: && (unsigned) (INTVAL (op) + 0x1000) < 0x2000));
427: }
428:
429: /* Return truth value of whether OP is a integer which fits the
430: range constraining immediate operands in three-address insns. */
431:
432: int
433: small_int (op, mode)
434: rtx op;
435: enum machine_mode mode;
436: {
437: return (GET_CODE (op) == CONST_INT && SMALL_INT (op));
438: }
439:
440: /* Return truth value of statement that OP is a call-clobbered register. */
441: int
442: clobbered_register (op, mode)
443: rtx op;
444: enum machine_mode mode;
445: {
446: return (GET_CODE (op) == REG && call_used_regs[REGNO (op)]);
447: }
448:
449: /* X and Y are two things to compare using CODE. Emit the compare insn and
450: return the rtx for register 0 in the proper mode. */
451:
452: rtx
453: gen_compare_reg (code, x, y)
454: enum rtx_code code;
455: rtx x, y;
456: {
457: enum machine_mode mode = SELECT_CC_MODE (code, x);
458: rtx cc_reg = gen_rtx (REG, mode, 0);
459:
460: emit_insn (gen_rtx (SET, VOIDmode, cc_reg,
461: gen_rtx (COMPARE, mode, x, y)));
462:
463: return cc_reg;
464: }
465:
466: /* Return nonzero if a return peephole merging return with
467: setting of output register is ok. */
468: int
469: leaf_return_peephole_ok ()
470: {
471: return (actual_fsize == 0);
472: }
473:
474: /* Return nonzero if TRIAL can go into the function epilogue's
475: delay slot. SLOT is the slot we are trying to fill. */
476:
477: int
478: eligible_for_epilogue_delay (trial, slot)
479: rtx trial;
480: int slot;
481: {
482: static char *this_function_name;
483: rtx pat, src;
484:
485: if (slot >= 1)
486: return 0;
487: if (GET_CODE (trial) != INSN
488: || GET_CODE (PATTERN (trial)) != SET)
489: return 0;
490: if (get_attr_length (trial) != 1)
491: return 0;
492:
493: /* In the case of a true leaf function, anything can
494: go into the delay slot. */
495: if (leaf_function)
496: {
497: if (leaf_return_peephole_ok ())
498: return (get_attr_in_branch_delay (trial) == IN_BRANCH_DELAY_TRUE);
499: return 0;
500: }
501:
502: /* Otherwise, only operations which can be done in tandem with
503: a `restore' insn can go into the delay slot. */
504: pat = PATTERN (trial);
505: if (GET_CODE (SET_DEST (pat)) != REG
506: || REGNO (SET_DEST (pat)) == 0
507: || (leaf_function
508: && REGNO (SET_DEST (pat)) < 32
509: && REGNO (SET_DEST (pat)) >= 16)
510: || (! leaf_function
511: && (REGNO (SET_DEST (pat)) >= 32
512: || REGNO (SET_DEST (pat)) < 24)))
513: return 0;
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. */
752: global_offset_table = gen_rtx (SYMBOL_REF, Pmode, "*__GLOBAL_OFFSET_TABLE_");
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: }
941: if (GET_CODE (operands[1]) == MEM)
942: return "ld %1,%0";
943: if (GET_CODE (operands[1]) == CONST_INT
944: && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
945: {
946: int i = INTVAL (operands[1]);
947:
948: /* If all low order 12 bits are clear, then we only need a single
949: sethi insn to load the constant. */
950: if (i & 0x00000FFF)
951: return "sethi %%hi(%a1),%0\n\tor %0,%%lo(%a1),%0";
952: else
953: return "sethi %%hi(%a1),%0";
954: }
955: /* ??? Wrong if target is DImode? */
956: return "mov %1,%0";
957: }
958:
959: /* Output assembler code to perform a doubleword move insn
960: with operands OPERANDS. */
961:
962: char *
963: output_move_double (operands)
964: rtx *operands;
965: {
966: enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
967: rtx latehalf[2];
968: rtx addreg0 = 0, addreg1 = 0;
969:
970: /* First classify both operands. */
971:
972: if (REG_P (operands[0]))
973: optype0 = REGOP;
974: else if (offsettable_memref_p (operands[0]))
975: optype0 = OFFSOP;
976: else if (GET_CODE (operands[0]) == MEM)
977: optype0 = MEMOP;
978: else
979: optype0 = RNDOP;
980:
981: if (REG_P (operands[1]))
982: optype1 = REGOP;
983: else if (CONSTANT_P (operands[1]))
984: optype1 = CNSTOP;
985: else if (offsettable_memref_p (operands[1]))
986: optype1 = OFFSOP;
987: else if (GET_CODE (operands[1]) == MEM)
988: optype1 = MEMOP;
989: else
990: optype1 = RNDOP;
991:
992: /* Check for the cases that the operand constraints are not
993: supposed to allow to happen. Abort if we get one,
994: because generating code for these cases is painful. */
995:
996: if (optype0 == RNDOP || optype1 == RNDOP)
997: abort ();
998:
999: /* If an operand is an unoffsettable memory ref, find a register
1000: we can increment temporarily to make it refer to the second word. */
1001:
1002: if (optype0 == MEMOP)
1003: addreg0 = find_addr_reg (XEXP (operands[0], 0));
1004:
1005: if (optype1 == MEMOP)
1006: addreg1 = find_addr_reg (XEXP (operands[1], 0));
1007:
1008: /* Ok, we can do one word at a time.
1009: Normally we do the low-numbered word first,
1010: but if either operand is autodecrementing then we
1011: do the high-numbered word first.
1012:
1013: In either case, set up in LATEHALF the operands to use for the
1014: high-numbered (least significant) word and in some cases alter the
1015: operands in OPERANDS to be suitable for the low-numbered word. */
1016:
1017: if (optype0 == REGOP)
1018: latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
1019: else if (optype0 == OFFSOP)
1020: latehalf[0] = adj_offsettable_operand (operands[0], 4);
1021: else
1022: latehalf[0] = operands[0];
1023:
1024: if (optype1 == REGOP)
1025: latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
1026: else if (optype1 == OFFSOP)
1027: latehalf[1] = adj_offsettable_operand (operands[1], 4);
1028: else if (optype1 == CNSTOP)
1029: split_double (operands[1], &operands[1], &latehalf[1]);
1030: else
1031: latehalf[1] = operands[1];
1032:
1033: /* If the first move would clobber the source of the second one,
1034: do them in the other order.
1035:
1036: RMS says "This happens only for registers;
1037: such overlap can't happen in memory unless the user explicitly
1038: sets it up, and that is an undefined circumstance."
1039:
1040: but it happens on the sparc when loading parameter registers,
1041: so I am going to define that circumstance, and make it work
1042: as expected. */
1043:
1044: /* Easy case: try moving both words at once. */
1045: /* First check for moving between an even/odd register pair
1046: and a memory location. */
1047: if ((optype0 == REGOP && optype1 != REGOP && optype1 != CNSTOP
1048: && (REGNO (operands[0]) & 1) == 0)
1049: || (optype0 != REGOP && optype0 != CNSTOP && optype1 == REGOP
1050: && (REGNO (operands[1]) & 1) == 0))
1051: {
1052: rtx op1, op2;
1053: rtx base = 0, offset = const0_rtx;
1054:
1055: /* OP1 gets the register pair, and OP2 gets the memory address. */
1056: if (optype0 == REGOP)
1057: op1 = operands[0], op2 = operands[1];
1058: else
1059: op1 = operands[1], op2 = operands[0];
1060:
1061: /* Now see if we can trust the address to be 8-byte aligned. */
1.1.1.2 ! root 1062: /* Trust double-precision floats in global variables. */
1.1 root 1063:
1.1.1.2 ! root 1064: if (GET_CODE (XEXP (op2, 0)) == LO_SUM && GET_MODE (op2) == DFmode)
1.1 root 1065: {
1066: if (final_sequence)
1067: abort ();
1.1.1.2 ! root 1068: return (op1 == operands[0] ? "ldd %1,%0" : "std %1,%0");
1.1 root 1069: }
1070:
1071: if (GET_CODE (XEXP (op2, 0)) == PLUS)
1072: {
1073: rtx temp = XEXP (op2, 0);
1074: if (GET_CODE (XEXP (temp, 0)) == REG)
1075: base = XEXP (temp, 0), offset = XEXP (temp, 1);
1076: else if (GET_CODE (XEXP (temp, 1)) == REG)
1077: base = XEXP (temp, 1), offset = XEXP (temp, 0);
1078: }
1079:
1080: /* Trust round enough offsets from the stack or frame pointer. */
1081: if (base
1082: && (REGNO (base) == FRAME_POINTER_REGNUM
1083: || REGNO (base) == STACK_POINTER_REGNUM))
1084: {
1085: if (GET_CODE (offset) == CONST_INT
1086: && (INTVAL (offset) & 0x7) == 0)
1087: {
1088: if (op1 == operands[0])
1089: return "ldd %1,%0";
1090: else
1091: return "std %1,%0";
1092: }
1093: }
1094: /* We know structs not on the stack are properly aligned. Since a
1095: double asks for 8-byte alignment, we know it must have got that
1096: if it is in a struct. But a DImode need not be 8-byte aligned,
1097: because it could be a struct containing two ints or pointers. */
1098: else if (GET_CODE (operands[1]) == MEM
1099: && GET_MODE (operands[1]) == DFmode
1100: && (CONSTANT_P (XEXP (operands[1], 0))
1101: /* Let user ask for it anyway. */
1.1.1.2 ! root 1102: || TARGET_HOPE_ALIGN))
1.1 root 1103: return "ldd %1,%0";
1104: else if (GET_CODE (operands[0]) == MEM
1105: && GET_MODE (operands[0]) == DFmode
1106: && (CONSTANT_P (XEXP (operands[0], 0))
1.1.1.2 ! root 1107: || TARGET_HOPE_ALIGN))
1.1 root 1108: return "std %1,%0";
1109: }
1110:
1111: if (optype0 == REGOP && optype1 == REGOP
1112: && REGNO (operands[0]) == REGNO (latehalf[1]))
1113: {
1114: /* Make any unoffsettable addresses point at high-numbered word. */
1115: if (addreg0)
1116: output_asm_insn ("add %0,0x4,%0", &addreg0);
1117: if (addreg1)
1118: output_asm_insn ("add %0,0x4,%0", &addreg1);
1119:
1120: /* Do that word. */
1121: output_asm_insn (singlemove_string (latehalf), latehalf);
1122:
1123: /* Undo the adds we just did. */
1124: if (addreg0)
1125: output_asm_insn ("add %0,-0x4,%0", &addreg0);
1126: if (addreg1)
1127: output_asm_insn ("add %0,-0x4,%0", &addreg1);
1128:
1129: /* Do low-numbered word. */
1130: return singlemove_string (operands);
1131: }
1132: else if (optype0 == REGOP && optype1 != REGOP
1133: && reg_overlap_mentioned_p (operands[0], operands[1]))
1134: {
1135: /* Do the late half first. */
1136: output_asm_insn (singlemove_string (latehalf), latehalf);
1137: /* Then clobber. */
1138: return singlemove_string (operands);
1139: }
1140:
1141: /* Normal case: do the two words, low-numbered first. */
1142:
1143: output_asm_insn (singlemove_string (operands), operands);
1144:
1145: /* Make any unoffsettable addresses point at high-numbered word. */
1146: if (addreg0)
1147: output_asm_insn ("add %0,0x4,%0", &addreg0);
1148: if (addreg1)
1149: output_asm_insn ("add %0,0x4,%0", &addreg1);
1150:
1151: /* Do that word. */
1152: output_asm_insn (singlemove_string (latehalf), latehalf);
1153:
1154: /* Undo the adds we just did. */
1155: if (addreg0)
1156: output_asm_insn ("add %0,-0x4,%0", &addreg0);
1157: if (addreg1)
1158: output_asm_insn ("add %0,-0x4,%0", &addreg1);
1159:
1160: return "";
1161: }
1162:
1163: char *
1164: output_fp_move_double (operands)
1165: rtx *operands;
1166: {
1167: rtx addr;
1168:
1169: if (FP_REG_P (operands[0]))
1170: {
1171: if (FP_REG_P (operands[1]))
1172: return "fmovs %1,%0\n\tfmovs %R1,%R0";
1173: if (GET_CODE (operands[1]) == REG)
1174: {
1175: if ((REGNO (operands[1]) & 1) == 0)
1176: return "std %1,[%@-8]\n\tldd [%@-8],%0";
1177: else
1178: return "st %R1,[%@-4]\n\tst %1,[%@-8]\n\tldd [%@-8],%0";
1179: }
1180: addr = XEXP (operands[1], 0);
1181:
1182: /* Use ldd if known to be aligned. */
1.1.1.2 ! root 1183: if (TARGET_HOPE_ALIGN
1.1 root 1184: || (GET_CODE (addr) == PLUS
1185: && (((XEXP (addr, 0) == frame_pointer_rtx
1186: || XEXP (addr, 0) == stack_pointer_rtx)
1187: && GET_CODE (XEXP (addr, 1)) == CONST_INT
1188: && (INTVAL (XEXP (addr, 1)) & 0x7) == 0)
1189: /* Arrays are known to be aligned,
1190: and reg+reg addresses are used (on this machine)
1191: only for array accesses. */
1192: || (REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))))
1193: || (GET_MODE (operands[0]) == DFmode
1194: && (GET_CODE (addr) == LO_SUM || CONSTANT_P (addr))))
1195: return "ldd %1,%0";
1196:
1197: /* Otherwise use two ld insns. */
1198: operands[2]
1199: = gen_rtx (MEM, GET_MODE (operands[1]),
1200: plus_constant_for_output (addr, 4));
1201: return "ld %1,%0\n\tld %2,%R0";
1202: }
1203: else if (FP_REG_P (operands[1]))
1204: {
1205: if (GET_CODE (operands[0]) == REG)
1206: {
1207: if ((REGNO (operands[0]) & 1) == 0)
1208: return "std %1,[%@-8]\n\tldd [%@-8],%0";
1209: else
1210: return "std %1,[%@-8]\n\tld [%@-4],%R0\n\tld [%@-8],%0";
1211: }
1212: addr = XEXP (operands[0], 0);
1213:
1214: /* Use std if we can be sure it is well-aligned. */
1.1.1.2 ! root 1215: if (TARGET_HOPE_ALIGN
1.1 root 1216: || (GET_CODE (addr) == PLUS
1217: && (((XEXP (addr, 0) == frame_pointer_rtx
1218: || XEXP (addr, 0) == stack_pointer_rtx)
1219: && GET_CODE (XEXP (addr, 1)) == CONST_INT
1220: && (INTVAL (XEXP (addr, 1)) & 0x7) == 0)
1221: /* Arrays are known to be aligned,
1222: and reg+reg addresses are used (on this machine)
1223: only for array accesses. */
1224: || (REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))))
1225: || (GET_MODE (operands[1]) == DFmode
1226: && (GET_CODE (addr) == LO_SUM || CONSTANT_P (addr))))
1227: return "std %1,%0";
1228:
1229: /* Otherwise use two st insns. */
1230: operands[2]
1231: = gen_rtx (MEM, GET_MODE (operands[0]),
1232: plus_constant_for_output (addr, 4));
1233: return "st %r1,%0\n\tst %R1,%2";
1234: }
1235: else abort ();
1236: }
1237:
1238: /* Return a REG that occurs in ADDR with coefficient 1.
1239: ADDR can be effectively incremented by incrementing REG. */
1240:
1241: static rtx
1242: find_addr_reg (addr)
1243: rtx addr;
1244: {
1245: while (GET_CODE (addr) == PLUS)
1246: {
1247: /* We absolutely can not fudge the frame pointer here, because the
1248: frame pointer must always be 8 byte aligned. It also confuses
1249: debuggers. */
1250: if (GET_CODE (XEXP (addr, 0)) == REG
1251: && REGNO (XEXP (addr, 0)) != FRAME_POINTER_REGNUM)
1252: addr = XEXP (addr, 0);
1253: else if (GET_CODE (XEXP (addr, 1)) == REG
1254: && REGNO (XEXP (addr, 1)) != FRAME_POINTER_REGNUM)
1255: addr = XEXP (addr, 1);
1256: else if (CONSTANT_P (XEXP (addr, 0)))
1257: addr = XEXP (addr, 1);
1258: else if (CONSTANT_P (XEXP (addr, 1)))
1259: addr = XEXP (addr, 0);
1260: else
1261: abort ();
1262: }
1263: if (GET_CODE (addr) == REG)
1264: return addr;
1265: abort ();
1266: }
1267:
1268: void
1269: output_sized_memop (opname, mode, signedp)
1270: char *opname;
1271: enum machine_mode mode;
1272: int signedp;
1273: {
1274: static char *ld_size_suffix_u[] = { "ub", "uh", "", "?", "d" };
1275: static char *ld_size_suffix_s[] = { "sb", "sh", "", "?", "d" };
1276: static char *st_size_suffix[] = { "b", "h", "", "?", "d" };
1277: char **opnametab, *modename;
1278:
1279: if (opname[0] == 'l')
1280: if (signedp)
1281: opnametab = ld_size_suffix_s;
1282: else
1283: opnametab = ld_size_suffix_u;
1284: else
1285: opnametab = st_size_suffix;
1286: modename = opnametab[GET_MODE_SIZE (mode) >> 1];
1287:
1288: fprintf (asm_out_file, "\t%s%s", opname, modename);
1289: }
1290:
1291: void
1292: output_move_with_extension (operands)
1293: rtx *operands;
1294: {
1295: if (GET_MODE (operands[2]) == HImode)
1296: output_asm_insn ("sll %2,0x10,%0", operands);
1297: else if (GET_MODE (operands[2]) == QImode)
1298: output_asm_insn ("sll %2,0x18,%0", operands);
1299: else
1300: abort ();
1301: }
1302:
1303: /* Load the address specified by OPERANDS[3] into the register
1304: specified by OPERANDS[0].
1305:
1306: OPERANDS[3] may be the result of a sum, hence it could either be:
1307:
1308: (1) CONST
1309: (2) REG
1310: (2) REG + CONST_INT
1311: (3) REG + REG + CONST_INT
1312: (4) REG + REG (special case of 3).
1313:
1314: Note that (3) is not a legitimate address.
1315: All cases are handled here. */
1316:
1317: void
1318: output_load_address (operands)
1319: rtx *operands;
1320: {
1321: rtx base, offset;
1322:
1323: if (CONSTANT_P (operands[3]))
1324: {
1325: output_asm_insn ("set %3,%0", operands);
1326: return;
1327: }
1328:
1329: if (REG_P (operands[3]))
1330: {
1331: if (REGNO (operands[0]) != REGNO (operands[3]))
1332: output_asm_insn ("mov %3,%0", operands);
1333: return;
1334: }
1335:
1336: if (GET_CODE (operands[3]) != PLUS)
1337: abort ();
1338:
1339: base = XEXP (operands[3], 0);
1340: offset = XEXP (operands[3], 1);
1341:
1342: if (GET_CODE (base) == CONST_INT)
1343: {
1344: rtx tmp = base;
1345: base = offset;
1346: offset = tmp;
1347: }
1348:
1349: if (GET_CODE (offset) != CONST_INT)
1350: {
1351: /* Operand is (PLUS (REG) (REG)). */
1352: base = operands[3];
1353: offset = const0_rtx;
1354: }
1355:
1356: if (REG_P (base))
1357: {
1358: operands[6] = base;
1359: operands[7] = offset;
1360: if (SMALL_INT (offset))
1361: output_asm_insn ("add %6,%7,%0", operands);
1362: else
1363: output_asm_insn ("set %7,%0\n\tadd %0,%6,%0", operands);
1364: }
1365: else if (GET_CODE (base) == PLUS)
1366: {
1367: operands[6] = XEXP (base, 0);
1368: operands[7] = XEXP (base, 1);
1369: operands[8] = offset;
1370:
1371: if (SMALL_INT (offset))
1372: output_asm_insn ("add %6,%7,%0\n\tadd %0,%8,%0", operands);
1373: else
1374: output_asm_insn ("set %8,%0\n\tadd %0,%6,%0\n\tadd %0,%7,%0", operands);
1375: }
1376: else
1377: abort ();
1378: }
1379:
1380: /* Output code to place a size count SIZE in register REG.
1381: ALIGN is the size of the unit of transfer.
1382:
1383: Because block moves are pipelined, we don't include the
1384: first element in the transfer of SIZE to REG. */
1385:
1386: static void
1387: output_size_for_block_move (size, reg, align)
1388: rtx size, reg;
1389: rtx align;
1390: {
1391: rtx xoperands[3];
1392:
1393: xoperands[0] = reg;
1394: xoperands[1] = size;
1395: xoperands[2] = align;
1396: if (GET_CODE (size) == REG)
1397: output_asm_insn ("sub %1,%2,%0", xoperands);
1398: else
1399: {
1400: xoperands[1]
1401: = gen_rtx (CONST_INT, VOIDmode, INTVAL (size) - INTVAL (align));
1402: output_asm_insn ("set %1,%0", xoperands);
1403: }
1404: }
1405:
1406: /* Emit code to perform a block move.
1407:
1408: OPERANDS[0] is the destination.
1409: OPERANDS[1] is the source.
1410: OPERANDS[2] is the size.
1411: OPERANDS[3] is the alignment safe to use.
1412: OPERANDS[4] is a register we can safely clobber as a temp. */
1413:
1414: char *
1415: output_block_move (operands)
1416: rtx *operands;
1417: {
1418: /* A vector for our computed operands. Note that load_output_address
1419: makes use of (and can clobber) up to the 8th element of this vector. */
1420: rtx xoperands[10];
1421: rtx zoperands[10];
1422: static int movstrsi_label = 0;
1423: int i;
1424: rtx temp1 = operands[4];
1425: rtx sizertx = operands[2];
1426: rtx alignrtx = operands[3];
1427: int align = INTVAL (alignrtx);
1428:
1429: xoperands[0] = operands[0];
1430: xoperands[1] = operands[1];
1431: xoperands[2] = temp1;
1432:
1.1.1.2 ! root 1433: /* We can't move more than this many bytes at a time because we have only
! 1434: one register, %g1, to move them through. */
! 1435: if (align > UNITS_PER_WORD)
! 1436: {
! 1437: align = UNITS_PER_WORD;
! 1438: alignrtx = gen_rtx (CONST_INT, VOIDmode, UNITS_PER_WORD);
! 1439: }
! 1440:
! 1441: /* We consider 8 ld/st pairs, for a total of 16 inline insns to be
! 1442: reasonable here. (Actually will emit a maximum of 18 inline insns for
! 1443: the case of size == 31 and align == 4). */
! 1444:
! 1445: if (GET_CODE (sizertx) == CONST_INT && (INTVAL (sizertx) / align) <= 8
! 1446: && memory_address_p (QImode, plus_constant_for_output (xoperands[0],
! 1447: INTVAL (sizertx)))
! 1448: && memory_address_p (QImode, plus_constant_for_output (xoperands[1],
! 1449: INTVAL (sizertx))))
1.1 root 1450: {
1.1.1.2 ! root 1451: int size = INTVAL (sizertx);
! 1452: int offset = 0;
! 1453:
! 1454: /* We will store different integers into this particular RTX. */
! 1455: xoperands[2] = rtx_alloc (CONST_INT);
! 1456: PUT_MODE (xoperands[2], VOIDmode);
! 1457:
! 1458: /* This case is currently not handled. Abort instead of generating
! 1459: bad code. */
! 1460: if (align > 4)
! 1461: abort ();
! 1462:
! 1463: if (align >= 4)
! 1464: {
! 1465: for (i = (size >> 2) - 1; i >= 0; i--)
! 1466: {
! 1467: INTVAL (xoperands[2]) = (i << 2) + offset;
! 1468: output_asm_insn ("ld [%a1+%2],%%g1\n\tst %%g1,[%a0+%2]",
! 1469: xoperands);
! 1470: }
! 1471: offset += (size & ~0x3);
! 1472: size = size & 0x3;
! 1473: if (size == 0)
! 1474: return "";
! 1475: }
! 1476:
! 1477: if (align >= 2)
! 1478: {
! 1479: for (i = (size >> 1) - 1; i >= 0; i--)
! 1480: {
! 1481: INTVAL (xoperands[2]) = (i << 1) + offset;
! 1482: output_asm_insn ("lduh [%a1+%2],%%g1\n\tsth %%g1,[%a0+%2]",
! 1483: xoperands);
! 1484: }
! 1485: offset += (size & ~0x1);
! 1486: size = size & 0x1;
! 1487: if (size == 0)
! 1488: return "";
! 1489: }
! 1490:
! 1491: if (align >= 1)
! 1492: {
! 1493: for (i = size - 1; i >= 0; i--)
! 1494: {
! 1495: INTVAL (xoperands[2]) = i + offset;
! 1496: output_asm_insn ("ldub [%a1+%2],%%g1\n\tstb %%g1,[%a0+%2]",
! 1497: xoperands);
! 1498: }
! 1499: return "";
! 1500: }
! 1501:
! 1502: /* We should never reach here. */
! 1503: abort ();
1.1 root 1504: }
1505:
1506: /* If the size isn't known to be a multiple of the alignment,
1507: we have to do it in smaller pieces. If we could determine that
1508: the size was a multiple of 2 (or whatever), we could be smarter
1509: about this. */
1510: if (GET_CODE (sizertx) != CONST_INT)
1511: align = 1;
1512: else
1513: {
1514: int size = INTVAL (sizertx);
1515: while (size % align)
1516: align >>= 1;
1517: }
1518:
1519: if (align != INTVAL (alignrtx))
1520: alignrtx = gen_rtx (CONST_INT, VOIDmode, align);
1521:
1522: xoperands[3] = gen_rtx (CONST_INT, VOIDmode, movstrsi_label++);
1523: xoperands[4] = gen_rtx (CONST_INT, VOIDmode, align);
1524: xoperands[5] = gen_rtx (CONST_INT, VOIDmode, movstrsi_label++);
1525:
1.1.1.2 ! root 1526: /* This is the size of the transfer. Emit code to decrement the size
! 1527: value by ALIGN, and store the result in the temp1 register. */
1.1 root 1528: output_size_for_block_move (sizertx, temp1, alignrtx);
1529:
1530: /* Must handle the case when the size is zero or negative, so the first thing
1531: we do is compare the size against zero, and only copy bytes if it is
1532: zero or greater. Note that we have already subtracted off the alignment
1533: once, so we must copy 1 alignment worth of bytes if the size is zero
1534: here.
1535:
1536: The SUN assembler complains about labels in branch delay slots, so we
1.1.1.2 ! root 1537: do this before outputting the load address, so that there will always
1.1 root 1538: be a harmless insn between the branch here and the next label emitted
1539: below. */
1540:
1541: #ifdef NO_UNDERSCORES
1542: output_asm_insn ("cmp %2,0\n\tbl .Lm%5", xoperands);
1543: #else
1544: output_asm_insn ("cmp %2,0\n\tbl Lm%5", xoperands);
1545: #endif
1546:
1547: zoperands[0] = operands[0];
1548: zoperands[3] = plus_constant_for_output (operands[0], align);
1549: output_load_address (zoperands);
1550:
1551: /* ??? This might be much faster if the loops below were preconditioned
1552: and unrolled.
1553:
1554: That is, at run time, copy enough bytes one at a time to ensure that the
1555: target and source addresses are aligned to the the largest possible
1556: alignment. Then use a preconditioned unrolled loop to copy say 16
1557: bytes at a time. Then copy bytes one at a time until finish the rest. */
1558:
1559: /* Output the first label separately, so that it is spaced properly. */
1560:
1561: #ifdef NO_UNDERSCORES
1562: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, ".Lm", INTVAL (xoperands[3]));
1563: #else
1564: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "Lm", INTVAL (xoperands[3]));
1565: #endif
1566:
1567: #ifdef NO_UNDERSCORES
1568: if (align == 1)
1569: output_asm_insn ("ldub [%1+%2],%%g1\n\tsubcc %2,%4,%2\n\tbge .Lm%3\n\tstb %%g1,[%0+%2]\n.Lm%5:", xoperands);
1570: else if (align == 2)
1571: output_asm_insn ("lduh [%1+%2],%%g1\n\tsubcc %2,%4,%2\n\tbge .Lm%3\n\tsth %%g1,[%0+%2]\n.Lm%5:", xoperands);
1572: else
1573: output_asm_insn ("ld [%1+%2],%%g1\n\tsubcc %2,%4,%2\n\tbge .Lm%3\n\tst %%g1,[%0+%2]\n.Lm%5:", xoperands);
1574: return "";
1575: #else
1576: if (align == 1)
1577: output_asm_insn ("ldub [%1+%2],%%g1\n\tsubcc %2,%4,%2\n\tbge Lm%3\n\tstb %%g1,[%0+%2]\nLm%5:", xoperands);
1578: else if (align == 2)
1579: output_asm_insn ("lduh [%1+%2],%%g1\n\tsubcc %2,%4,%2\n\tbge Lm%3\n\tsth %%g1,[%0+%2]\nLm%5:", xoperands);
1580: else
1581: output_asm_insn ("ld [%1+%2],%%g1\n\tsubcc %2,%4,%2\n\tbge Lm%3\n\tst %%g1,[%0+%2]\nLm%5:", xoperands);
1582: return "";
1583: #endif
1584: }
1585:
1586: /* Output reasonable peephole for set-on-condition-code insns.
1587: Note that these insns assume a particular way of defining
1588: labels. Therefore, *both* sparc.h and this function must
1589: be changed if a new syntax is needed. */
1590:
1591: char *
1592: output_scc_insn (operands, insn)
1593: rtx operands[];
1594: rtx insn;
1595: {
1596: static char string[100];
1597: rtx label = 0, next = insn;
1598: int need_label = 0;
1599:
1600: /* Try doing a jump optimization which jump.c can't do for us
1601: because we did not expose that setcc works by using branches.
1602:
1603: If this scc insn is followed by an unconditional branch, then have
1604: the jump insn emitted here jump to that location, instead of to
1605: the end of the scc sequence as usual. */
1606:
1607: do
1608: {
1609: if (GET_CODE (next) == CODE_LABEL)
1610: label = next;
1611: next = NEXT_INSN (next);
1612: if (next == 0)
1613: break;
1614: }
1615: while (GET_CODE (next) == NOTE || GET_CODE (next) == CODE_LABEL);
1616:
1617: /* If we are in a sequence, and the following insn is a sequence also,
1618: then just following the current insn's next field will take us to the
1619: first insn of the next sequence, which is the wrong place. We don't
1620: want to optimize with a branch that has had its delay slot filled.
1621: Avoid this by verifying that NEXT_INSN (PREV_INSN (next)) == next
1622: which fails only if NEXT is such a branch. */
1623:
1624: if (next && GET_CODE (next) == JUMP_INSN && simplejump_p (next)
1625: && (! final_sequence || NEXT_INSN (PREV_INSN (next)) == next))
1626: label = JUMP_LABEL (next);
1627: /* If not optimizing, jump label fields are not set. To be safe, always
1628: check here to whether label is still zero. */
1629: if (label == 0)
1630: {
1631: label = gen_label_rtx ();
1632: need_label = 1;
1633: }
1634:
1635: LABEL_NUSES (label) += 1;
1636:
1637: operands[2] = label;
1638:
1639: /* If we are in a delay slot, assume it is the delay slot of an fpcc
1640: insn since our type isn't allowed anywhere else. */
1641:
1642: /* ??? Fpcc instructions no longer have delay slots, so this code is
1643: probably obsolete. */
1644:
1645: /* The fastest way to emit code for this is an annulled branch followed
1646: by two move insns. This will take two cycles if the branch is taken,
1647: and three cycles if the branch is not taken.
1648:
1649: However, if we are in the delay slot of another branch, this won't work,
1650: because we can't put a branch in the delay slot of another branch.
1651: The above sequence would effectively take 3 or 4 cycles respectively
1652: since a no op would have be inserted between the two branches.
1653: In this case, we want to emit a move, annulled branch, and then the
1654: second move. This sequence always takes 3 cycles, and hence is faster
1655: when we are in a branch delay slot. */
1656:
1657: if (final_sequence)
1658: {
1659: strcpy (string, "mov 0,%0\n\t");
1660: strcat (string, output_cbranch (operands[1], 2, 0, 1, 0));
1661: strcat (string, "\n\tmov 1,%0");
1662: }
1663: else
1664: {
1665: strcpy (string, output_cbranch (operands[1], 2, 0, 1, 0));
1666: strcat (string, "\n\tmov 1,%0\n\tmov 0,%0");
1667: }
1668:
1669: if (need_label)
1670: strcat (string, "\n%l2:");
1671:
1672: return string;
1673: }
1674:
1675: /* Vectors to keep interesting information about registers where
1676: it can easily be got. */
1677:
1678: /* Modes for condition codes. */
1679: #define C_MODES \
1680: ((1 << (int) CCmode) | (1 << (int) CC_NOOVmode) | (1 << (int) CCFPmode))
1681:
1682: /* Modes for single-word (and smaller) quantities. */
1683: #define S_MODES \
1684: (~C_MODES \
1685: & ~ ((1 << (int) DImode) | (1 << (int) TImode) \
1686: | (1 << (int) DFmode) | (1 << (int) TFmode)))
1687:
1688: /* Modes for double-word (and smaller) quantities. */
1689: #define D_MODES \
1690: (~C_MODES \
1691: & ~ ((1 << (int) TImode) | (1 << (int) TFmode)))
1692:
1693: /* Modes for quad-word quantities. */
1694: #define T_MODES (~C_MODES)
1695:
1696: /* Modes for single-float quantities. */
1697: #define SF_MODES ((1 << (int) SFmode))
1698:
1699: /* Modes for double-float quantities. */
1700: #define DF_MODES (SF_MODES | (1 << (int) DFmode) | (1 << (int) SCmode))
1701:
1702: /* Modes for quad-float quantities. */
1703: #define TF_MODES (DF_MODES | (1 << (int) TFmode) | (1 << (int) DCmode))
1704:
1705: /* Value is 1 if register/mode pair is acceptable on sparc.
1706: The funny mixture of D and T modes is because integer operations
1707: do not specially operate on tetra quantities, so non-quad-aligned
1708: registers can hold quadword quantities (except %o4 and %i4 because
1709: they cross fixed registers. */
1710:
1711: int hard_regno_mode_ok[] = {
1712: C_MODES, S_MODES, T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES,
1713: T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES, D_MODES, S_MODES,
1714: T_MODES, S_MODES, T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES,
1715: T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES, D_MODES, S_MODES,
1716:
1717: TF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES,
1718: TF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES,
1719: TF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES,
1720: TF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES};
1721:
1722: #ifdef __GNUC__
1723: inline
1724: #endif
1725: static int
1726: save_regs (file, low, high, base, offset, n_fregs)
1727: FILE *file;
1728: int low, high;
1729: char *base;
1730: int offset;
1731: int n_fregs;
1732: {
1733: int i;
1734:
1735: for (i = low; i < high; i += 2)
1736: {
1737: if (regs_ever_live[i] && ! call_used_regs[i])
1738: if (regs_ever_live[i+1] && ! call_used_regs[i+1])
1739: fprintf (file, "\tstd %s,[%s+%d]\n",
1740: reg_names[i], base, offset + 4 * n_fregs),
1741: n_fregs += 2;
1742: else
1743: fprintf (file, "\tst %s,[%s+%d]\n",
1744: reg_names[i], base, offset + 4 * n_fregs),
1745: n_fregs += 2;
1746: else if (regs_ever_live[i+1] && ! call_used_regs[i+1])
1747: fprintf (file, "\tst %s,[%s+%d]\n",
1748: reg_names[i+1], base, offset + 4 * n_fregs),
1749: n_fregs += 2;
1750: }
1751: return n_fregs;
1752: }
1753:
1754: #ifdef __GNUC__
1755: inline
1756: #endif
1757: static int
1758: restore_regs (file, low, high, base, offset, n_fregs)
1759: FILE *file;
1760: int low, high;
1761: char *base;
1762: int offset;
1763: {
1764: int i;
1765:
1766: for (i = low; i < high; i += 2)
1767: {
1768: if (regs_ever_live[i] && ! call_used_regs[i])
1769: if (regs_ever_live[i+1] && ! call_used_regs[i+1])
1770: fprintf (file, "\tldd [%s+%d], %s\n",
1771: base, offset + 4 * n_fregs, reg_names[i]),
1772: n_fregs += 2;
1773: else
1774: fprintf (file, "\tld [%s+%d],%s\n",
1775: base, offset + 4 * n_fregs, reg_names[i]),
1776: n_fregs += 2;
1777: else if (regs_ever_live[i+1] && ! call_used_regs[i+1])
1778: fprintf (file, "\tld [%s+%d],%s\n",
1779: base, offset + 4 * n_fregs, reg_names[i+1]),
1780: n_fregs += 2;
1781: }
1782: return n_fregs;
1783: }
1784:
1785: /* Static variables we want to share between prologue and epilogue. */
1786:
1787: /* Number of live floating point registers needed to be saved. */
1788: static int num_fregs;
1789:
1790: /* Nonzero if any floating point register was ever used. */
1791: static int fregs_ever_live;
1792:
1793: int
1794: compute_frame_size (size, leaf_function)
1795: int size;
1796: int leaf_function;
1797: {
1798: int fregs_ever_live = 0;
1799: int n_fregs = 0, i;
1800: int outgoing_args_size = (current_function_outgoing_args_size
1801: + REG_PARM_STACK_SPACE (current_function_decl));
1802:
1803: apparent_fsize = ((size) + 7 - STARTING_FRAME_OFFSET) & -8;
1804: for (i = 32; i < FIRST_PSEUDO_REGISTER; i += 2)
1805: fregs_ever_live |= regs_ever_live[i]|regs_ever_live[i+1];
1806:
1807: if (TARGET_EPILOGUE && fregs_ever_live)
1808: {
1809: for (i = 32; i < FIRST_PSEUDO_REGISTER; i += 2)
1810: if ((regs_ever_live[i] && ! call_used_regs[i])
1811: || (regs_ever_live[i+1] && ! call_used_regs[i+1]))
1812: n_fregs += 2;
1813: }
1814:
1815: /* Set up values for use in `function_epilogue'. */
1816: num_fregs = n_fregs;
1817:
1818: apparent_fsize += (outgoing_args_size+7) & -8;
1819: if (leaf_function && n_fregs == 0
1820: && apparent_fsize == (REG_PARM_STACK_SPACE (current_function_decl)
1821: - STARTING_FRAME_OFFSET))
1822: apparent_fsize = 0;
1823:
1824: actual_fsize = apparent_fsize + n_fregs*4;
1825:
1826: /* Make sure nothing can clobber our register windows.
1827: If a SAVE must be done, or there is a stack-local variable,
1828: the register window area must be allocated. */
1829: if (leaf_function == 0 || size > 0)
1830: actual_fsize += (16 * UNITS_PER_WORD)+8;
1831:
1832: return actual_fsize;
1833: }
1834:
1835: void
1836: output_function_prologue (file, size, leaf_function)
1837: FILE *file;
1838: int size;
1839: {
1840: if (leaf_function)
1841: frame_base_name = "%sp+80";
1842: else
1843: frame_base_name = "%fp";
1844:
1845: actual_fsize = compute_frame_size (size, leaf_function);
1846:
1847: fprintf (file, "\t!#PROLOGUE# 0\n");
1848: if (actual_fsize == 0) /* do nothing. */ ;
1849: else if (actual_fsize < 4096)
1850: {
1851: if (! leaf_function)
1852: fprintf (file, "\tsave %%sp,-%d,%%sp\n", actual_fsize);
1853: else
1854: fprintf (file, "\tadd %%sp,-%d,%%sp\n", actual_fsize);
1855: }
1856: else if (! leaf_function)
1857: {
1858: /* Need to use actual_fsize, since we are also allocating space for
1859: our callee (and our own register save area). */
1860: fprintf (file, "\tsethi %%hi(%d),%%g1\n\tor %%g1,%%lo(%d),%%g1\n",
1861: -actual_fsize, -actual_fsize);
1862: fprintf (file, "\tsave %%sp,%%g1,%%sp\n");
1863: }
1864: else
1865: {
1866: /* Put pointer to parameters into %g4, and allocate
1867: frame space using result computed into %g1. actual_fsize
1868: used instead of apparent_fsize for reasons stated above. */
1869: abort ();
1870:
1871: fprintf (file, "\tsethi %%hi(%d),%%g1\n\tor %%g1,%%lo(%d),%%g1\n",
1872: -actual_fsize, -actual_fsize);
1873: fprintf (file, "\tadd %%sp,64,%%g4\n\tadd %%sp,%%g1,%%sp\n");
1874: }
1875:
1876: /* If doing anything with PIC, do it now. */
1877: if (! flag_pic)
1878: fprintf (file, "\t!#PROLOGUE# 1\n");
1879:
1880: /* Figure out where to save any special registers. */
1881: if (num_fregs)
1882: {
1883: int offset, n_fregs = num_fregs;
1884:
1885: if (! leaf_function)
1886: offset = -apparent_fsize;
1887: else
1888: offset = 0;
1889:
1890: if (TARGET_EPILOGUE && ! leaf_function)
1891: n_fregs = save_regs (file, 0, 16, frame_base_name, offset, 0);
1892: else if (leaf_function)
1893: n_fregs = save_regs (file, 0, 32, frame_base_name, offset, 0);
1894: if (TARGET_EPILOGUE)
1895: save_regs (file, 32, FIRST_PSEUDO_REGISTER,
1896: frame_base_name, offset, n_fregs);
1897: }
1898:
1899: if (regs_ever_live[62])
1900: fprintf (file, "\tst %s,[%s-16]\n\tst %s,[%s-12]\n",
1901: reg_names[0], frame_base_name,
1902: reg_names[0], frame_base_name);
1903:
1904: leaf_label = 0;
1905: if (leaf_function && actual_fsize != 0)
1906: {
1907: /* warning ("leaf procedure with frame size %d", actual_fsize); */
1908: if (! TARGET_EPILOGUE)
1909: leaf_label = gen_label_rtx ();
1910: }
1911: }
1912:
1913: void
1914: output_function_epilogue (file, size, leaf_function, true_epilogue)
1915: FILE *file;
1916: int size;
1917: {
1918: int n_fregs, i;
1919: char *ret;
1920:
1921: if (leaf_label)
1922: {
1923: if (leaf_function < 0)
1924: abort ();
1925: emit_label_after (leaf_label, get_last_insn ());
1926: final_scan_insn (get_last_insn (), file, 0, 0, 1);
1927: }
1928:
1929: if (num_fregs)
1930: {
1931: int offset, n_fregs = num_fregs;
1932:
1933: if (! leaf_function)
1934: offset = -apparent_fsize;
1935: else
1936: offset = 0;
1937:
1938: if (TARGET_EPILOGUE && ! leaf_function)
1939: n_fregs = restore_regs (file, 0, 16, frame_base_name, offset, 0);
1940: else if (leaf_function)
1941: n_fregs = restore_regs (file, 0, 32, frame_base_name, offset, 0);
1942: if (TARGET_EPILOGUE)
1943: restore_regs (file, 32, FIRST_PSEUDO_REGISTER,
1944: frame_base_name, offset, n_fregs);
1945: }
1946:
1947: /* Work out how to skip the caller's unimp instruction if required. */
1948: if (leaf_function)
1949: ret = (current_function_returns_struct ? "jmp %o7+12" : "retl");
1950: else
1951: ret = (current_function_returns_struct ? "jmp %i7+12" : "ret");
1952:
1953: /* Tail calls have to do this work themselves. */
1954: if (leaf_function >= 0)
1955: {
1956: if (TARGET_EPILOGUE || leaf_label)
1957: {
1958: int old_target_epilogue = TARGET_EPILOGUE;
1959: target_flags &= ~old_target_epilogue;
1960:
1961: if (! leaf_function)
1962: {
1963: /* If we wound up with things in our delay slot,
1964: flush them here. */
1965: if (current_function_epilogue_delay_list)
1966: {
1967: rtx insn = emit_jump_insn_after (gen_rtx (RETURN, VOIDmode),
1968: get_last_insn ());
1969: PATTERN (insn) = gen_rtx (PARALLEL, VOIDmode,
1970: gen_rtvec (2,
1971: PATTERN (XEXP (current_function_epilogue_delay_list, 0)),
1972: PATTERN (insn)));
1973: final_scan_insn (insn, file, 1, 0, 1);
1974: }
1975: else
1976: fprintf (file, "\t%s\n\trestore\n", ret);
1977: }
1978: else if (actual_fsize < 4096)
1979: {
1980: if (current_function_epilogue_delay_list)
1981: {
1982: fprintf (file, "\t%s\n", ret);
1983: final_scan_insn (XEXP (current_function_epilogue_delay_list, 0),
1984: file, 1, 0, 1);
1985: }
1986: else
1987: fprintf (file, "\t%s\n\tadd %%sp,%d,%%sp\n",
1988: ret, actual_fsize);
1989: }
1990: else
1991: {
1992: if (current_function_epilogue_delay_list)
1993: abort ();
1994: fprintf (file, "\tsethi %%hi(%d),%%g1\n\tor %%g1,%%lo(%d),%%g1\n\t%s\n\tadd %%sp,%%g1,%%sp\n",
1995: actual_fsize, actual_fsize, ret);
1996: }
1997: target_flags |= old_target_epilogue;
1998: }
1999: }
2000: else if (true_epilogue)
2001: {
2002: /* We may still need a return insn! Somebody could jump around
2003: the tail-calls that this function makes. */
2004: if (TARGET_EPILOGUE)
2005: {
2006: rtx last = get_last_insn ();
2007:
2008: last = prev_nonnote_insn (last);
2009: if (last == 0
2010: || (GET_CODE (last) != JUMP_INSN && GET_CODE (last) != BARRIER))
2011: fprintf (file, "\t%s\n\tnop\n", ret);
2012: }
2013: }
2014: }
2015:
2016: /* Return the string to output a conditional branch to LABEL, which is
2017: the operand number of the label. OP is the conditional expression. The
2018: mode of register 0 says what kind of comparison we made.
2019:
2020: REVERSED is non-zero if we should reverse the sense of the comparison.
2021:
2022: ANNUL is non-zero if we should generate an annulling branch.
2023:
2024: NOOP is non-zero if we have to follow this branch by a noop. */
2025:
2026: char *
2027: output_cbranch (op, label, reversed, annul, noop)
2028: rtx op;
2029: int label;
2030: int reversed, annul, noop;
2031: {
2032: static char string[20];
2033: enum rtx_code code = GET_CODE (op);
2034: enum machine_mode mode = GET_MODE (XEXP (op, 0));
2035: static char labelno[] = " %lX";
2036:
1.1.1.2 ! root 2037: /* ??? FP branches can not be preceded by another floating point insn.
1.1 root 2038: Because there is currently no concept of pre-delay slots, we can fix
2039: this only by always emitting a nop before a floating point branch. */
2040:
2041: if (mode == CCFPmode)
2042: strcpy (string, "nop\n\t");
2043:
2044: /* If not floating-point or if EQ or NE, we can just reverse the code. */
2045: if (reversed && (mode != CCFPmode || code == EQ || code == NE))
2046: code = reverse_condition (code), reversed = 0;
2047:
2048: /* Start by writing the branch condition. */
2049: switch (code)
2050: {
2051: case NE:
2052: if (mode == CCFPmode)
2053: strcat (string, "fbne");
2054: else
2055: strcpy (string, "bne");
2056: break;
2057:
2058: case EQ:
2059: if (mode == CCFPmode)
2060: strcat (string, "fbe");
2061: else
2062: strcpy (string, "be");
2063: break;
2064:
2065: case GE:
2066: if (mode == CCFPmode)
2067: {
2068: if (reversed)
2069: strcat (string, "fbul");
2070: else
2071: strcat (string, "fbge");
2072: }
2073: else if (mode == CC_NOOVmode)
2074: strcpy (string, "bpos");
2075: else
2076: strcpy (string, "bge");
2077: break;
2078:
2079: case GT:
2080: if (mode == CCFPmode)
2081: {
2082: if (reversed)
2083: strcat (string, "fbule");
2084: else
2085: strcat (string, "fbg");
2086: }
2087: else
2088: strcpy (string, "bg");
2089: break;
2090:
2091: case LE:
2092: if (mode == CCFPmode)
2093: {
2094: if (reversed)
2095: strcat (string, "fbug");
2096: else
2097: strcat (string, "fble");
2098: }
2099: else
2100: strcpy (string, "ble");
2101: break;
2102:
2103: case LT:
2104: if (mode == CCFPmode)
2105: {
2106: if (reversed)
2107: strcat (string, "fbuge");
2108: else
2109: strcat (string, "fbl");
2110: }
2111: else if (mode == CC_NOOVmode)
2112: strcpy (string, "bneg");
2113: else
2114: strcpy (string, "bl");
2115: break;
2116:
2117: case GEU:
2118: strcpy (string, "bgeu");
2119: break;
2120:
2121: case GTU:
2122: strcpy (string, "bgu");
2123: break;
2124:
2125: case LEU:
2126: strcpy (string, "bleu");
2127: break;
2128:
2129: case LTU:
2130: strcpy (string, "blu");
2131: break;
2132: }
2133:
2134: /* Now add the annulling, the label, and a possible noop. */
2135: if (annul)
2136: strcat (string, ",a");
2137:
2138: labelno[3] = label + '0';
2139: strcat (string, labelno);
2140:
2141: if (noop)
2142: strcat (string, "\n\tnop");
2143:
2144: return string;
2145: }
2146:
2147: char *
2148: output_return (operands)
2149: rtx *operands;
2150: {
2151: if (leaf_label)
2152: {
2153: operands[0] = leaf_label;
2154: return "b,a %l0";
2155: }
2156: else if (leaf_function)
2157: {
2158: operands[0] = gen_rtx (CONST_INT, VOIDmode, actual_fsize);
2159: if (actual_fsize < 4096)
2160: {
2161: if (current_function_returns_struct)
2162: return "jmp %%o7+12\n\tadd %%sp,%0,%%sp";
2163: else
2164: return "retl\n\tadd %%sp,%0,%%sp";
2165: }
2166: else
2167: {
2168: if (current_function_returns_struct)
2169: return "sethi %%hi(%a0),%%g1\n\tor %%g1,%%lo(%a0),%%g1\n\tjmp %%o7+12\n\tadd %%sp,%%g1,%%sp";
2170: else
2171: return "sethi %%hi(%a0),%%g1\n\tor %%g1,%%lo(%a0),%%g1\n\tretl\n\tadd %%sp,%%g1,%%sp";
2172: }
2173: }
2174: else
2175: {
2176: if (current_function_returns_struct)
2177: return "jmp %%i7+12\n\trestore";
2178: else
2179: return "ret\n\trestore";
2180: }
2181: }
2182:
2183: char *
2184: output_floatsisf2 (operands)
2185: rtx *operands;
2186: {
2187: if (GET_CODE (operands[1]) == MEM)
2188: return "ld %1,%0\n\tfitos %0,%0";
2189: else if (FP_REG_P (operands[1]))
2190: return "fitos %1,%0";
2191: return "st %r1,[%%fp-4]\n\tld [%%fp-4],%0\n\tfitos %0,%0";
2192: }
2193:
2194: char *
2195: output_floatsidf2 (operands)
2196: rtx *operands;
2197: {
2198: if (GET_CODE (operands[1]) == MEM)
2199: return "ld %1,%0\n\tfitod %0,%0";
2200: else if (FP_REG_P (operands[1]))
2201: return "fitod %1,%0";
2202: return "st %r1,[%%fp-4]\n\tld [%%fp-4],%0\n\tfitod %0,%0";
2203: }
2204:
2205: int
2206: tail_call_valid_p ()
2207: {
2208: static int checked = 0;
2209: static int valid_p = 0;
2210:
2211: if (! checked)
2212: {
2213: register int i;
2214:
2215: checked = 1;
2216: for (i = 32; i < FIRST_PSEUDO_REGISTER; i++)
2217: if (! fixed_regs[i] && ! call_used_regs[i])
2218: return 0;
2219: valid_p = 1;
2220: }
2221: return valid_p;
2222: }
2223:
2224: /* Leaf functions and non-leaf functions have different needs. */
2225:
2226: static int
2227: reg_leaf_alloc_order[] = REG_LEAF_ALLOC_ORDER;
2228:
2229: static int
2230: reg_nonleaf_alloc_order[] = REG_ALLOC_ORDER;
2231:
2232: static int *reg_alloc_orders[] = {
2233: reg_leaf_alloc_order,
2234: reg_nonleaf_alloc_order};
2235:
2236: void
2237: order_regs_for_local_alloc ()
2238: {
2239: static int last_order_nonleaf = 1;
2240:
2241: if (regs_ever_live[15] != last_order_nonleaf)
2242: {
2243: last_order_nonleaf = !last_order_nonleaf;
2244: bcopy (reg_alloc_orders[last_order_nonleaf], reg_alloc_order,
2245: FIRST_PSEUDO_REGISTER * sizeof (int));
2246: }
2247: }
2248:
2249: /* Machine dependent routines for the branch probability, arc profiling
2250: code. */
2251:
2252: /* The label used by the arc profiling code. */
2253:
2254: static rtx profiler_label;
2255:
2256: void
2257: init_arc_profiler ()
2258: {
2259: /* Generate and save a copy of this so it can be shared. */
2260: profiler_label = gen_rtx (SYMBOL_REF, Pmode, "*LPBX2");
2261: }
2262:
2263: void
2264: output_arc_profiler (arcno, insert_after)
2265: int arcno;
2266: rtx insert_after;
2267: {
2268: rtx profiler_target_addr
2269: = gen_rtx (CONST, Pmode,
2270: gen_rtx (PLUS, Pmode, profiler_label,
2271: gen_rtx (CONST_INT, VOIDmode, 4 * arcno)));
2272: register rtx profiler_reg = gen_reg_rtx (SImode);
1.1.1.2 ! root 2273: register rtx address_reg = gen_reg_rtx (Pmode);
! 2274: rtx mem_ref;
! 2275:
! 2276: insert_after = emit_insn_after (gen_rtx (SET, VOIDmode, address_reg,
! 2277: gen_rtx (HIGH, Pmode,
! 2278: profiler_target_addr)),
! 2279: insert_after);
! 2280:
! 2281: mem_ref = gen_rtx (MEM, SImode, gen_rtx (LO_SUM, Pmode, address_reg,
! 2282: profiler_target_addr));
! 2283: insert_after = emit_insn_after (gen_rtx (SET, VOIDmode, profiler_reg,
! 2284: mem_ref),
! 2285: insert_after);
! 2286:
! 2287: insert_after = emit_insn_after (gen_rtx (SET, VOIDmode, profiler_reg,
! 2288: gen_rtx (PLUS, SImode, profiler_reg,
! 2289: const1_rtx)),
! 2290: insert_after);
! 2291:
! 2292: /* This is the same rtx as above, but it is not legal to share this rtx. */
! 2293: mem_ref = gen_rtx (MEM, SImode, gen_rtx (LO_SUM, Pmode, address_reg,
! 2294: profiler_target_addr));
! 2295: emit_insn_after (gen_rtx (SET, VOIDmode, mem_ref, profiler_reg),
1.1 root 2296: insert_after);
2297: }
2298:
2299: /* All the remaining routines in this file have been turned off. */
2300: #if 0
2301: char *
2302: output_tail_call (operands, insn)
2303: rtx *operands;
2304: rtx insn;
2305: {
2306: int this_fsize = actual_fsize;
2307: rtx next;
2308: int need_nop_at_end = 0;
2309:
2310: next = next_real_insn (insn);
2311: while (next && GET_CODE (next) == CODE_LABEL)
2312: next = next_real_insn (insn);
2313:
2314: if (final_sequence && this_fsize > 0)
2315: {
2316: rtx xoperands[1];
2317:
2318: /* If we have to restore any registers, don't take any chances
2319: restoring a register before we discharge it into
2320: its home. If the frame size is only 88, we are guaranteed
2321: that the epilogue will fit in the delay slot. */
2322: rtx delay_insn = XVECEXP (final_sequence, 0, 1);
2323: if (GET_CODE (PATTERN (delay_insn)) == SET)
2324: {
2325: rtx dest = SET_DEST (PATTERN (delay_insn));
2326: if (GET_CODE (dest) == REG
2327: && reg_mentioned_p (dest, insn))
2328: abort ();
2329: }
2330: else if (GET_CODE (PATTERN (delay_insn)) == PARALLEL)
2331: abort ();
2332: xoperands[0] = operands[0];
2333: final_scan_insn (delay_insn, asm_out_file, 0, 0, 1);
2334: operands[0] = xoperands[0];
2335: final_sequence = 0;
2336: }
2337:
2338: /* Make sure we are clear to return. */
2339: output_function_epilogue (asm_out_file, get_frame_size (), -1, 0);
2340:
2341: /* Strip the MEM. */
2342: operands[0] = XEXP (operands[0], 0);
2343:
2344: if (final_sequence == 0
2345: && (next == 0
2346: || GET_CODE (next) == CALL_INSN
2347: || GET_CODE (next) == JUMP_INSN))
2348: need_nop_at_end = 1;
2349:
2350: if (flag_pic)
2351: return output_pic_sequence_2 (2, 3, 0, "jmpl %%g1+%3", operands, need_nop_at_end);
2352:
2353: if (GET_CODE (operands[0]) == REG)
2354: output_asm_insn ("jmpl %a0,%%g0", operands);
2355: else if (TARGET_TAIL_CALL)
2356: {
2357: /* We assume all labels will be within 16 MB of our call. */
2358: if (need_nop_at_end || final_sequence)
2359: output_asm_insn ("b %a0", operands);
2360: else
2361: output_asm_insn ("b,a %a0", operands);
2362: }
2363: else if (! final_sequence)
2364: {
2365: output_asm_insn ("sethi %%hi(%a0),%%g1\n\tjmpl %%g1+%%lo(%a0),%%g1",
2366: operands);
2367: }
2368: else
2369: {
2370: int i;
2371: rtx x = PATTERN (XVECEXP (final_sequence, 0, 1));
2372: for (i = 1; i < 32; i++)
2373: if ((i == 1 || ! fixed_regs[i])
2374: && call_used_regs[i]
2375: && ! refers_to_regno_p (i, i+1, x, 0))
2376: break;
2377: if (i == 32)
2378: abort ();
2379: operands[1] = gen_rtx (REG, SImode, i);
2380: output_asm_insn ("sethi %%hi(%a0),%1\n\tjmpl %1+%%lo(%a0),%1", operands);
2381: }
2382: return (need_nop_at_end ? "nop" : "");
2383: }
2384: #endif
2385:
2386: /* Print operand X (an rtx) in assembler syntax to file FILE.
2387: CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
2388: For `%' followed by punctuation, CODE is the punctuation and X is null. */
2389:
2390: void
2391: print_operand (file, x, code)
2392: FILE *file;
2393: rtx x;
2394: int code;
2395: {
2396: switch (code)
2397: {
2398: case '#':
2399: /* Output a 'nop' if there's nothing for the delay slot. */
2400: if (dbr_sequence_length () == 0)
2401: fputs ("\n\tnop", file);
2402: return;
2403: case '*':
2404: /* Output an annul flag if there's nothing for the delay slot. */
2405: if (dbr_sequence_length () == 0)
2406: fputs (",a", file);
2407: return;
2408: case 'Y':
2409: /* Adjust the operand to take into account a RESTORE operation. */
2410: if (GET_CODE (x) != REG)
2411: abort ();
2412: if (REGNO (x) < 8)
2413: fputs (reg_names[REGNO (x)], file);
2414: else if (REGNO (x) >= 24 && REGNO (x) < 32)
2415: fputs (reg_names[REGNO (x)-16], file);
2416: else
2417: abort ();
2418: return;
2419: case '@':
2420: /* Print out what we are using as the frame pointer. This might
2421: be %fp, or might be %sp+offset. */
2422: fputs (frame_base_name, file);
2423: return;
2424: case 'R':
2425: /* Print out the second register name of a register pair.
2426: I.e., R (%o0) => %o1. */
2427: fputs (reg_names[REGNO (x)+1], file);
2428: return;
2429: case 'm':
2430: /* Print the operand's address only. */
2431: output_address (XEXP (x, 0));
2432: return;
2433: case 'r':
2434: /* In this case we need a register. Use %g0 if the
2435: operand in const0_rtx. */
2436: if (x == const0_rtx)
2437: {
2438: fputs ("%g0", file);
2439: return;
2440: }
2441: else
2442: break;
2443:
2444: case 'A':
2445: switch (GET_CODE (x))
2446: {
2447: case IOR: fputs ("or", file); break;
2448: case AND: fputs ("and", file); break;
2449: case XOR: fputs ("xor", file); break;
2450: default: abort ();
2451: }
2452: return;
2453:
2454: case 'B':
2455: switch (GET_CODE (x))
2456: {
2457: case IOR: fputs ("orn", file); break;
2458: case AND: fputs ("andn", file); break;
2459: case XOR: fputs ("xnor", file); break;
2460: default: abort ();
2461: }
2462: return;
2463:
2464: case 'b':
2465: {
2466: /* Print a sign-extended character. */
2467: int i = INTVAL (x) & 0xff;
2468: if (i & 0x80)
2469: i |= 0xffffff00;
2470: fprintf (file, "%d", i);
2471: return;
2472: }
2473:
2474: case 0:
2475: /* Do nothing special. */
2476: break;
2477:
2478: default:
2479: /* Undocumented flag. */
2480: abort ();
2481: }
2482:
2483: if (GET_CODE (x) == REG)
2484: fputs (reg_names[REGNO (x)], file);
2485: else if (GET_CODE (x) == MEM)
2486: {
2487: fputc ('[', file);
2488: if (CONSTANT_P (XEXP (x, 0)))
2489: /* Poor Sun assembler doesn't understand absolute addressing. */
2490: fputs ("%g0+", file);
2491: output_address (XEXP (x, 0));
2492: fputc (']', file);
2493: }
2494: else if (GET_CODE (x) == HIGH)
2495: {
2496: fputs ("%hi(", file);
2497: output_addr_const (file, XEXP (x, 0));
2498: fputc (')', file);
2499: }
2500: else if (GET_CODE (x) == LO_SUM)
2501: {
2502: print_operand (file, XEXP (x, 0), 0);
2503: fputs ("+%lo(", file);
2504: output_addr_const (file, XEXP (x, 1));
2505: fputc (')', file);
2506: }
2507: else if (GET_CODE (x) == CONST_DOUBLE)
2508: {
2509: if (CONST_DOUBLE_HIGH (x) == 0)
2510: fprintf (file, "%u", CONST_DOUBLE_LOW (x));
2511: else if (CONST_DOUBLE_HIGH (x) == -1
2512: && CONST_DOUBLE_LOW (x) < 0)
2513: fprintf (file, "%d", CONST_DOUBLE_LOW (x));
2514: else
2515: abort ();
2516: }
2517: else { output_addr_const (file, x); }
2518: }
2519:
2520: /* This function outputs assembler code for VALUE to FILE, where VALUE is
2521: a 64 bit (DImode) value. */
2522:
2523: /* ??? If there is a 64 bit counterpart to .word that the assembler
2524: understands, then using that would simply this code greatly. */
2525:
2526: void
2527: output_double_int (file, value)
2528: FILE *file;
2529: rtx value;
2530: {
2531: if (GET_CODE (value) == CONST_INT)
2532: {
2533: if (INTVAL (value) < 0)
2534: ASM_OUTPUT_INT (file, constm1_rtx);
2535: else
2536: ASM_OUTPUT_INT (file, const0_rtx);
2537: ASM_OUTPUT_INT (file, value);
2538: }
2539: else if (GET_CODE (value) == CONST_DOUBLE)
2540: {
2541: ASM_OUTPUT_INT (file, gen_rtx (CONST_INT, VOIDmode,
2542: CONST_DOUBLE_HIGH (value)));
2543: ASM_OUTPUT_INT (file, gen_rtx (CONST_INT, VOIDmode,
2544: CONST_DOUBLE_LOW (value)));
2545: }
2546: else if (GET_CODE (value) == SYMBOL_REF
2547: || GET_CODE (value) == CONST
2548: || GET_CODE (value) == PLUS)
2549: {
2550: /* Addresses are only 32 bits. */
2551: ASM_OUTPUT_INT (file, const0_rtx);
2552: ASM_OUTPUT_INT (file, value);
2553: }
2554: else
2555: abort ();
2556: }
2557:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.