|
|
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 can be used as an operand in a two
410: address arithmetic insn (such as set 123456,%o4) of mode MODE. */
411:
412: int
413: arith32_operand (op, mode)
414: rtx op;
415: enum machine_mode mode;
416: {
417: return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);
418: }
419:
420: /* Return truth value of whether OP is a register or a CONST_DOUBLE. */
421:
422: int
423: arith_double_operand (op, mode)
424: rtx op;
425: enum machine_mode mode;
426: {
427: return (register_operand (op, mode)
428: || (GET_CODE (op) == CONST_DOUBLE
429: && (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
430: && (unsigned) (CONST_DOUBLE_LOW (op) + 0x1000) < 0x2000
431: && ((CONST_DOUBLE_HIGH (op) == -1
432: && (CONST_DOUBLE_LOW (op) & 0x1000) == 0x1000)
433: || (CONST_DOUBLE_HIGH (op) == 0
434: && (CONST_DOUBLE_LOW (op) & 0x1000) == 0)))
435: || (GET_CODE (op) == CONST_INT
436: && (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
437: && (unsigned) (INTVAL (op) + 0x1000) < 0x2000));
438: }
439:
440: /* Return truth value of whether OP is a integer which fits the
441: range constraining immediate operands in three-address insns. */
442:
443: int
444: small_int (op, mode)
445: rtx op;
446: enum machine_mode mode;
447: {
448: return (GET_CODE (op) == CONST_INT && SMALL_INT (op));
449: }
450:
451: /* Return truth value of statement that OP is a call-clobbered register. */
452: int
453: clobbered_register (op, mode)
454: rtx op;
455: enum machine_mode mode;
456: {
457: return (GET_CODE (op) == REG && call_used_regs[REGNO (op)]);
458: }
459:
460: /* X and Y are two things to compare using CODE. Emit the compare insn and
461: return the rtx for register 0 in the proper mode. */
462:
463: rtx
464: gen_compare_reg (code, x, y)
465: enum rtx_code code;
466: rtx x, y;
467: {
468: enum machine_mode mode = SELECT_CC_MODE (code, x);
469: rtx cc_reg = gen_rtx (REG, mode, 0);
470:
471: emit_insn (gen_rtx (SET, VOIDmode, cc_reg,
472: gen_rtx (COMPARE, mode, x, y)));
473:
474: return cc_reg;
475: }
476:
477: /* Return nonzero if a return peephole merging return with
478: setting of output register is ok. */
479: int
480: leaf_return_peephole_ok ()
481: {
482: return (actual_fsize == 0);
483: }
484:
485: /* Return nonzero if TRIAL can go into the function epilogue's
486: delay slot. SLOT is the slot we are trying to fill. */
487:
488: int
489: eligible_for_epilogue_delay (trial, slot)
490: rtx trial;
491: int slot;
492: {
493: static char *this_function_name;
494: rtx pat, src;
495:
496: if (slot >= 1)
497: return 0;
498: if (GET_CODE (trial) != INSN
499: || GET_CODE (PATTERN (trial)) != SET)
500: return 0;
501: if (get_attr_length (trial) != 1)
502: return 0;
503:
504: /* In the case of a true leaf function, anything can
505: go into the delay slot. */
506: if (leaf_function)
507: {
508: if (leaf_return_peephole_ok ())
509: return (get_attr_in_branch_delay (trial) == IN_BRANCH_DELAY_TRUE);
510: return 0;
511: }
512:
513: /* Otherwise, only operations which can be done in tandem with
514: a `restore' insn can go into the delay slot. */
515: pat = PATTERN (trial);
516: if (GET_CODE (SET_DEST (pat)) != REG
517: || REGNO (SET_DEST (pat)) == 0
518: || (leaf_function
519: && REGNO (SET_DEST (pat)) < 32
520: && REGNO (SET_DEST (pat)) >= 16)
521: || (! leaf_function
522: && (REGNO (SET_DEST (pat)) >= 32
523: || REGNO (SET_DEST (pat)) < 24)))
524: return 0;
525: src = SET_SRC (pat);
526: if (arith_operand (src, GET_MODE (src)))
527: return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (SImode);
528: if (arith_double_operand (src, GET_MODE (src)))
529: return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (DImode);
530: if (GET_CODE (src) == PLUS)
531: {
532: if (register_operand (XEXP (src, 0), SImode)
533: && arith_operand (XEXP (src, 1), SImode))
534: return 1;
535: if (register_operand (XEXP (src, 1), SImode)
536: && arith_operand (XEXP (src, 0), SImode))
537: return 1;
538: if (register_operand (XEXP (src, 0), DImode)
539: && arith_double_operand (XEXP (src, 1), DImode))
540: return 1;
541: if (register_operand (XEXP (src, 1), DImode)
542: && arith_double_operand (XEXP (src, 0), DImode))
543: return 1;
544: }
545: if (GET_CODE (src) == MINUS
546: && register_operand (XEXP (src, 0), SImode)
547: && small_int (XEXP (src, 1), VOIDmode))
548: return 1;
549: if (GET_CODE (src) == MINUS
550: && register_operand (XEXP (src, 0), DImode)
551: && !register_operand (XEXP (src, 1), DImode)
552: && arith_double_operand (XEXP (src, 1), DImode))
553: return 1;
554: return 0;
555: }
556:
557: int
558: short_branch (uid1, uid2)
559: int uid1, uid2;
560: {
561: unsigned int delta = insn_addresses[uid1] - insn_addresses[uid2];
562: if (delta + 1024 < 2048)
563: return 1;
564: /* warning ("long branch, distance %d", delta); */
565: return 0;
566: }
567:
568: /* Return non-zero if REG is not used after INSN.
569: We assume REG is a reload reg, and therefore does
570: not live past labels or calls or jumps. */
571: int
572: reg_unused_after (reg, insn)
573: rtx reg;
574: rtx insn;
575: {
576: enum rtx_code code, prev_code = UNKNOWN;
577:
578: while (insn = NEXT_INSN (insn))
579: {
580: if (prev_code == CALL_INSN && call_used_regs[REGNO (reg)])
581: return 1;
582:
583: code = GET_CODE (insn);
584: if (GET_CODE (insn) == CODE_LABEL)
585: return 1;
586:
587: if (GET_RTX_CLASS (code) == 'i')
588: {
589: rtx set = single_set (insn);
590: int in_src = set && reg_overlap_mentioned_p (reg, SET_SRC (set));
591: if (set && in_src)
592: return 0;
593: if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
594: return 1;
595: if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
596: return 0;
597: }
598: prev_code = code;
599: }
600: return 1;
601: }
602:
603: /* Legitimize PIC addresses. If the address is already position-independent,
604: we return ORIG. Newly generated position-independent addresses go into a
605: reg. This is REG if non zero, otherwise we allocate register(s) as
606: necessary. If this is called during reload, and we need a second temp
607: register, then we use SCRATCH, which is provided via the
608: SECONDARY_INPUT_RELOAD_CLASS mechanism. */
609:
610: rtx
611: legitimize_pic_address (orig, mode, reg, scratch)
612: rtx orig;
613: enum machine_mode mode;
614: rtx reg, scratch;
615: {
616: if (GET_CODE (orig) == SYMBOL_REF)
617: {
618: rtx pic_ref, address;
619: rtx insn;
620:
621: if (reg == 0)
622: {
623: if (reload_in_progress)
624: abort ();
625: else
626: reg = gen_reg_rtx (Pmode);
627: }
628:
629: if (flag_pic == 2)
630: {
631: /* If not during reload, allocate another temp reg here for loading
632: in the address, so that these instructions can be optimized
633: properly. */
634: rtx temp_reg = (reload_in_progress ? reg : gen_reg_rtx (Pmode));
635:
636: emit_insn (gen_rtx (SET, VOIDmode, temp_reg,
637: gen_rtx (HIGH, Pmode, orig)));
638: emit_insn (gen_rtx (SET, VOIDmode, temp_reg,
639: gen_rtx (LO_SUM, Pmode, temp_reg, orig)));
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: {
667: if (reload_in_progress)
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));
687: else if (! reload_in_progress)
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. */
1062: /* Trust global variables. */
1063:
1064: if (GET_CODE (op2) == LO_SUM)
1065: {
1066: operands[0] = op1;
1067: operands[1] = op2;
1068:
1069: if (final_sequence)
1070: abort ();
1071: return "ldd %1,%0";
1072: }
1073:
1074: if (GET_CODE (XEXP (op2, 0)) == PLUS)
1075: {
1076: rtx temp = XEXP (op2, 0);
1077: if (GET_CODE (XEXP (temp, 0)) == REG)
1078: base = XEXP (temp, 0), offset = XEXP (temp, 1);
1079: else if (GET_CODE (XEXP (temp, 1)) == REG)
1080: base = XEXP (temp, 1), offset = XEXP (temp, 0);
1081: }
1082:
1083: /* Trust round enough offsets from the stack or frame pointer. */
1084: if (base
1085: && (REGNO (base) == FRAME_POINTER_REGNUM
1086: || REGNO (base) == STACK_POINTER_REGNUM))
1087: {
1088: if (GET_CODE (offset) == CONST_INT
1089: && (INTVAL (offset) & 0x7) == 0)
1090: {
1091: if (op1 == operands[0])
1092: return "ldd %1,%0";
1093: else
1094: return "std %1,%0";
1095: }
1096: }
1097: /* We know structs not on the stack are properly aligned. Since a
1098: double asks for 8-byte alignment, we know it must have got that
1099: if it is in a struct. But a DImode need not be 8-byte aligned,
1100: because it could be a struct containing two ints or pointers. */
1101: else if (GET_CODE (operands[1]) == MEM
1102: && GET_MODE (operands[1]) == DFmode
1103: && (CONSTANT_P (XEXP (operands[1], 0))
1104: /* Let user ask for it anyway. */
1105: || TARGET_ALIGN))
1106: return "ldd %1,%0";
1107: else if (GET_CODE (operands[0]) == MEM
1108: && GET_MODE (operands[0]) == DFmode
1109: && (CONSTANT_P (XEXP (operands[0], 0))
1110: || TARGET_ALIGN))
1111: return "std %1,%0";
1112: }
1113:
1114: if (optype0 == REGOP && optype1 == REGOP
1115: && REGNO (operands[0]) == REGNO (latehalf[1]))
1116: {
1117: /* Make any unoffsettable addresses point at high-numbered word. */
1118: if (addreg0)
1119: output_asm_insn ("add %0,0x4,%0", &addreg0);
1120: if (addreg1)
1121: output_asm_insn ("add %0,0x4,%0", &addreg1);
1122:
1123: /* Do that word. */
1124: output_asm_insn (singlemove_string (latehalf), latehalf);
1125:
1126: /* Undo the adds we just did. */
1127: if (addreg0)
1128: output_asm_insn ("add %0,-0x4,%0", &addreg0);
1129: if (addreg1)
1130: output_asm_insn ("add %0,-0x4,%0", &addreg1);
1131:
1132: /* Do low-numbered word. */
1133: return singlemove_string (operands);
1134: }
1135: else if (optype0 == REGOP && optype1 != REGOP
1136: && reg_overlap_mentioned_p (operands[0], operands[1]))
1137: {
1138: /* Do the late half first. */
1139: output_asm_insn (singlemove_string (latehalf), latehalf);
1140: /* Then clobber. */
1141: return singlemove_string (operands);
1142: }
1143:
1144: /* Normal case: do the two words, low-numbered first. */
1145:
1146: output_asm_insn (singlemove_string (operands), operands);
1147:
1148: /* Make any unoffsettable addresses point at high-numbered word. */
1149: if (addreg0)
1150: output_asm_insn ("add %0,0x4,%0", &addreg0);
1151: if (addreg1)
1152: output_asm_insn ("add %0,0x4,%0", &addreg1);
1153:
1154: /* Do that word. */
1155: output_asm_insn (singlemove_string (latehalf), latehalf);
1156:
1157: /* Undo the adds we just did. */
1158: if (addreg0)
1159: output_asm_insn ("add %0,-0x4,%0", &addreg0);
1160: if (addreg1)
1161: output_asm_insn ("add %0,-0x4,%0", &addreg1);
1162:
1163: return "";
1164: }
1165:
1166: char *
1167: output_fp_move_double (operands)
1168: rtx *operands;
1169: {
1170: rtx addr;
1171:
1172: if (FP_REG_P (operands[0]))
1173: {
1174: if (FP_REG_P (operands[1]))
1175: return "fmovs %1,%0\n\tfmovs %R1,%R0";
1176: if (GET_CODE (operands[1]) == REG)
1177: {
1178: if ((REGNO (operands[1]) & 1) == 0)
1179: return "std %1,[%@-8]\n\tldd [%@-8],%0";
1180: else
1181: return "st %R1,[%@-4]\n\tst %1,[%@-8]\n\tldd [%@-8],%0";
1182: }
1183: addr = XEXP (operands[1], 0);
1184:
1185: /* Use ldd if known to be aligned. */
1186: if (TARGET_ALIGN
1187: || (GET_CODE (addr) == PLUS
1188: && (((XEXP (addr, 0) == frame_pointer_rtx
1189: || XEXP (addr, 0) == stack_pointer_rtx)
1190: && GET_CODE (XEXP (addr, 1)) == CONST_INT
1191: && (INTVAL (XEXP (addr, 1)) & 0x7) == 0)
1192: /* Arrays are known to be aligned,
1193: and reg+reg addresses are used (on this machine)
1194: only for array accesses. */
1195: || (REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))))
1196: || (GET_MODE (operands[0]) == DFmode
1197: && (GET_CODE (addr) == LO_SUM || CONSTANT_P (addr))))
1198: return "ldd %1,%0";
1199:
1200: /* Otherwise use two ld insns. */
1201: operands[2]
1202: = gen_rtx (MEM, GET_MODE (operands[1]),
1203: plus_constant_for_output (addr, 4));
1204: return "ld %1,%0\n\tld %2,%R0";
1205: }
1206: else if (FP_REG_P (operands[1]))
1207: {
1208: if (GET_CODE (operands[0]) == REG)
1209: {
1210: if ((REGNO (operands[0]) & 1) == 0)
1211: return "std %1,[%@-8]\n\tldd [%@-8],%0";
1212: else
1213: return "std %1,[%@-8]\n\tld [%@-4],%R0\n\tld [%@-8],%0";
1214: }
1215: addr = XEXP (operands[0], 0);
1216:
1217: /* Use std if we can be sure it is well-aligned. */
1218: if (TARGET_ALIGN
1219: || (GET_CODE (addr) == PLUS
1220: && (((XEXP (addr, 0) == frame_pointer_rtx
1221: || XEXP (addr, 0) == stack_pointer_rtx)
1222: && GET_CODE (XEXP (addr, 1)) == CONST_INT
1223: && (INTVAL (XEXP (addr, 1)) & 0x7) == 0)
1224: /* Arrays are known to be aligned,
1225: and reg+reg addresses are used (on this machine)
1226: only for array accesses. */
1227: || (REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))))
1228: || (GET_MODE (operands[1]) == DFmode
1229: && (GET_CODE (addr) == LO_SUM || CONSTANT_P (addr))))
1230: return "std %1,%0";
1231:
1232: /* Otherwise use two st insns. */
1233: operands[2]
1234: = gen_rtx (MEM, GET_MODE (operands[0]),
1235: plus_constant_for_output (addr, 4));
1236: return "st %r1,%0\n\tst %R1,%2";
1237: }
1238: else abort ();
1239: }
1240:
1241: /* Return a REG that occurs in ADDR with coefficient 1.
1242: ADDR can be effectively incremented by incrementing REG. */
1243:
1244: static rtx
1245: find_addr_reg (addr)
1246: rtx addr;
1247: {
1248: while (GET_CODE (addr) == PLUS)
1249: {
1250: /* We absolutely can not fudge the frame pointer here, because the
1251: frame pointer must always be 8 byte aligned. It also confuses
1252: debuggers. */
1253: if (GET_CODE (XEXP (addr, 0)) == REG
1254: && REGNO (XEXP (addr, 0)) != FRAME_POINTER_REGNUM)
1255: addr = XEXP (addr, 0);
1256: else if (GET_CODE (XEXP (addr, 1)) == REG
1257: && REGNO (XEXP (addr, 1)) != FRAME_POINTER_REGNUM)
1258: addr = XEXP (addr, 1);
1259: else if (CONSTANT_P (XEXP (addr, 0)))
1260: addr = XEXP (addr, 1);
1261: else if (CONSTANT_P (XEXP (addr, 1)))
1262: addr = XEXP (addr, 0);
1263: else
1264: abort ();
1265: }
1266: if (GET_CODE (addr) == REG)
1267: return addr;
1268: abort ();
1269: }
1270:
1271: void
1272: output_sized_memop (opname, mode, signedp)
1273: char *opname;
1274: enum machine_mode mode;
1275: int signedp;
1276: {
1277: static char *ld_size_suffix_u[] = { "ub", "uh", "", "?", "d" };
1278: static char *ld_size_suffix_s[] = { "sb", "sh", "", "?", "d" };
1279: static char *st_size_suffix[] = { "b", "h", "", "?", "d" };
1280: char **opnametab, *modename;
1281:
1282: if (opname[0] == 'l')
1283: if (signedp)
1284: opnametab = ld_size_suffix_s;
1285: else
1286: opnametab = ld_size_suffix_u;
1287: else
1288: opnametab = st_size_suffix;
1289: modename = opnametab[GET_MODE_SIZE (mode) >> 1];
1290:
1291: fprintf (asm_out_file, "\t%s%s", opname, modename);
1292: }
1293:
1294: void
1295: output_move_with_extension (operands)
1296: rtx *operands;
1297: {
1298: if (GET_MODE (operands[2]) == HImode)
1299: output_asm_insn ("sll %2,0x10,%0", operands);
1300: else if (GET_MODE (operands[2]) == QImode)
1301: output_asm_insn ("sll %2,0x18,%0", operands);
1302: else
1303: abort ();
1304: }
1305:
1306: /* Load the address specified by OPERANDS[3] into the register
1307: specified by OPERANDS[0].
1308:
1309: OPERANDS[3] may be the result of a sum, hence it could either be:
1310:
1311: (1) CONST
1312: (2) REG
1313: (2) REG + CONST_INT
1314: (3) REG + REG + CONST_INT
1315: (4) REG + REG (special case of 3).
1316:
1317: Note that (3) is not a legitimate address.
1318: All cases are handled here. */
1319:
1320: void
1321: output_load_address (operands)
1322: rtx *operands;
1323: {
1324: rtx base, offset;
1325:
1326: if (CONSTANT_P (operands[3]))
1327: {
1328: output_asm_insn ("set %3,%0", operands);
1329: return;
1330: }
1331:
1332: if (REG_P (operands[3]))
1333: {
1334: if (REGNO (operands[0]) != REGNO (operands[3]))
1335: output_asm_insn ("mov %3,%0", operands);
1336: return;
1337: }
1338:
1339: if (GET_CODE (operands[3]) != PLUS)
1340: abort ();
1341:
1342: base = XEXP (operands[3], 0);
1343: offset = XEXP (operands[3], 1);
1344:
1345: if (GET_CODE (base) == CONST_INT)
1346: {
1347: rtx tmp = base;
1348: base = offset;
1349: offset = tmp;
1350: }
1351:
1352: if (GET_CODE (offset) != CONST_INT)
1353: {
1354: /* Operand is (PLUS (REG) (REG)). */
1355: base = operands[3];
1356: offset = const0_rtx;
1357: }
1358:
1359: if (REG_P (base))
1360: {
1361: operands[6] = base;
1362: operands[7] = offset;
1363: if (SMALL_INT (offset))
1364: output_asm_insn ("add %6,%7,%0", operands);
1365: else
1366: output_asm_insn ("set %7,%0\n\tadd %0,%6,%0", operands);
1367: }
1368: else if (GET_CODE (base) == PLUS)
1369: {
1370: operands[6] = XEXP (base, 0);
1371: operands[7] = XEXP (base, 1);
1372: operands[8] = offset;
1373:
1374: if (SMALL_INT (offset))
1375: output_asm_insn ("add %6,%7,%0\n\tadd %0,%8,%0", operands);
1376: else
1377: output_asm_insn ("set %8,%0\n\tadd %0,%6,%0\n\tadd %0,%7,%0", operands);
1378: }
1379: else
1380: abort ();
1381: }
1382:
1383: /* Output code to place a size count SIZE in register REG.
1384: ALIGN is the size of the unit of transfer.
1385:
1386: Because block moves are pipelined, we don't include the
1387: first element in the transfer of SIZE to REG. */
1388:
1389: static void
1390: output_size_for_block_move (size, reg, align)
1391: rtx size, reg;
1392: rtx align;
1393: {
1394: rtx xoperands[3];
1395:
1396: xoperands[0] = reg;
1397: xoperands[1] = size;
1398: xoperands[2] = align;
1399: if (GET_CODE (size) == REG)
1400: output_asm_insn ("sub %1,%2,%0", xoperands);
1401: else
1402: {
1403: xoperands[1]
1404: = gen_rtx (CONST_INT, VOIDmode, INTVAL (size) - INTVAL (align));
1405: output_asm_insn ("set %1,%0", xoperands);
1406: }
1407: }
1408:
1409: /* Emit code to perform a block move.
1410:
1411: OPERANDS[0] is the destination.
1412: OPERANDS[1] is the source.
1413: OPERANDS[2] is the size.
1414: OPERANDS[3] is the alignment safe to use.
1415: OPERANDS[4] is a register we can safely clobber as a temp. */
1416:
1417: char *
1418: output_block_move (operands)
1419: rtx *operands;
1420: {
1421: /* A vector for our computed operands. Note that load_output_address
1422: makes use of (and can clobber) up to the 8th element of this vector. */
1423: rtx xoperands[10];
1424: rtx zoperands[10];
1425: static int movstrsi_label = 0;
1426: int i;
1427: rtx temp1 = operands[4];
1428: rtx sizertx = operands[2];
1429: rtx alignrtx = operands[3];
1430: int align = INTVAL (alignrtx);
1431:
1432: xoperands[0] = operands[0];
1433: xoperands[1] = operands[1];
1434: xoperands[2] = temp1;
1435:
1436: /* We can't move more than this many bytes at a time
1437: because we have only one register to move them through. */
1438: if (align > GET_MODE_SIZE (GET_MODE (temp1)))
1439: {
1440: align = GET_MODE_SIZE (GET_MODE (temp1));
1441: alignrtx = gen_rtx (CONST_INT, VOIDmode, GET_MODE_SIZE (GET_MODE (temp1)));
1442: }
1443:
1444: /* If the size isn't known to be a multiple of the alignment,
1445: we have to do it in smaller pieces. If we could determine that
1446: the size was a multiple of 2 (or whatever), we could be smarter
1447: about this. */
1448: if (GET_CODE (sizertx) != CONST_INT)
1449: align = 1;
1450: else
1451: {
1452: int size = INTVAL (sizertx);
1453: while (size % align)
1454: align >>= 1;
1455: }
1456:
1457: if (align != INTVAL (alignrtx))
1458: alignrtx = gen_rtx (CONST_INT, VOIDmode, align);
1459:
1460: /* Recognize special cases of block moves. These occur
1461: when GNU C++ is forced to treat something as BLKmode
1462: to keep it in memory, when its mode could be represented
1463: with something smaller.
1464:
1465: We cannot do this for global variables, since we don't know
1466: what pages they don't cross. Sigh. */
1467: if (GET_CODE (sizertx) == CONST_INT && INTVAL (sizertx) <= 16)
1468: {
1469: int size = INTVAL (sizertx);
1470:
1471: if (align == 1)
1472: {
1473: if (memory_address_p (QImode,
1474: plus_constant_for_output (xoperands[0], size))
1475: && memory_address_p (QImode,
1476: plus_constant_for_output (xoperands[1],
1477: size)))
1478: {
1479: /* We will store different integers into this particular RTX. */
1480: xoperands[2] = rtx_alloc (CONST_INT);
1481: PUT_MODE (xoperands[2], VOIDmode);
1482: for (i = size-1; i >= 0; i--)
1483: {
1484: INTVAL (xoperands[2]) = i;
1485: output_asm_insn ("ldub [%a1+%2],%%g1\n\tstb %%g1,[%a0+%2]",
1486: xoperands);
1487: }
1488: return "";
1489: }
1490: }
1491: else if (align == 2)
1492: {
1493: if (memory_address_p (HImode,
1494: plus_constant_for_output (xoperands[0], size))
1495: && memory_address_p (HImode,
1496: plus_constant_for_output (xoperands[1],
1497: size)))
1498: {
1499: /* We will store different integers into this particular RTX. */
1500: xoperands[2] = rtx_alloc (CONST_INT);
1501: PUT_MODE (xoperands[2], VOIDmode);
1502: for (i = (size>>1)-1; i >= 0; i--)
1503: {
1504: INTVAL (xoperands[2]) = i<<1;
1505: output_asm_insn ("lduh [%a1+%2],%%g1\n\tsth %%g1,[%a0+%2]",
1506: xoperands);
1507: }
1508: return "";
1509: }
1510: }
1511: else
1512: {
1513: if (memory_address_p (SImode,
1514: plus_constant_for_output (xoperands[0], size))
1515: && memory_address_p (SImode,
1516: plus_constant_for_output (xoperands[1],
1517: size)))
1518: {
1519: /* We will store different integers into this particular RTX. */
1520: xoperands[2] = rtx_alloc (CONST_INT);
1521: PUT_MODE (xoperands[2], VOIDmode);
1522: for (i = (size>>2)-1; i >= 0; i--)
1523: {
1524: INTVAL (xoperands[2]) = i<<2;
1525: output_asm_insn ("ld [%a1+%2],%%g1\n\tst %%g1,[%a0+%2]",
1526: xoperands);
1527: }
1528: return "";
1529: }
1530: }
1531: }
1532:
1533: xoperands[3] = gen_rtx (CONST_INT, VOIDmode, movstrsi_label++);
1534: xoperands[4] = gen_rtx (CONST_INT, VOIDmode, align);
1535: xoperands[5] = gen_rtx (CONST_INT, VOIDmode, movstrsi_label++);
1536:
1537: /* This is the size of the transfer.
1538: Either use the register which already contains the size,
1539: or use a free register (used by no operands).
1540: Also emit code to decrement the size value by ALIGN. */
1541: output_size_for_block_move (sizertx, temp1, alignrtx);
1542:
1543: /* Must handle the case when the size is zero or negative, so the first thing
1544: we do is compare the size against zero, and only copy bytes if it is
1545: zero or greater. Note that we have already subtracted off the alignment
1546: once, so we must copy 1 alignment worth of bytes if the size is zero
1547: here.
1548:
1549: The SUN assembler complains about labels in branch delay slots, so we
1550: do this before outputing the load address, so that there will always
1551: be a harmless insn between the branch here and the next label emitted
1552: below. */
1553:
1554: #ifdef NO_UNDERSCORES
1555: output_asm_insn ("cmp %2,0\n\tbl .Lm%5", xoperands);
1556: #else
1557: output_asm_insn ("cmp %2,0\n\tbl Lm%5", xoperands);
1558: #endif
1559:
1560: zoperands[0] = operands[0];
1561: zoperands[3] = plus_constant_for_output (operands[0], align);
1562: output_load_address (zoperands);
1563:
1564: /* ??? This might be much faster if the loops below were preconditioned
1565: and unrolled.
1566:
1567: That is, at run time, copy enough bytes one at a time to ensure that the
1568: target and source addresses are aligned to the the largest possible
1569: alignment. Then use a preconditioned unrolled loop to copy say 16
1570: bytes at a time. Then copy bytes one at a time until finish the rest. */
1571:
1572: /* Output the first label separately, so that it is spaced properly. */
1573:
1574: #ifdef NO_UNDERSCORES
1575: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, ".Lm", INTVAL (xoperands[3]));
1576: #else
1577: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "Lm", INTVAL (xoperands[3]));
1578: #endif
1579:
1580: #ifdef NO_UNDERSCORES
1581: if (align == 1)
1582: 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);
1583: else if (align == 2)
1584: 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);
1585: else
1586: 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);
1587: return "";
1588: #else
1589: if (align == 1)
1590: output_asm_insn ("ldub [%1+%2],%%g1\n\tsubcc %2,%4,%2\n\tbge Lm%3\n\tstb %%g1,[%0+%2]\nLm%5:", xoperands);
1591: else if (align == 2)
1592: output_asm_insn ("lduh [%1+%2],%%g1\n\tsubcc %2,%4,%2\n\tbge Lm%3\n\tsth %%g1,[%0+%2]\nLm%5:", xoperands);
1593: else
1594: output_asm_insn ("ld [%1+%2],%%g1\n\tsubcc %2,%4,%2\n\tbge Lm%3\n\tst %%g1,[%0+%2]\nLm%5:", xoperands);
1595: return "";
1596: #endif
1597: }
1598:
1599: /* Output reasonable peephole for set-on-condition-code insns.
1600: Note that these insns assume a particular way of defining
1601: labels. Therefore, *both* sparc.h and this function must
1602: be changed if a new syntax is needed. */
1603:
1604: char *
1605: output_scc_insn (operands, insn)
1606: rtx operands[];
1607: rtx insn;
1608: {
1609: static char string[100];
1610: rtx label = 0, next = insn;
1611: int need_label = 0;
1612:
1613: /* Try doing a jump optimization which jump.c can't do for us
1614: because we did not expose that setcc works by using branches.
1615:
1616: If this scc insn is followed by an unconditional branch, then have
1617: the jump insn emitted here jump to that location, instead of to
1618: the end of the scc sequence as usual. */
1619:
1620: do
1621: {
1622: if (GET_CODE (next) == CODE_LABEL)
1623: label = next;
1624: next = NEXT_INSN (next);
1625: if (next == 0)
1626: break;
1627: }
1628: while (GET_CODE (next) == NOTE || GET_CODE (next) == CODE_LABEL);
1629:
1630: /* If we are in a sequence, and the following insn is a sequence also,
1631: then just following the current insn's next field will take us to the
1632: first insn of the next sequence, which is the wrong place. We don't
1633: want to optimize with a branch that has had its delay slot filled.
1634: Avoid this by verifying that NEXT_INSN (PREV_INSN (next)) == next
1635: which fails only if NEXT is such a branch. */
1636:
1637: if (next && GET_CODE (next) == JUMP_INSN && simplejump_p (next)
1638: && (! final_sequence || NEXT_INSN (PREV_INSN (next)) == next))
1639: label = JUMP_LABEL (next);
1640: /* If not optimizing, jump label fields are not set. To be safe, always
1641: check here to whether label is still zero. */
1642: if (label == 0)
1643: {
1644: label = gen_label_rtx ();
1645: need_label = 1;
1646: }
1647:
1648: LABEL_NUSES (label) += 1;
1649:
1650: operands[2] = label;
1651:
1652: /* If we are in a delay slot, assume it is the delay slot of an fpcc
1653: insn since our type isn't allowed anywhere else. */
1654:
1655: /* ??? Fpcc instructions no longer have delay slots, so this code is
1656: probably obsolete. */
1657:
1658: /* The fastest way to emit code for this is an annulled branch followed
1659: by two move insns. This will take two cycles if the branch is taken,
1660: and three cycles if the branch is not taken.
1661:
1662: However, if we are in the delay slot of another branch, this won't work,
1663: because we can't put a branch in the delay slot of another branch.
1664: The above sequence would effectively take 3 or 4 cycles respectively
1665: since a no op would have be inserted between the two branches.
1666: In this case, we want to emit a move, annulled branch, and then the
1667: second move. This sequence always takes 3 cycles, and hence is faster
1668: when we are in a branch delay slot. */
1669:
1670: if (final_sequence)
1671: {
1672: strcpy (string, "mov 0,%0\n\t");
1673: strcat (string, output_cbranch (operands[1], 2, 0, 1, 0));
1674: strcat (string, "\n\tmov 1,%0");
1675: }
1676: else
1677: {
1678: strcpy (string, output_cbranch (operands[1], 2, 0, 1, 0));
1679: strcat (string, "\n\tmov 1,%0\n\tmov 0,%0");
1680: }
1681:
1682: if (need_label)
1683: strcat (string, "\n%l2:");
1684:
1685: return string;
1686: }
1687:
1688: /* Vectors to keep interesting information about registers where
1689: it can easily be got. */
1690:
1691: /* Modes for condition codes. */
1692: #define C_MODES \
1693: ((1 << (int) CCmode) | (1 << (int) CC_NOOVmode) | (1 << (int) CCFPmode))
1694:
1695: /* Modes for single-word (and smaller) quantities. */
1696: #define S_MODES \
1697: (~C_MODES \
1698: & ~ ((1 << (int) DImode) | (1 << (int) TImode) \
1699: | (1 << (int) DFmode) | (1 << (int) TFmode)))
1700:
1701: /* Modes for double-word (and smaller) quantities. */
1702: #define D_MODES \
1703: (~C_MODES \
1704: & ~ ((1 << (int) TImode) | (1 << (int) TFmode)))
1705:
1706: /* Modes for quad-word quantities. */
1707: #define T_MODES (~C_MODES)
1708:
1709: /* Modes for single-float quantities. */
1710: #define SF_MODES ((1 << (int) SFmode))
1711:
1712: /* Modes for double-float quantities. */
1713: #define DF_MODES (SF_MODES | (1 << (int) DFmode) | (1 << (int) SCmode))
1714:
1715: /* Modes for quad-float quantities. */
1716: #define TF_MODES (DF_MODES | (1 << (int) TFmode) | (1 << (int) DCmode))
1717:
1718: /* Value is 1 if register/mode pair is acceptable on sparc.
1719: The funny mixture of D and T modes is because integer operations
1720: do not specially operate on tetra quantities, so non-quad-aligned
1721: registers can hold quadword quantities (except %o4 and %i4 because
1722: they cross fixed registers. */
1723:
1724: int hard_regno_mode_ok[] = {
1725: C_MODES, S_MODES, T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES,
1726: T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES, D_MODES, S_MODES,
1727: T_MODES, S_MODES, T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES,
1728: T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES, D_MODES, S_MODES,
1729:
1730: TF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES,
1731: TF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES,
1732: TF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES,
1733: TF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES};
1734:
1735: #ifdef __GNUC__
1736: inline
1737: #endif
1738: static int
1739: save_regs (file, low, high, base, offset, n_fregs)
1740: FILE *file;
1741: int low, high;
1742: char *base;
1743: int offset;
1744: int n_fregs;
1745: {
1746: int i;
1747:
1748: for (i = low; i < high; i += 2)
1749: {
1750: if (regs_ever_live[i] && ! call_used_regs[i])
1751: if (regs_ever_live[i+1] && ! call_used_regs[i+1])
1752: fprintf (file, "\tstd %s,[%s+%d]\n",
1753: reg_names[i], base, offset + 4 * n_fregs),
1754: n_fregs += 2;
1755: else
1756: fprintf (file, "\tst %s,[%s+%d]\n",
1757: reg_names[i], base, offset + 4 * n_fregs),
1758: n_fregs += 2;
1759: else if (regs_ever_live[i+1] && ! call_used_regs[i+1])
1760: fprintf (file, "\tst %s,[%s+%d]\n",
1761: reg_names[i+1], base, offset + 4 * n_fregs),
1762: n_fregs += 2;
1763: }
1764: return n_fregs;
1765: }
1766:
1767: #ifdef __GNUC__
1768: inline
1769: #endif
1770: static int
1771: restore_regs (file, low, high, base, offset, n_fregs)
1772: FILE *file;
1773: int low, high;
1774: char *base;
1775: int offset;
1776: {
1777: int i;
1778:
1779: for (i = low; i < high; i += 2)
1780: {
1781: if (regs_ever_live[i] && ! call_used_regs[i])
1782: if (regs_ever_live[i+1] && ! call_used_regs[i+1])
1783: fprintf (file, "\tldd [%s+%d], %s\n",
1784: base, offset + 4 * n_fregs, reg_names[i]),
1785: n_fregs += 2;
1786: else
1787: fprintf (file, "\tld [%s+%d],%s\n",
1788: base, offset + 4 * n_fregs, reg_names[i]),
1789: n_fregs += 2;
1790: else if (regs_ever_live[i+1] && ! call_used_regs[i+1])
1791: fprintf (file, "\tld [%s+%d],%s\n",
1792: base, offset + 4 * n_fregs, reg_names[i+1]),
1793: n_fregs += 2;
1794: }
1795: return n_fregs;
1796: }
1797:
1798: /* Static variables we want to share between prologue and epilogue. */
1799:
1800: /* Number of live floating point registers needed to be saved. */
1801: static int num_fregs;
1802:
1803: /* Nonzero if any floating point register was ever used. */
1804: static int fregs_ever_live;
1805:
1806: int
1807: compute_frame_size (size, leaf_function)
1808: int size;
1809: int leaf_function;
1810: {
1811: int fregs_ever_live = 0;
1812: int n_fregs = 0, i;
1813: int outgoing_args_size = (current_function_outgoing_args_size
1814: + REG_PARM_STACK_SPACE (current_function_decl));
1815:
1816: apparent_fsize = ((size) + 7 - STARTING_FRAME_OFFSET) & -8;
1817: for (i = 32; i < FIRST_PSEUDO_REGISTER; i += 2)
1818: fregs_ever_live |= regs_ever_live[i]|regs_ever_live[i+1];
1819:
1820: if (TARGET_EPILOGUE && fregs_ever_live)
1821: {
1822: for (i = 32; i < FIRST_PSEUDO_REGISTER; i += 2)
1823: if ((regs_ever_live[i] && ! call_used_regs[i])
1824: || (regs_ever_live[i+1] && ! call_used_regs[i+1]))
1825: n_fregs += 2;
1826: }
1827:
1828: /* Set up values for use in `function_epilogue'. */
1829: num_fregs = n_fregs;
1830:
1831: apparent_fsize += (outgoing_args_size+7) & -8;
1832: if (leaf_function && n_fregs == 0
1833: && apparent_fsize == (REG_PARM_STACK_SPACE (current_function_decl)
1834: - STARTING_FRAME_OFFSET))
1835: apparent_fsize = 0;
1836:
1837: actual_fsize = apparent_fsize + n_fregs*4;
1838:
1839: /* Make sure nothing can clobber our register windows.
1840: If a SAVE must be done, or there is a stack-local variable,
1841: the register window area must be allocated. */
1842: if (leaf_function == 0 || size > 0)
1843: actual_fsize += (16 * UNITS_PER_WORD)+8;
1844:
1845: return actual_fsize;
1846: }
1847:
1848: void
1849: output_function_prologue (file, size, leaf_function)
1850: FILE *file;
1851: int size;
1852: {
1853: if (leaf_function)
1854: frame_base_name = "%sp+80";
1855: else
1856: frame_base_name = "%fp";
1857:
1858: actual_fsize = compute_frame_size (size, leaf_function);
1859:
1860: fprintf (file, "\t!#PROLOGUE# 0\n");
1861: if (actual_fsize == 0) /* do nothing. */ ;
1862: else if (actual_fsize < 4096)
1863: {
1864: if (! leaf_function)
1865: fprintf (file, "\tsave %%sp,-%d,%%sp\n", actual_fsize);
1866: else
1867: fprintf (file, "\tadd %%sp,-%d,%%sp\n", actual_fsize);
1868: }
1869: else if (! leaf_function)
1870: {
1871: /* Need to use actual_fsize, since we are also allocating space for
1872: our callee (and our own register save area). */
1873: fprintf (file, "\tsethi %%hi(%d),%%g1\n\tor %%g1,%%lo(%d),%%g1\n",
1874: -actual_fsize, -actual_fsize);
1875: fprintf (file, "\tsave %%sp,%%g1,%%sp\n");
1876: }
1877: else
1878: {
1879: /* Put pointer to parameters into %g4, and allocate
1880: frame space using result computed into %g1. actual_fsize
1881: used instead of apparent_fsize for reasons stated above. */
1882: abort ();
1883:
1884: fprintf (file, "\tsethi %%hi(%d),%%g1\n\tor %%g1,%%lo(%d),%%g1\n",
1885: -actual_fsize, -actual_fsize);
1886: fprintf (file, "\tadd %%sp,64,%%g4\n\tadd %%sp,%%g1,%%sp\n");
1887: }
1888:
1889: /* If doing anything with PIC, do it now. */
1890: if (! flag_pic)
1891: fprintf (file, "\t!#PROLOGUE# 1\n");
1892:
1893: /* Figure out where to save any special registers. */
1894: if (num_fregs)
1895: {
1896: int offset, n_fregs = num_fregs;
1897:
1898: if (! leaf_function)
1899: offset = -apparent_fsize;
1900: else
1901: offset = 0;
1902:
1903: if (TARGET_EPILOGUE && ! leaf_function)
1904: n_fregs = save_regs (file, 0, 16, frame_base_name, offset, 0);
1905: else if (leaf_function)
1906: n_fregs = save_regs (file, 0, 32, frame_base_name, offset, 0);
1907: if (TARGET_EPILOGUE)
1908: save_regs (file, 32, FIRST_PSEUDO_REGISTER,
1909: frame_base_name, offset, n_fregs);
1910: }
1911:
1912: if (regs_ever_live[62])
1913: fprintf (file, "\tst %s,[%s-16]\n\tst %s,[%s-12]\n",
1914: reg_names[0], frame_base_name,
1915: reg_names[0], frame_base_name);
1916:
1917: leaf_label = 0;
1918: if (leaf_function && actual_fsize != 0)
1919: {
1920: /* warning ("leaf procedure with frame size %d", actual_fsize); */
1921: if (! TARGET_EPILOGUE)
1922: leaf_label = gen_label_rtx ();
1923: }
1924: }
1925:
1926: void
1927: output_function_epilogue (file, size, leaf_function, true_epilogue)
1928: FILE *file;
1929: int size;
1930: {
1931: int n_fregs, i;
1932: char *ret;
1933:
1934: if (leaf_label)
1935: {
1936: if (leaf_function < 0)
1937: abort ();
1938: emit_label_after (leaf_label, get_last_insn ());
1939: final_scan_insn (get_last_insn (), file, 0, 0, 1);
1940: }
1941:
1942: if (num_fregs)
1943: {
1944: int offset, n_fregs = num_fregs;
1945:
1946: if (! leaf_function)
1947: offset = -apparent_fsize;
1948: else
1949: offset = 0;
1950:
1951: if (TARGET_EPILOGUE && ! leaf_function)
1952: n_fregs = restore_regs (file, 0, 16, frame_base_name, offset, 0);
1953: else if (leaf_function)
1954: n_fregs = restore_regs (file, 0, 32, frame_base_name, offset, 0);
1955: if (TARGET_EPILOGUE)
1956: restore_regs (file, 32, FIRST_PSEUDO_REGISTER,
1957: frame_base_name, offset, n_fregs);
1958: }
1959:
1960: /* Work out how to skip the caller's unimp instruction if required. */
1961: if (leaf_function)
1962: ret = (current_function_returns_struct ? "jmp %o7+12" : "retl");
1963: else
1964: ret = (current_function_returns_struct ? "jmp %i7+12" : "ret");
1965:
1966: /* Tail calls have to do this work themselves. */
1967: if (leaf_function >= 0)
1968: {
1969: if (TARGET_EPILOGUE || leaf_label)
1970: {
1971: int old_target_epilogue = TARGET_EPILOGUE;
1972: target_flags &= ~old_target_epilogue;
1973:
1974: if (! leaf_function)
1975: {
1976: /* If we wound up with things in our delay slot,
1977: flush them here. */
1978: if (current_function_epilogue_delay_list)
1979: {
1980: rtx insn = emit_jump_insn_after (gen_rtx (RETURN, VOIDmode),
1981: get_last_insn ());
1982: PATTERN (insn) = gen_rtx (PARALLEL, VOIDmode,
1983: gen_rtvec (2,
1984: PATTERN (XEXP (current_function_epilogue_delay_list, 0)),
1985: PATTERN (insn)));
1986: final_scan_insn (insn, file, 1, 0, 1);
1987: }
1988: else
1989: fprintf (file, "\t%s\n\trestore\n", ret);
1990: }
1991: else if (actual_fsize < 4096)
1992: {
1993: if (current_function_epilogue_delay_list)
1994: {
1995: fprintf (file, "\t%s\n", ret);
1996: final_scan_insn (XEXP (current_function_epilogue_delay_list, 0),
1997: file, 1, 0, 1);
1998: }
1999: else
2000: fprintf (file, "\t%s\n\tadd %%sp,%d,%%sp\n",
2001: ret, actual_fsize);
2002: }
2003: else
2004: {
2005: if (current_function_epilogue_delay_list)
2006: abort ();
2007: fprintf (file, "\tsethi %%hi(%d),%%g1\n\tor %%g1,%%lo(%d),%%g1\n\t%s\n\tadd %%sp,%%g1,%%sp\n",
2008: actual_fsize, actual_fsize, ret);
2009: }
2010: target_flags |= old_target_epilogue;
2011: }
2012: }
2013: else if (true_epilogue)
2014: {
2015: /* We may still need a return insn! Somebody could jump around
2016: the tail-calls that this function makes. */
2017: if (TARGET_EPILOGUE)
2018: {
2019: rtx last = get_last_insn ();
2020:
2021: last = prev_nonnote_insn (last);
2022: if (last == 0
2023: || (GET_CODE (last) != JUMP_INSN && GET_CODE (last) != BARRIER))
2024: fprintf (file, "\t%s\n\tnop\n", ret);
2025: }
2026: }
2027: }
2028:
2029: /* Return the string to output a conditional branch to LABEL, which is
2030: the operand number of the label. OP is the conditional expression. The
2031: mode of register 0 says what kind of comparison we made.
2032:
2033: REVERSED is non-zero if we should reverse the sense of the comparison.
2034:
2035: ANNUL is non-zero if we should generate an annulling branch.
2036:
2037: NOOP is non-zero if we have to follow this branch by a noop. */
2038:
2039: char *
2040: output_cbranch (op, label, reversed, annul, noop)
2041: rtx op;
2042: int label;
2043: int reversed, annul, noop;
2044: {
2045: static char string[20];
2046: enum rtx_code code = GET_CODE (op);
2047: enum machine_mode mode = GET_MODE (XEXP (op, 0));
2048: static char labelno[] = " %lX";
2049:
2050: /* ??? FP branches can not be preceeded by another floating point insn.
2051: Because there is currently no concept of pre-delay slots, we can fix
2052: this only by always emitting a nop before a floating point branch. */
2053:
2054: if (mode == CCFPmode)
2055: strcpy (string, "nop\n\t");
2056:
2057: /* If not floating-point or if EQ or NE, we can just reverse the code. */
2058: if (reversed && (mode != CCFPmode || code == EQ || code == NE))
2059: code = reverse_condition (code), reversed = 0;
2060:
2061: /* Start by writing the branch condition. */
2062: switch (code)
2063: {
2064: case NE:
2065: if (mode == CCFPmode)
2066: strcat (string, "fbne");
2067: else
2068: strcpy (string, "bne");
2069: break;
2070:
2071: case EQ:
2072: if (mode == CCFPmode)
2073: strcat (string, "fbe");
2074: else
2075: strcpy (string, "be");
2076: break;
2077:
2078: case GE:
2079: if (mode == CCFPmode)
2080: {
2081: if (reversed)
2082: strcat (string, "fbul");
2083: else
2084: strcat (string, "fbge");
2085: }
2086: else if (mode == CC_NOOVmode)
2087: strcpy (string, "bpos");
2088: else
2089: strcpy (string, "bge");
2090: break;
2091:
2092: case GT:
2093: if (mode == CCFPmode)
2094: {
2095: if (reversed)
2096: strcat (string, "fbule");
2097: else
2098: strcat (string, "fbg");
2099: }
2100: else
2101: strcpy (string, "bg");
2102: break;
2103:
2104: case LE:
2105: if (mode == CCFPmode)
2106: {
2107: if (reversed)
2108: strcat (string, "fbug");
2109: else
2110: strcat (string, "fble");
2111: }
2112: else
2113: strcpy (string, "ble");
2114: break;
2115:
2116: case LT:
2117: if (mode == CCFPmode)
2118: {
2119: if (reversed)
2120: strcat (string, "fbuge");
2121: else
2122: strcat (string, "fbl");
2123: }
2124: else if (mode == CC_NOOVmode)
2125: strcpy (string, "bneg");
2126: else
2127: strcpy (string, "bl");
2128: break;
2129:
2130: case GEU:
2131: strcpy (string, "bgeu");
2132: break;
2133:
2134: case GTU:
2135: strcpy (string, "bgu");
2136: break;
2137:
2138: case LEU:
2139: strcpy (string, "bleu");
2140: break;
2141:
2142: case LTU:
2143: strcpy (string, "blu");
2144: break;
2145: }
2146:
2147: /* Now add the annulling, the label, and a possible noop. */
2148: if (annul)
2149: strcat (string, ",a");
2150:
2151: labelno[3] = label + '0';
2152: strcat (string, labelno);
2153:
2154: if (noop)
2155: strcat (string, "\n\tnop");
2156:
2157: return string;
2158: }
2159:
2160: char *
2161: output_return (operands)
2162: rtx *operands;
2163: {
2164: if (leaf_label)
2165: {
2166: operands[0] = leaf_label;
2167: return "b,a %l0";
2168: }
2169: else if (leaf_function)
2170: {
2171: operands[0] = gen_rtx (CONST_INT, VOIDmode, actual_fsize);
2172: if (actual_fsize < 4096)
2173: {
2174: if (current_function_returns_struct)
2175: return "jmp %%o7+12\n\tadd %%sp,%0,%%sp";
2176: else
2177: return "retl\n\tadd %%sp,%0,%%sp";
2178: }
2179: else
2180: {
2181: if (current_function_returns_struct)
2182: return "sethi %%hi(%a0),%%g1\n\tor %%g1,%%lo(%a0),%%g1\n\tjmp %%o7+12\n\tadd %%sp,%%g1,%%sp";
2183: else
2184: return "sethi %%hi(%a0),%%g1\n\tor %%g1,%%lo(%a0),%%g1\n\tretl\n\tadd %%sp,%%g1,%%sp";
2185: }
2186: }
2187: else
2188: {
2189: if (current_function_returns_struct)
2190: return "jmp %%i7+12\n\trestore";
2191: else
2192: return "ret\n\trestore";
2193: }
2194: }
2195:
2196: char *
2197: output_floatsisf2 (operands)
2198: rtx *operands;
2199: {
2200: if (GET_CODE (operands[1]) == MEM)
2201: return "ld %1,%0\n\tfitos %0,%0";
2202: else if (FP_REG_P (operands[1]))
2203: return "fitos %1,%0";
2204: return "st %r1,[%%fp-4]\n\tld [%%fp-4],%0\n\tfitos %0,%0";
2205: }
2206:
2207: char *
2208: output_floatsidf2 (operands)
2209: rtx *operands;
2210: {
2211: if (GET_CODE (operands[1]) == MEM)
2212: return "ld %1,%0\n\tfitod %0,%0";
2213: else if (FP_REG_P (operands[1]))
2214: return "fitod %1,%0";
2215: return "st %r1,[%%fp-4]\n\tld [%%fp-4],%0\n\tfitod %0,%0";
2216: }
2217:
2218: int
2219: tail_call_valid_p ()
2220: {
2221: static int checked = 0;
2222: static int valid_p = 0;
2223:
2224: if (! checked)
2225: {
2226: register int i;
2227:
2228: checked = 1;
2229: for (i = 32; i < FIRST_PSEUDO_REGISTER; i++)
2230: if (! fixed_regs[i] && ! call_used_regs[i])
2231: return 0;
2232: valid_p = 1;
2233: }
2234: return valid_p;
2235: }
2236:
2237: /* Leaf functions and non-leaf functions have different needs. */
2238:
2239: static int
2240: reg_leaf_alloc_order[] = REG_LEAF_ALLOC_ORDER;
2241:
2242: static int
2243: reg_nonleaf_alloc_order[] = REG_ALLOC_ORDER;
2244:
2245: static int *reg_alloc_orders[] = {
2246: reg_leaf_alloc_order,
2247: reg_nonleaf_alloc_order};
2248:
2249: void
2250: order_regs_for_local_alloc ()
2251: {
2252: static int last_order_nonleaf = 1;
2253:
2254: if (regs_ever_live[15] != last_order_nonleaf)
2255: {
2256: last_order_nonleaf = !last_order_nonleaf;
2257: bcopy (reg_alloc_orders[last_order_nonleaf], reg_alloc_order,
2258: FIRST_PSEUDO_REGISTER * sizeof (int));
2259: }
2260: }
2261:
2262: /* Machine dependent routines for the branch probability, arc profiling
2263: code. */
2264:
2265: /* The label used by the arc profiling code. */
2266:
2267: static rtx profiler_label;
2268:
2269: void
2270: init_arc_profiler ()
2271: {
2272: /* Generate and save a copy of this so it can be shared. */
2273: profiler_label = gen_rtx (SYMBOL_REF, Pmode, "*LPBX2");
2274: }
2275:
2276: void
2277: output_arc_profiler (arcno, insert_after)
2278: int arcno;
2279: rtx insert_after;
2280: {
2281: rtx profiler_target_addr
2282: = gen_rtx (CONST, Pmode,
2283: gen_rtx (PLUS, Pmode, profiler_label,
2284: gen_rtx (CONST_INT, VOIDmode, 4 * arcno)));
2285: register rtx profiler_reg = gen_reg_rtx (SImode);
2286: register rtx temp = gen_reg_rtx (Pmode);
2287: register rtx profiler_target = gen_rtx (MEM, SImode,
2288: gen_rtx (LO_SUM, Pmode, temp,
2289: profiler_target_addr));
2290: /* The insns are emitted from last to first after the insn insert_after.
2291: Emit_insn_after is used because sometimes we want to put the
2292: instrumentation code after the last insn of the function. */
2293: emit_insn_after (gen_rtx (SET, VOIDmode, profiler_target, profiler_reg),
2294: insert_after);
2295: emit_insn_after (gen_rtx (SET, VOIDmode, profiler_reg,
2296: gen_rtx (PLUS, SImode, profiler_reg, const1_rtx)),
2297: insert_after);
2298: emit_insn_after (gen_rtx (SET, VOIDmode, profiler_reg, profiler_target),
2299: insert_after);
2300: emit_insn_after (gen_rtx (SET, VOIDmode, temp,
2301: gen_rtx (HIGH, Pmode, profiler_target_addr)),
2302: insert_after);
2303: }
2304:
2305: /* All the remaining routines in this file have been turned off. */
2306: #if 0
2307: char *
2308: output_tail_call (operands, insn)
2309: rtx *operands;
2310: rtx insn;
2311: {
2312: int this_fsize = actual_fsize;
2313: rtx next;
2314: int need_nop_at_end = 0;
2315:
2316: next = next_real_insn (insn);
2317: while (next && GET_CODE (next) == CODE_LABEL)
2318: next = next_real_insn (insn);
2319:
2320: if (final_sequence && this_fsize > 0)
2321: {
2322: rtx xoperands[1];
2323:
2324: /* If we have to restore any registers, don't take any chances
2325: restoring a register before we discharge it into
2326: its home. If the frame size is only 88, we are guaranteed
2327: that the epilogue will fit in the delay slot. */
2328: rtx delay_insn = XVECEXP (final_sequence, 0, 1);
2329: if (GET_CODE (PATTERN (delay_insn)) == SET)
2330: {
2331: rtx dest = SET_DEST (PATTERN (delay_insn));
2332: if (GET_CODE (dest) == REG
2333: && reg_mentioned_p (dest, insn))
2334: abort ();
2335: }
2336: else if (GET_CODE (PATTERN (delay_insn)) == PARALLEL)
2337: abort ();
2338: xoperands[0] = operands[0];
2339: final_scan_insn (delay_insn, asm_out_file, 0, 0, 1);
2340: operands[0] = xoperands[0];
2341: final_sequence = 0;
2342: }
2343:
2344: /* Make sure we are clear to return. */
2345: output_function_epilogue (asm_out_file, get_frame_size (), -1, 0);
2346:
2347: /* Strip the MEM. */
2348: operands[0] = XEXP (operands[0], 0);
2349:
2350: if (final_sequence == 0
2351: && (next == 0
2352: || GET_CODE (next) == CALL_INSN
2353: || GET_CODE (next) == JUMP_INSN))
2354: need_nop_at_end = 1;
2355:
2356: if (flag_pic)
2357: return output_pic_sequence_2 (2, 3, 0, "jmpl %%g1+%3", operands, need_nop_at_end);
2358:
2359: if (GET_CODE (operands[0]) == REG)
2360: output_asm_insn ("jmpl %a0,%%g0", operands);
2361: else if (TARGET_TAIL_CALL)
2362: {
2363: /* We assume all labels will be within 16 MB of our call. */
2364: if (need_nop_at_end || final_sequence)
2365: output_asm_insn ("b %a0", operands);
2366: else
2367: output_asm_insn ("b,a %a0", operands);
2368: }
2369: else if (! final_sequence)
2370: {
2371: output_asm_insn ("sethi %%hi(%a0),%%g1\n\tjmpl %%g1+%%lo(%a0),%%g1",
2372: operands);
2373: }
2374: else
2375: {
2376: int i;
2377: rtx x = PATTERN (XVECEXP (final_sequence, 0, 1));
2378: for (i = 1; i < 32; i++)
2379: if ((i == 1 || ! fixed_regs[i])
2380: && call_used_regs[i]
2381: && ! refers_to_regno_p (i, i+1, x, 0))
2382: break;
2383: if (i == 32)
2384: abort ();
2385: operands[1] = gen_rtx (REG, SImode, i);
2386: output_asm_insn ("sethi %%hi(%a0),%1\n\tjmpl %1+%%lo(%a0),%1", operands);
2387: }
2388: return (need_nop_at_end ? "nop" : "");
2389: }
2390: #endif
2391:
2392: /* Print operand X (an rtx) in assembler syntax to file FILE.
2393: CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
2394: For `%' followed by punctuation, CODE is the punctuation and X is null. */
2395:
2396: void
2397: print_operand (file, x, code)
2398: FILE *file;
2399: rtx x;
2400: int code;
2401: {
2402: switch (code)
2403: {
2404: case '#':
2405: /* Output a 'nop' if there's nothing for the delay slot. */
2406: if (dbr_sequence_length () == 0)
2407: fputs ("\n\tnop", file);
2408: return;
2409: case '*':
2410: /* Output an annul flag if there's nothing for the delay slot. */
2411: if (dbr_sequence_length () == 0)
2412: fputs (",a", file);
2413: return;
2414: case 'Y':
2415: /* Adjust the operand to take into account a RESTORE operation. */
2416: if (GET_CODE (x) != REG)
2417: abort ();
2418: if (REGNO (x) < 8)
2419: fputs (reg_names[REGNO (x)], file);
2420: else if (REGNO (x) >= 24 && REGNO (x) < 32)
2421: fputs (reg_names[REGNO (x)-16], file);
2422: else
2423: abort ();
2424: return;
2425: case '@':
2426: /* Print out what we are using as the frame pointer. This might
2427: be %fp, or might be %sp+offset. */
2428: fputs (frame_base_name, file);
2429: return;
2430: case 'R':
2431: /* Print out the second register name of a register pair.
2432: I.e., R (%o0) => %o1. */
2433: fputs (reg_names[REGNO (x)+1], file);
2434: return;
2435: case 'm':
2436: /* Print the operand's address only. */
2437: output_address (XEXP (x, 0));
2438: return;
2439: case 'r':
2440: /* In this case we need a register. Use %g0 if the
2441: operand in const0_rtx. */
2442: if (x == const0_rtx)
2443: {
2444: fputs ("%g0", file);
2445: return;
2446: }
2447: else
2448: break;
2449:
2450: case 'A':
2451: switch (GET_CODE (x))
2452: {
2453: case IOR: fputs ("or", file); break;
2454: case AND: fputs ("and", file); break;
2455: case XOR: fputs ("xor", file); break;
2456: default: abort ();
2457: }
2458: return;
2459:
2460: case 'B':
2461: switch (GET_CODE (x))
2462: {
2463: case IOR: fputs ("orn", file); break;
2464: case AND: fputs ("andn", file); break;
2465: case XOR: fputs ("xnor", file); break;
2466: default: abort ();
2467: }
2468: return;
2469:
2470: case 'b':
2471: {
2472: /* Print a sign-extended character. */
2473: int i = INTVAL (x) & 0xff;
2474: if (i & 0x80)
2475: i |= 0xffffff00;
2476: fprintf (file, "%d", i);
2477: return;
2478: }
2479:
2480: case 0:
2481: /* Do nothing special. */
2482: break;
2483:
2484: default:
2485: /* Undocumented flag. */
2486: abort ();
2487: }
2488:
2489: if (GET_CODE (x) == REG)
2490: fputs (reg_names[REGNO (x)], file);
2491: else if (GET_CODE (x) == MEM)
2492: {
2493: fputc ('[', file);
2494: if (CONSTANT_P (XEXP (x, 0)))
2495: /* Poor Sun assembler doesn't understand absolute addressing. */
2496: fputs ("%g0+", file);
2497: output_address (XEXP (x, 0));
2498: fputc (']', file);
2499: }
2500: else if (GET_CODE (x) == HIGH)
2501: {
2502: fputs ("%hi(", file);
2503: output_addr_const (file, XEXP (x, 0));
2504: fputc (')', file);
2505: }
2506: else if (GET_CODE (x) == LO_SUM)
2507: {
2508: print_operand (file, XEXP (x, 0), 0);
2509: fputs ("+%lo(", file);
2510: output_addr_const (file, XEXP (x, 1));
2511: fputc (')', file);
2512: }
2513: else if (GET_CODE (x) == CONST_DOUBLE)
2514: {
2515: if (CONST_DOUBLE_HIGH (x) == 0)
2516: fprintf (file, "%u", CONST_DOUBLE_LOW (x));
2517: else if (CONST_DOUBLE_HIGH (x) == -1
2518: && CONST_DOUBLE_LOW (x) < 0)
2519: fprintf (file, "%d", CONST_DOUBLE_LOW (x));
2520: else
2521: abort ();
2522: }
2523: else { output_addr_const (file, x); }
2524: }
2525:
2526: /* This function outputs assembler code for VALUE to FILE, where VALUE is
2527: a 64 bit (DImode) value. */
2528:
2529: /* ??? If there is a 64 bit counterpart to .word that the assembler
2530: understands, then using that would simply this code greatly. */
2531:
2532: void
2533: output_double_int (file, value)
2534: FILE *file;
2535: rtx value;
2536: {
2537: if (GET_CODE (value) == CONST_INT)
2538: {
2539: if (INTVAL (value) < 0)
2540: ASM_OUTPUT_INT (file, constm1_rtx);
2541: else
2542: ASM_OUTPUT_INT (file, const0_rtx);
2543: ASM_OUTPUT_INT (file, value);
2544: }
2545: else if (GET_CODE (value) == CONST_DOUBLE)
2546: {
2547: ASM_OUTPUT_INT (file, gen_rtx (CONST_INT, VOIDmode,
2548: CONST_DOUBLE_HIGH (value)));
2549: ASM_OUTPUT_INT (file, gen_rtx (CONST_INT, VOIDmode,
2550: CONST_DOUBLE_LOW (value)));
2551: }
2552: else if (GET_CODE (value) == SYMBOL_REF
2553: || GET_CODE (value) == CONST
2554: || GET_CODE (value) == PLUS)
2555: {
2556: /* Addresses are only 32 bits. */
2557: ASM_OUTPUT_INT (file, const0_rtx);
2558: ASM_OUTPUT_INT (file, value);
2559: }
2560: else
2561: abort ();
2562: }
2563:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.