|
|
1.1 root 1: /* Subroutines for insn-output.c for Intel 860
2: Copyright (C) 1989, 1991 Free Software Foundation, Inc.
3: Derived from sparc.c.
4:
5: Written by Richard Stallman ([email protected]).
6:
7: Hacked substantially by Ron Guilmette ([email protected]) to cater
8: to the whims of the System V Release 4 assembler.
9:
10: This file is part of GNU CC.
11:
12: GNU CC is free software; you can redistribute it and/or modify
13: it under the terms of the GNU General Public License as published by
14: the Free Software Foundation; either version 2, or (at your option)
15: any later version.
16:
17: GNU CC is distributed in the hope that it will be useful,
18: but WITHOUT ANY WARRANTY; without even the implied warranty of
19: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20: GNU General Public License for more details.
21:
22: You should have received a copy of the GNU General Public License
23: along with GNU CC; see the file COPYING. If not, write to
24: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
25:
26:
27: #include "config.h"
28: #include "flags.h"
29: #include "rtl.h"
30: #include "regs.h"
31: #include "hard-reg-set.h"
32: #include "real.h"
33: #include "insn-config.h"
34: #include "conditions.h"
35: #include "insn-flags.h"
36: #include "output.h"
37: #include "recog.h"
38: #include "insn-attr.h"
39:
40: #include <stdio.h>
41:
42: static rtx find_addr_reg ();
43:
44: #ifndef I860_REG_PREFIX
45: #define I860_REG_PREFIX ""
46: #endif
47:
48: char *i860_reg_prefix = I860_REG_PREFIX;
49:
50: /* Save information from a "cmpxx" operation until the branch is emitted. */
51:
52: rtx i860_compare_op0, i860_compare_op1;
53:
54: /* Return non-zero if this pattern, can be evaluated safely, even if it
55: was not asked for. */
56: int
57: safe_insn_src_p (op, mode)
58: rtx op;
59: enum machine_mode mode;
60: {
61: /* Just experimenting. */
62:
63: /* No floating point src is safe if it contains an arithmetic
64: operation, since that operation may trap. */
65: switch (GET_CODE (op))
66: {
67: case CONST_INT:
68: case LABEL_REF:
69: case SYMBOL_REF:
70: case CONST:
71: return 1;
72:
73: case REG:
74: return 1;
75:
76: case MEM:
77: return CONSTANT_ADDRESS_P (XEXP (op, 0));
78:
79: /* We never need to negate or complement constants. */
80: case NEG:
81: return (mode != SFmode && mode != DFmode);
82: case NOT:
83: case ZERO_EXTEND:
84: return 1;
85:
86: case EQ:
87: case NE:
88: case LT:
89: case GT:
90: case LE:
91: case GE:
92: case LTU:
93: case GTU:
94: case LEU:
95: case GEU:
96: case MINUS:
97: case PLUS:
98: return (mode != SFmode && mode != DFmode);
99: case AND:
100: case IOR:
101: case XOR:
102: case LSHIFT:
103: case ASHIFT:
104: case ASHIFTRT:
105: case LSHIFTRT:
106: if ((GET_CODE (XEXP (op, 0)) == CONST_INT && ! SMALL_INT (XEXP (op, 0)))
107: || (GET_CODE (XEXP (op, 1)) == CONST_INT && ! SMALL_INT (XEXP (op, 1))))
108: return 0;
109: return 1;
110:
111: default:
112: return 0;
113: }
114: }
115:
116: /* Return 1 if REG is clobbered in IN.
117: Return 2 if REG is used in IN.
118: Return 3 if REG is both used and clobbered in IN.
119: Return 0 if neither. */
120:
121: static int
122: reg_clobbered_p (reg, in)
123: rtx reg;
124: rtx in;
125: {
126: register enum rtx_code code;
127:
128: if (in == 0)
129: return 0;
130:
131: code = GET_CODE (in);
132:
133: if (code == SET || code == CLOBBER)
134: {
135: rtx dest = SET_DEST (in);
136: int set = 0;
137: int used = 0;
138:
139: while (GET_CODE (dest) == STRICT_LOW_PART
140: || GET_CODE (dest) == SUBREG
141: || GET_CODE (dest) == SIGN_EXTRACT
142: || GET_CODE (dest) == ZERO_EXTRACT)
143: dest = XEXP (dest, 0);
144:
145: if (dest == reg)
146: set = 1;
147: else if (GET_CODE (dest) == REG
148: && refers_to_regno_p (REGNO (reg),
149: REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
150: SET_DEST (in), 0))
151: {
152: set = 1;
153: /* Anything that sets just part of the register
154: is considered using as well as setting it.
155: But note that a straight SUBREG of a single-word value
156: clobbers the entire value. */
157: if (dest != SET_DEST (in)
158: && ! (GET_CODE (SET_DEST (in)) == SUBREG
159: || UNITS_PER_WORD >= GET_MODE_SIZE (GET_MODE (dest))))
160: used = 1;
161: }
162:
163: if (code == SET)
164: {
165: if (set)
166: used = refers_to_regno_p (REGNO (reg),
167: REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
168: SET_SRC (in), 0);
169: else
170: used = refers_to_regno_p (REGNO (reg),
171: REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
172: in, 0);
173: }
174:
175: return set + used * 2;
176: }
177:
178: if (refers_to_regno_p (REGNO (reg),
179: REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
180: in, 0))
181: return 2;
182: return 0;
183: }
184:
185: /* Return non-zero if OP can be written to without screwing up
186: GCC's model of what's going on. It is assumed that this operand
187: appears in the dest position of a SET insn in a conditional
188: branch's delay slot. AFTER is the label to start looking from. */
189: int
190: operand_clobbered_before_used_after (op, after)
191: rtx op;
192: rtx after;
193: {
194: /* Just experimenting. */
195: if (GET_CODE (op) == CC0)
196: return 1;
197: if (GET_CODE (op) == REG)
198: {
199: rtx insn;
200:
201: if (op == stack_pointer_rtx)
202: return 0;
203:
204: /* Scan forward from the label, to see if the value of OP
205: is clobbered before the first use. */
206:
207: for (insn = NEXT_INSN (after); insn; insn = NEXT_INSN (insn))
208: {
209: if (GET_CODE (insn) == NOTE)
210: continue;
211: if (GET_CODE (insn) == INSN
212: || GET_CODE (insn) == JUMP_INSN
213: || GET_CODE (insn) == CALL_INSN)
214: {
215: switch (reg_clobbered_p (op, PATTERN (insn)))
216: {
217: default:
218: return 0;
219: case 1:
220: return 1;
221: case 0:
222: break;
223: }
224: }
225: /* If we reach another label without clobbering OP,
226: then we cannot safely write it here. */
227: else if (GET_CODE (insn) == CODE_LABEL)
228: return 0;
229: if (GET_CODE (insn) == JUMP_INSN)
230: {
231: if (condjump_p (insn))
232: return 0;
233: /* This is a jump insn which has already
234: been mangled. We can't tell what it does. */
235: if (GET_CODE (PATTERN (insn)) == PARALLEL)
236: return 0;
237: if (! JUMP_LABEL (insn))
238: return 0;
239: /* Keep following jumps. */
240: insn = JUMP_LABEL (insn);
241: }
242: }
243: return 1;
244: }
245:
246: /* In both of these cases, the first insn executed
247: for this op will be a orh whatever%h,%?r0,%?r31,
248: which is tolerable. */
249: if (GET_CODE (op) == MEM)
250: return (CONSTANT_ADDRESS_P (XEXP (op, 0)));
251:
252: return 0;
253: }
254:
255: /* Return non-zero if this pattern, as a source to a "SET",
256: is known to yield an instruction of unit size. */
257: int
258: single_insn_src_p (op, mode)
259: rtx op;
260: enum machine_mode mode;
261: {
262: switch (GET_CODE (op))
263: {
264: case CONST_INT:
265: /* This is not always a single insn src, technically,
266: but output_delayed_branch knows how to deal with it. */
267: return 1;
268:
269: case SYMBOL_REF:
270: case CONST:
271: /* This is not a single insn src, technically,
272: but output_delayed_branch knows how to deal with it. */
273: return 1;
274:
275: case REG:
276: return 1;
277:
278: case MEM:
279: return 1;
280:
281: /* We never need to negate or complement constants. */
282: case NEG:
283: return (mode != DFmode);
284: case NOT:
285: case ZERO_EXTEND:
286: return 1;
287:
288: case PLUS:
289: case MINUS:
290: /* Detect cases that require multiple instructions. */
291: if (CONSTANT_P (XEXP (op, 1))
292: && !(GET_CODE (XEXP (op, 1)) == CONST_INT
293: && SMALL_INT (XEXP (op, 1))))
294: return 0;
295: case EQ:
296: case NE:
297: case LT:
298: case GT:
299: case LE:
300: case GE:
301: case LTU:
302: case GTU:
303: case LEU:
304: case GEU:
305: /* Not doing floating point, since they probably
306: take longer than the branch slot they might fill. */
307: return (mode != SFmode && mode != DFmode);
308:
309: case AND:
310: if (GET_CODE (XEXP (op, 1)) == NOT)
311: {
312: rtx arg = XEXP (XEXP (op, 1), 0);
313: if (CONSTANT_P (arg)
314: && !(GET_CODE (arg) == CONST_INT
315: && (SMALL_INT (arg)
316: || INTVAL (arg) & 0xffff == 0)))
317: return 0;
318: }
319: case IOR:
320: case XOR:
321: /* Both small and round numbers take one instruction;
322: others take two. */
323: if (CONSTANT_P (XEXP (op, 1))
324: && !(GET_CODE (XEXP (op, 1)) == CONST_INT
325: && (SMALL_INT (XEXP (op, 1))
326: || INTVAL (XEXP (op, 1)) & 0xffff == 0)))
327: return 0;
328:
329: case LSHIFT:
330: case ASHIFT:
331: case ASHIFTRT:
332: case LSHIFTRT:
333: return 1;
334:
335: case SUBREG:
336: if (SUBREG_WORD (op) != 0)
337: return 0;
338: return single_insn_src_p (SUBREG_REG (op), mode);
339:
340: /* Not doing floating point, since they probably
341: take longer than the branch slot they might fill. */
342: case FLOAT_EXTEND:
343: case FLOAT_TRUNCATE:
344: case FLOAT:
345: case FIX:
346: case UNSIGNED_FLOAT:
347: case UNSIGNED_FIX:
348: return 0;
349:
350: default:
351: return 0;
352: }
353: }
354:
355: /* Return non-zero only if OP is a register of mode MODE,
356: or const0_rtx. */
357: int
358: reg_or_0_operand (op, mode)
359: rtx op;
360: enum machine_mode mode;
361: {
362: return (op == const0_rtx || register_operand (op, mode)
363: || op == CONST0_RTX (mode));
364: }
365:
366: /* Return truth value of whether OP can be used as an operands in a three
367: address add/subtract insn (such as add %o1,7,%l2) of mode MODE. */
368:
369: int
370: arith_operand (op, mode)
371: rtx op;
372: enum machine_mode mode;
373: {
374: return (register_operand (op, mode)
375: || (GET_CODE (op) == CONST_INT && SMALL_INT (op)));
376: }
377:
378: /* Return 1 if OP is a valid first operand for a logical insn of mode MODE. */
379:
380: int
381: logic_operand (op, mode)
382: rtx op;
383: enum machine_mode mode;
384: {
385: return (register_operand (op, mode)
386: || (GET_CODE (op) == CONST_INT && LOGIC_INT (op)));
387: }
388:
389: /* Return 1 if OP is a valid first operand for a shift insn of mode MODE. */
390:
391: int
392: shift_operand (op, mode)
393: rtx op;
394: enum machine_mode mode;
395: {
396: return (register_operand (op, mode)
397: || (GET_CODE (op) == CONST_INT));
398: }
399:
400: /* Return 1 if OP is a valid first operand for either a logical insn
401: or an add insn of mode MODE. */
402:
403: int
404: compare_operand (op, mode)
405: rtx op;
406: enum machine_mode mode;
407: {
408: return (register_operand (op, mode)
409: || (GET_CODE (op) == CONST_INT && SMALL_INT (op) && LOGIC_INT (op)));
410: }
411:
412: /* Return truth value of whether OP can be used as the 5-bit immediate
413: operand of a bte or btne insn. */
414:
415: int
416: bte_operand (op, mode)
417: rtx op;
418: enum machine_mode mode;
419: {
420: return (register_operand (op, mode)
421: || (GET_CODE (op) == CONST_INT
422: && (unsigned) INTVAL (op) < 0x20));
423: }
424:
425: /* Return 1 if OP is an indexed memory reference of mode MODE. */
426:
427: int
428: indexed_operand (op, mode)
429: rtx op;
430: enum machine_mode mode;
431: {
432: return (GET_CODE (op) == MEM && GET_MODE (op) == mode
433: && GET_CODE (XEXP (op, 0)) == PLUS
434: && GET_MODE (XEXP (op, 0)) == SImode
435: && register_operand (XEXP (XEXP (op, 0), 0), SImode)
436: && register_operand (XEXP (XEXP (op, 0), 1), SImode));
437: }
438:
439: /* Return 1 if OP is a suitable source operand for a load insn
440: with mode MODE. */
441:
442: int
443: load_operand (op, mode)
444: rtx op;
445: enum machine_mode mode;
446: {
447: return (memory_operand (op, mode) || indexed_operand (op, mode));
448: }
449:
450: /* Return truth value of whether OP is a integer which fits the
451: range constraining immediate operands in add/subtract insns. */
452:
453: int
454: small_int (op, mode)
455: rtx op;
456: enum machine_mode mode;
457: {
458: return (GET_CODE (op) == CONST_INT && SMALL_INT (op));
459: }
460:
461: /* Return truth value of whether OP is a integer which fits the
462: range constraining immediate operands in logic insns. */
463:
464: int
465: logic_int (op, mode)
466: rtx op;
467: enum machine_mode mode;
468: {
469: return (GET_CODE (op) == CONST_INT && LOGIC_INT (op));
470: }
471:
472: /* Test for a valid operand for a call instruction.
473: Don't allow the arg pointer register or virtual regs
474: since they may change into reg + const, which the patterns
475: can't handle yet. */
476:
477: int
478: call_insn_operand (op, mode)
479: rtx op;
480: enum machine_mode mode;
481: {
482: if (GET_CODE (op) == MEM
483: && (CONSTANT_ADDRESS_P (XEXP (op, 0))
484: || (GET_CODE (XEXP (op, 0)) == REG
485: && XEXP (op, 0) != arg_pointer_rtx
486: && !(REGNO (XEXP (op, 0)) >= FIRST_PSEUDO_REGISTER
487: && REGNO (XEXP (op, 0)) <= LAST_VIRTUAL_REGISTER))))
488: return 1;
489: return 0;
490: }
491:
492: /* Return the best assembler insn template
493: for moving operands[1] into operands[0] as a fullword. */
494:
495: static char *
496: singlemove_string (operands)
497: rtx *operands;
498: {
499: if (GET_CODE (operands[0]) == MEM)
500: {
501: if (GET_CODE (operands[1]) != MEM)
502: if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
503: {
504: if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
505: && (cc_prev_status.flags & CC_HI_R31_ADJ)
506: && cc_prev_status.mdep == XEXP (operands[0], 0)))
507: {
508: CC_STATUS_INIT;
509: output_asm_insn ("orh %h0,%?r0,%?r31", operands);
510: }
511: cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
512: cc_status.mdep = XEXP (operands[0], 0);
513: return "st.l %r1,%L0(%?r31)";
514: }
515: else
516: return "st.l %r1,%0";
517: else
518: abort ();
519: #if 0
520: {
521: rtx xoperands[2];
522:
523: cc_status.flags &= ~CC_F0_IS_0;
524: xoperands[0] = gen_rtx (REG, SFmode, 32);
525: xoperands[1] = operands[1];
526: output_asm_insn (singlemove_string (xoperands), xoperands);
527: xoperands[1] = xoperands[0];
528: xoperands[0] = operands[0];
529: output_asm_insn (singlemove_string (xoperands), xoperands);
530: return "";
531: }
532: #endif
533: }
534: if (GET_CODE (operands[1]) == MEM)
535: {
536: if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
537: {
538: if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
539: && (cc_prev_status.flags & CC_HI_R31_ADJ)
540: && cc_prev_status.mdep == XEXP (operands[1], 0)))
541: {
542: CC_STATUS_INIT;
543: output_asm_insn ("orh %h1,%?r0,%?r31", operands);
544: }
545: cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
546: cc_status.mdep = XEXP (operands[1], 0);
547: return "ld.l %L1(%?r31),%0";
548: }
549: return "ld.l %m1,%0";
550: }
551: if (GET_CODE (operands[1]) == CONST_INT)
552: {
553: if (operands[1] == const0_rtx)
554: return "mov %?r0,%0";
555: if((INTVAL (operands[1]) & 0xffff0000) == 0)
556: return "or %L1,%?r0,%0";
557: if((INTVAL (operands[1]) & 0xffff8000) == 0xffff8000)
558: return "adds %1,%?r0,%0";
559: if((INTVAL (operands[1]) & 0x0000ffff) == 0)
560: return "orh %H1,%?r0,%0";
561: }
562: return "mov %1,%0";
563: }
564:
565: /* Output assembler code to perform a doubleword move insn
566: with operands OPERANDS. */
567:
568: char *
569: output_move_double (operands)
570: rtx *operands;
571: {
572: enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
573: rtx latehalf[2];
574: rtx addreg0 = 0, addreg1 = 0;
575: int highest_first = 0;
576: int no_addreg1_decrement = 0;
577:
578: /* First classify both operands. */
579:
580: if (REG_P (operands[0]))
581: optype0 = REGOP;
582: else if (offsettable_memref_p (operands[0]))
583: optype0 = OFFSOP;
584: else if (GET_CODE (operands[0]) == MEM)
585: optype0 = MEMOP;
586: else
587: optype0 = RNDOP;
588:
589: if (REG_P (operands[1]))
590: optype1 = REGOP;
591: else if (CONSTANT_P (operands[1]))
592: optype1 = CNSTOP;
593: else if (offsettable_memref_p (operands[1]))
594: optype1 = OFFSOP;
595: else if (GET_CODE (operands[1]) == MEM)
596: optype1 = MEMOP;
597: else
598: optype1 = RNDOP;
599:
600: /* Check for the cases that the operand constraints are not
601: supposed to allow to happen. Abort if we get one,
602: because generating code for these cases is painful. */
603:
604: if (optype0 == RNDOP || optype1 == RNDOP)
605: abort ();
606:
607: /* If an operand is an unoffsettable memory ref, find a register
608: we can increment temporarily to make it refer to the second word. */
609:
610: if (optype0 == MEMOP)
611: addreg0 = find_addr_reg (XEXP (operands[0], 0));
612:
613: if (optype1 == MEMOP)
614: addreg1 = find_addr_reg (XEXP (operands[1], 0));
615:
616: /* ??? Perhaps in some cases move double words
617: if there is a spare pair of floating regs. */
618:
619: /* Ok, we can do one word at a time.
620: Normally we do the low-numbered word first,
621: but if either operand is autodecrementing then we
622: do the high-numbered word first.
623:
624: In either case, set up in LATEHALF the operands to use
625: for the high-numbered word and in some cases alter the
626: operands in OPERANDS to be suitable for the low-numbered word. */
627:
628: if (optype0 == REGOP)
629: latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
630: else if (optype0 == OFFSOP)
631: latehalf[0] = adj_offsettable_operand (operands[0], 4);
632: else
633: latehalf[0] = operands[0];
634:
635: if (optype1 == REGOP)
636: latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
637: else if (optype1 == OFFSOP)
638: latehalf[1] = adj_offsettable_operand (operands[1], 4);
639: else if (optype1 == CNSTOP)
640: {
641: if (GET_CODE (operands[1]) == CONST_DOUBLE)
642: split_double (operands[1], &operands[1], &latehalf[1]);
643: else if (CONSTANT_P (operands[1]))
644: latehalf[1] = const0_rtx;
645: }
646: else
647: latehalf[1] = operands[1];
648:
649: /* If the first move would clobber the source of the second one,
650: do them in the other order.
651:
652: RMS says "This happens only for registers;
653: such overlap can't happen in memory unless the user explicitly
654: sets it up, and that is an undefined circumstance."
655:
656: but it happens on the sparc when loading parameter registers,
657: so I am going to define that circumstance, and make it work
658: as expected. */
659:
660: if (optype0 == REGOP && optype1 == REGOP
661: && REGNO (operands[0]) == REGNO (latehalf[1]))
662: {
663: CC_STATUS_PARTIAL_INIT;
664: /* Make any unoffsettable addresses point at high-numbered word. */
665: if (addreg0)
666: output_asm_insn ("adds 0x4,%0,%0", &addreg0);
667: if (addreg1)
668: output_asm_insn ("adds 0x4,%0,%0", &addreg1);
669:
670: /* Do that word. */
671: output_asm_insn (singlemove_string (latehalf), latehalf);
672:
673: /* Undo the adds we just did. */
674: if (addreg0)
675: output_asm_insn ("adds -0x4,%0,%0", &addreg0);
676: if (addreg1)
677: output_asm_insn ("adds -0x4,%0,%0", &addreg1);
678:
679: /* Do low-numbered word. */
680: return singlemove_string (operands);
681: }
682: else if (optype0 == REGOP && optype1 != REGOP
683: && reg_overlap_mentioned_p (operands[0], operands[1]))
684: {
685: /* If both halves of dest are used in the src memory address,
686: add the two regs and put them in the low reg (operands[0]).
687: Then it works to load latehalf first. */
688: if (reg_mentioned_p (operands[0], XEXP (operands[1], 0))
689: && reg_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
690: {
691: rtx xops[2];
692: xops[0] = latehalf[0];
693: xops[1] = operands[0];
694: output_asm_insn ("adds %1,%0,%1", xops);
695: operands[1] = gen_rtx (MEM, DImode, operands[0]);
696: latehalf[1] = adj_offsettable_operand (operands[1], 4);
697: addreg1 = 0;
698: highest_first = 1;
699: }
700: /* Only one register in the dest is used in the src memory address,
701: and this is the first register of the dest, so we want to do
702: the late half first here also. */
703: else if (! reg_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
704: highest_first = 1;
705: /* Only one register in the dest is used in the src memory address,
706: and this is the second register of the dest, so we want to do
707: the late half last. If addreg1 is set, and addreg1 is the same
708: register as latehalf, then we must suppress the trailing decrement,
709: because it would clobber the value just loaded. */
710: else if (addreg1 && reg_mentioned_p (addreg1, latehalf[0]))
711: no_addreg1_decrement = 1;
712: }
713:
714: /* Normal case: do the two words, low-numbered first.
715: Overlap case (highest_first set): do high-numbered word first. */
716:
717: if (! highest_first)
718: output_asm_insn (singlemove_string (operands), operands);
719:
720: CC_STATUS_PARTIAL_INIT;
721: /* Make any unoffsettable addresses point at high-numbered word. */
722: if (addreg0)
723: output_asm_insn ("adds 0x4,%0,%0", &addreg0);
724: if (addreg1)
725: output_asm_insn ("adds 0x4,%0,%0", &addreg1);
726:
727: /* Do that word. */
728: output_asm_insn (singlemove_string (latehalf), latehalf);
729:
730: /* Undo the adds we just did. */
731: if (addreg0)
732: output_asm_insn ("adds -0x4,%0,%0", &addreg0);
733: if (addreg1 && !no_addreg1_decrement)
734: output_asm_insn ("adds -0x4,%0,%0", &addreg1);
735:
736: if (highest_first)
737: output_asm_insn (singlemove_string (operands), operands);
738:
739: return "";
740: }
741:
742: char *
743: output_fp_move_double (operands)
744: rtx *operands;
745: {
746: /* If the source operand is any sort of zero, use f0 instead. */
747:
748: if (operands[1] == CONST0_RTX (GET_MODE (operands[1])))
749: operands[1] = gen_rtx (REG, DFmode, F0_REGNUM);
750:
751: if (FP_REG_P (operands[0]))
752: {
753: if (FP_REG_P (operands[1]))
754: return "fmov.dd %1,%0";
755: if (GET_CODE (operands[1]) == REG)
756: {
757: output_asm_insn ("ixfr %1,%0", operands);
758: operands[0] = gen_rtx (REG, VOIDmode, REGNO (operands[0]) + 1);
759: operands[1] = gen_rtx (REG, VOIDmode, REGNO (operands[1]) + 1);
760: return "ixfr %1,%0";
761: }
762: if (operands[1] == CONST0_RTX (DFmode))
763: return "fmov.dd f0,%0";
764: if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
765: {
766: if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
767: && (cc_prev_status.flags & CC_HI_R31_ADJ)
768: && cc_prev_status.mdep == XEXP (operands[1], 0)))
769: {
770: CC_STATUS_INIT;
771: output_asm_insn ("orh %h1,%?r0,%?r31", operands);
772: }
773: cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
774: cc_status.mdep = XEXP (operands[1], 0);
775: return "fld.d %L1(%?r31),%0";
776: }
777: return "fld.d %1,%0";
778: }
779: else if (FP_REG_P (operands[1]))
780: {
781: if (GET_CODE (operands[0]) == REG)
782: {
783: output_asm_insn ("fxfr %1,%0", operands);
784: operands[0] = gen_rtx (REG, VOIDmode, REGNO (operands[0]) + 1);
785: operands[1] = gen_rtx (REG, VOIDmode, REGNO (operands[1]) + 1);
786: return "fxfr %1,%0";
787: }
788: if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
789: {
790: if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
791: && (cc_prev_status.flags & CC_HI_R31_ADJ)
792: && cc_prev_status.mdep == XEXP (operands[0], 0)))
793: {
794: CC_STATUS_INIT;
795: output_asm_insn ("orh %h0,%?r0,%?r31", operands);
796: }
797: cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
798: cc_status.mdep = XEXP (operands[0], 0);
799: return "fst.d %1,%L0(%?r31)";
800: }
801: return "fst.d %1,%0";
802: }
803: else
804: abort ();
805: /* NOTREACHED */
806: return NULL;
807: }
808:
809: /* Return a REG that occurs in ADDR with coefficient 1.
810: ADDR can be effectively incremented by incrementing REG. */
811:
812: static rtx
813: find_addr_reg (addr)
814: rtx addr;
815: {
816: while (GET_CODE (addr) == PLUS)
817: {
818: if (GET_CODE (XEXP (addr, 0)) == REG)
819: addr = XEXP (addr, 0);
820: else if (GET_CODE (XEXP (addr, 1)) == REG)
821: addr = XEXP (addr, 1);
822: else if (CONSTANT_P (XEXP (addr, 0)))
823: addr = XEXP (addr, 1);
824: else if (CONSTANT_P (XEXP (addr, 1)))
825: addr = XEXP (addr, 0);
826: else
827: abort ();
828: }
829: if (GET_CODE (addr) == REG)
830: return addr;
831: abort ();
832: /* NOTREACHED */
833: return NULL;
834: }
835:
836: /* Return a template for a load instruction with mode MODE and
837: arguments from the string ARGS.
838:
839: This string is in static storage. */
840:
841: static char *
842: load_opcode (mode, args, reg)
843: enum machine_mode mode;
844: char *args;
845: rtx reg;
846: {
847: static char buf[30];
848: char *opcode;
849:
850: switch (mode)
851: {
852: case QImode:
853: opcode = "ld.b";
854: break;
855:
856: case HImode:
857: opcode = "ld.s";
858: break;
859:
860: case SImode:
861: case SFmode:
862: if (FP_REG_P (reg))
863: opcode = "fld.l";
864: else
865: opcode = "ld.l";
866: break;
867:
868: case DImode:
869: if (!FP_REG_P (reg))
870: abort ();
871: case DFmode:
872: opcode = "fld.d";
873: break;
874:
875: default:
876: abort ();
877: }
878:
879: sprintf (buf, "%s %s", opcode, args);
880: return buf;
881: }
882:
883: /* Return a template for a store instruction with mode MODE and
884: arguments from the string ARGS.
885:
886: This string is in static storage. */
887:
888: static char *
889: store_opcode (mode, args, reg)
890: enum machine_mode mode;
891: char *args;
892: rtx reg;
893: {
894: static char buf[30];
895: char *opcode;
896:
897: switch (mode)
898: {
899: case QImode:
900: opcode = "st.b";
901: break;
902:
903: case HImode:
904: opcode = "st.s";
905: break;
906:
907: case SImode:
908: case SFmode:
909: if (FP_REG_P (reg))
910: opcode = "fst.l";
911: else
912: opcode = "st.l";
913: break;
914:
915: case DImode:
916: if (!FP_REG_P (reg))
917: abort ();
918: case DFmode:
919: opcode = "fst.d";
920: break;
921:
922: default:
923: abort ();
924: }
925:
926: sprintf (buf, "%s %s", opcode, args);
927: return buf;
928: }
929:
930: /* Output a store-in-memory whose operands are OPERANDS[0,1].
931: OPERANDS[0] is a MEM, and OPERANDS[1] is a reg or zero.
932:
933: This function returns a template for an insn.
934: This is in static storage.
935:
936: It may also output some insns directly.
937: It may alter the values of operands[0] and operands[1]. */
938:
939: char *
940: output_store (operands)
941: rtx *operands;
942: {
943: enum machine_mode mode = GET_MODE (operands[0]);
944: rtx address = XEXP (operands[0], 0);
945: char *string;
946:
947: cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
948: cc_status.mdep = address;
949:
950: if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
951: && (cc_prev_status.flags & CC_HI_R31_ADJ)
952: && address == cc_prev_status.mdep))
953: {
954: CC_STATUS_INIT;
955: output_asm_insn ("orh %h0,%?r0,%?r31", operands);
956: cc_prev_status.mdep = address;
957: }
958:
959: /* Store zero in two parts when appropriate. */
960: if (mode == DFmode && operands[1] == CONST0_RTX (DFmode))
961: return store_opcode (DFmode, "%r1,%L0(%?r31)", operands[1]);
962:
963: /* Code below isn't smart enough to move a doubleword in two parts,
964: so use output_move_double to do that in the cases that require it. */
965: if ((mode == DImode || mode == DFmode)
966: && ! FP_REG_P (operands[1]))
967: return output_move_double (operands);
968:
969: return store_opcode (mode, "%r1,%L0(%?r31)", operands[1]);
970: }
971:
972: /* Output a load-from-memory whose operands are OPERANDS[0,1].
973: OPERANDS[0] is a reg, and OPERANDS[1] is a mem.
974:
975: This function returns a template for an insn.
976: This is in static storage.
977:
978: It may also output some insns directly.
979: It may alter the values of operands[0] and operands[1]. */
980:
981: char *
982: output_load (operands)
983: rtx *operands;
984: {
985: enum machine_mode mode = GET_MODE (operands[0]);
986: rtx address = XEXP (operands[1], 0);
987:
988: /* We don't bother trying to see if we know %hi(address).
989: This is because we are doing a load, and if we know the
990: %hi value, we probably also know that value in memory. */
991: cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
992: cc_status.mdep = address;
993:
994: if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
995: && (cc_prev_status.flags & CC_HI_R31_ADJ)
996: && address == cc_prev_status.mdep
997: && cc_prev_status.mdep == cc_status.mdep))
998: {
999: CC_STATUS_INIT;
1000: output_asm_insn ("orh %h1,%?r0,%?r31", operands);
1001: cc_prev_status.mdep = address;
1002: }
1003:
1004: /* Code below isn't smart enough to move a doubleword in two parts,
1005: so use output_move_double to do that in the cases that require it. */
1006: if ((mode == DImode || mode == DFmode)
1007: && ! FP_REG_P (operands[0]))
1008: return output_move_double (operands);
1009:
1010: return load_opcode (mode, "%L1(%?r31),%0", operands[0]);
1011: }
1012:
1013: #if 0
1014: /* Load the address specified by OPERANDS[3] into the register
1015: specified by OPERANDS[0].
1016:
1017: OPERANDS[3] may be the result of a sum, hence it could either be:
1018:
1019: (1) CONST
1020: (2) REG
1021: (2) REG + CONST_INT
1022: (3) REG + REG + CONST_INT
1023: (4) REG + REG (special case of 3).
1024:
1025: Note that (3) is not a legitimate address.
1026: All cases are handled here. */
1027:
1028: void
1029: output_load_address (operands)
1030: rtx *operands;
1031: {
1032: rtx base, offset;
1033:
1034: if (CONSTANT_P (operands[3]))
1035: {
1036: output_asm_insn ("mov %3,%0", operands);
1037: return;
1038: }
1039:
1040: if (REG_P (operands[3]))
1041: {
1042: if (REGNO (operands[0]) != REGNO (operands[3]))
1043: output_asm_insn ("shl %?r0,%3,%0", operands);
1044: return;
1045: }
1046:
1047: if (GET_CODE (operands[3]) != PLUS)
1048: abort ();
1049:
1050: base = XEXP (operands[3], 0);
1051: offset = XEXP (operands[3], 1);
1052:
1053: if (GET_CODE (base) == CONST_INT)
1054: {
1055: rtx tmp = base;
1056: base = offset;
1057: offset = tmp;
1058: }
1059:
1060: if (GET_CODE (offset) != CONST_INT)
1061: {
1062: /* Operand is (PLUS (REG) (REG)). */
1063: base = operands[3];
1064: offset = const0_rtx;
1065: }
1066:
1067: if (REG_P (base))
1068: {
1069: operands[6] = base;
1070: operands[7] = offset;
1071: CC_STATUS_PARTIAL_INIT;
1072: if (SMALL_INT (offset))
1073: output_asm_insn ("adds %7,%6,%0", operands);
1074: else
1075: output_asm_insn ("mov %7,%0\n\tadds %0,%6,%0", operands);
1076: }
1077: else if (GET_CODE (base) == PLUS)
1078: {
1079: operands[6] = XEXP (base, 0);
1080: operands[7] = XEXP (base, 1);
1081: operands[8] = offset;
1082:
1083: CC_STATUS_PARTIAL_INIT;
1084: if (SMALL_INT (offset))
1085: output_asm_insn ("adds %6,%7,%0\n\tadds %8,%0,%0", operands);
1086: else
1087: output_asm_insn ("mov %8,%0\n\tadds %0,%6,%0\n\tadds %0,%7,%0", operands);
1088: }
1089: else
1090: abort ();
1091: }
1092: #endif
1093:
1094: /* Output code to place a size count SIZE in register REG.
1095: Because block moves are pipelined, we don't include the
1096: first element in the transfer of SIZE to REG.
1097: For this, we subtract ALIGN. (Actually, I think it is not
1098: right to subtract on this machine, so right now we don't.) */
1099:
1100: static void
1101: output_size_for_block_move (size, reg, align)
1102: rtx size, reg, align;
1103: {
1104: rtx xoperands[3];
1105:
1106: xoperands[0] = reg;
1107: xoperands[1] = size;
1108: xoperands[2] = align;
1109:
1110: #if 1
1111: cc_status.flags &= ~ CC_KNOW_HI_R31;
1112: output_asm_insn (singlemove_string (xoperands), xoperands);
1113: #else
1114: if (GET_CODE (size) == REG)
1115: output_asm_insn ("sub %2,%1,%0", xoperands);
1116: else
1117: {
1118: xoperands[1]
1119: = gen_rtx (CONST_INT, VOIDmode, INTVAL (size) - INTVAL (align));
1120: cc_status.flags &= ~ CC_KNOW_HI_R31;
1121: output_asm_insn ("mov %1,%0", xoperands);
1122: }
1123: #endif
1124: }
1125:
1126: /* Emit code to perform a block move.
1127:
1128: OPERANDS[0] is the destination.
1129: OPERANDS[1] is the source.
1130: OPERANDS[2] is the size.
1131: OPERANDS[3] is the known safe alignment.
1132: OPERANDS[4..6] are pseudos we can safely clobber as temps. */
1133:
1134: char *
1135: output_block_move (operands)
1136: rtx *operands;
1137: {
1138: /* A vector for our computed operands. Note that load_output_address
1139: makes use of (and can clobber) up to the 8th element of this vector. */
1140: rtx xoperands[10];
1141: rtx zoperands[10];
1142: static int movstrsi_label = 0;
1143: int i, j;
1144: rtx temp1 = operands[4];
1145: rtx alignrtx = operands[3];
1146: int align = INTVAL (alignrtx);
1147: int chunk_size;
1148:
1149: xoperands[0] = operands[0];
1150: xoperands[1] = operands[1];
1151: xoperands[2] = temp1;
1152:
1153: /* We can't move more than four bytes at a time
1154: because we have only one register to move them through. */
1155: if (align > 4)
1156: {
1157: align = 4;
1158: alignrtx = gen_rtx (CONST_INT, VOIDmode, 4);
1159: }
1160:
1161: /* Recognize special cases of block moves. These occur
1162: when GNU C++ is forced to treat something as BLKmode
1163: to keep it in memory, when its mode could be represented
1164: with something smaller.
1165:
1166: We cannot do this for global variables, since we don't know
1167: what pages they don't cross. Sigh. */
1168: if (GET_CODE (operands[2]) == CONST_INT
1169: && ! CONSTANT_ADDRESS_P (operands[0])
1170: && ! CONSTANT_ADDRESS_P (operands[1]))
1171: {
1172: int size = INTVAL (operands[2]);
1173: rtx op0 = xoperands[0];
1174: rtx op1 = xoperands[1];
1175:
1176: if ((align & 3) == 0 && (size & 3) == 0 && (size >> 2) <= 16)
1177: {
1178: if (memory_address_p (SImode, plus_constant (op0, size))
1179: && memory_address_p (SImode, plus_constant (op1, size)))
1180: {
1181: cc_status.flags &= ~CC_KNOW_HI_R31;
1182: for (i = (size>>2)-1; i >= 0; i--)
1183: {
1184: xoperands[0] = plus_constant (op0, i * 4);
1185: xoperands[1] = plus_constant (op1, i * 4);
1186: output_asm_insn ("ld.l %a1,%?r31\n\tst.l %?r31,%a0",
1187: xoperands);
1188: }
1189: return "";
1190: }
1191: }
1192: else if ((align & 1) == 0 && (size & 1) == 0 && (size >> 1) <= 16)
1193: {
1194: if (memory_address_p (HImode, plus_constant (op0, size))
1195: && memory_address_p (HImode, plus_constant (op1, size)))
1196: {
1197: cc_status.flags &= ~CC_KNOW_HI_R31;
1198: for (i = (size>>1)-1; i >= 0; i--)
1199: {
1200: xoperands[0] = plus_constant (op0, i * 2);
1201: xoperands[1] = plus_constant (op1, i * 2);
1202: output_asm_insn ("ld.s %a1,%?r31\n\tst.s %?r31,%a0",
1203: xoperands);
1204: }
1205: return "";
1206: }
1207: }
1208: else if (size <= 16)
1209: {
1210: if (memory_address_p (QImode, plus_constant (op0, size))
1211: && memory_address_p (QImode, plus_constant (op1, size)))
1212: {
1213: cc_status.flags &= ~CC_KNOW_HI_R31;
1214: for (i = size-1; i >= 0; i--)
1215: {
1216: xoperands[0] = plus_constant (op0, i);
1217: xoperands[1] = plus_constant (op1, i);
1218: output_asm_insn ("ld.b %a1,%?r31\n\tst.b %?r31,%a0",
1219: xoperands);
1220: }
1221: return "";
1222: }
1223: }
1224: }
1225:
1226: /* Since we clobber untold things, nix the condition codes. */
1227: CC_STATUS_INIT;
1228:
1229: /* This is the size of the transfer.
1230: Either use the register which already contains the size,
1231: or use a free register (used by no operands). */
1232: output_size_for_block_move (operands[2], operands[4], alignrtx);
1233:
1234: #if 0
1235: /* Also emit code to decrement the size value by ALIGN. */
1236: zoperands[0] = operands[0];
1237: zoperands[3] = plus_constant (operands[0], align);
1238: output_load_address (zoperands);
1239: #endif
1240:
1241: /* Generate number for unique label. */
1242:
1243: xoperands[3] = gen_rtx (CONST_INT, VOIDmode, movstrsi_label++);
1244:
1245: /* Calculate the size of the chunks we will be trying to move first. */
1246:
1247: #if 0
1248: if ((align & 3) == 0)
1249: chunk_size = 4;
1250: else if ((align & 1) == 0)
1251: chunk_size = 2;
1252: else
1253: #endif
1254: chunk_size = 1;
1255:
1256: /* Copy the increment (negative) to a register for bla insn. */
1257:
1258: xoperands[4] = gen_rtx (CONST_INT, VOIDmode, - chunk_size);
1259: xoperands[5] = operands[5];
1260: output_asm_insn ("adds %4,%?r0,%5", xoperands);
1261:
1262: /* Predecrement the loop counter. This happens again also in the `bla'
1263: instruction which precedes the loop, but we need to have it done
1264: two times before we enter the loop because of the bizarre semantics
1265: of the bla instruction. */
1266:
1267: output_asm_insn ("adds %5,%2,%2", xoperands);
1268:
1269: /* Check for the case where the original count was less than or equal to
1270: zero. Avoid going through the loop at all if the original count was
1271: indeed less than or equal to zero. Note that we treat the count as
1272: if it were a signed 32-bit quantity here, rather than an unsigned one,
1273: even though we really shouldn't. We have to do this because of the
1274: semantics of the `ble' instruction, which assume that the count is
1275: a signed 32-bit value. Anyway, in practice it won't matter because
1276: nobody is going to try to do a memcpy() of more than half of the
1277: entire address space (i.e. 2 gigabytes) anyway. */
1278:
1279: output_asm_insn ("bc .Le%3", xoperands);
1280:
1281: /* Make available a register which is a temporary. */
1282:
1283: xoperands[6] = operands[6];
1284:
1285: /* Now the actual loop.
1286: In xoperands, elements 1 and 0 are the input and output vectors.
1287: Element 2 is the loop index. Element 5 is the increment. */
1288:
1289: output_asm_insn ("subs %1,%5,%1", xoperands);
1290: output_asm_insn ("bla %5,%2,.Lm%3", xoperands);
1291: output_asm_insn ("adds %0,%2,%6", xoperands);
1292: output_asm_insn ("\n.Lm%3:", xoperands); /* Label for bla above. */
1293: output_asm_insn ("\n.Ls%3:", xoperands); /* Loop start label. */
1294: output_asm_insn ("adds %5,%6,%6", xoperands);
1295:
1296: /* NOTE: The code here which is supposed to handle the cases where the
1297: sources and destinations are known to start on a 4 or 2 byte boundary
1298: are currently broken. They fail to do anything about the overflow
1299: bytes which might still need to be copied even after we have copied
1300: some number of words or halfwords. Thus, for now we use the lowest
1301: common denominator, i.e. the code which just copies some number of
1302: totally unaligned individual bytes. (See the calculation of
1303: chunk_size above. */
1304:
1305: if (chunk_size == 4)
1306: {
1307: output_asm_insn ("ld.l %2(%1),%?r31", xoperands);
1308: output_asm_insn ("bla %5,%2,.Ls%3", xoperands);
1309: output_asm_insn ("st.l %?r31,8(%6)", xoperands);
1310: }
1311: else if (chunk_size == 2)
1312: {
1313: output_asm_insn ("ld.s %2(%1),%?r31", xoperands);
1314: output_asm_insn ("bla %5,%2,.Ls%3", xoperands);
1315: output_asm_insn ("st.s %?r31,4(%6)", xoperands);
1316: }
1317: else /* chunk_size == 1 */
1318: {
1319: output_asm_insn ("ld.b %2(%1),%?r31", xoperands);
1320: output_asm_insn ("bla %5,%2,.Ls%3", xoperands);
1321: output_asm_insn ("st.b %?r31,2(%6)", xoperands);
1322: }
1323: output_asm_insn ("\n.Le%3:", xoperands); /* Here if count <= 0. */
1324:
1325: return "";
1326: }
1327:
1328: /* Output a delayed branch insn with the delay insn in its
1329: branch slot. The delayed branch insn template is in TEMPLATE,
1330: with operands OPERANDS. The insn in its delay slot is INSN.
1331:
1332: As a special case, since we know that all memory transfers are via
1333: ld/st insns, if we see a (MEM (SYMBOL_REF ...)) we divide the memory
1334: reference around the branch as
1335:
1336: orh ha%x,%?r0,%?r31
1337: b ...
1338: ld/st l%x(%?r31),...
1339:
1340: As another special case, we handle loading (SYMBOL_REF ...) and
1341: other large constants around branches as well:
1342:
1343: orh h%x,%?r0,%0
1344: b ...
1345: or l%x,%0,%1
1346:
1347: */
1348:
1349: char *
1350: output_delayed_branch (template, operands, insn)
1351: char *template;
1352: rtx *operands;
1353: rtx insn;
1354: {
1355: rtx src = XVECEXP (PATTERN (insn), 0, 1);
1356: rtx dest = XVECEXP (PATTERN (insn), 0, 0);
1357:
1358: /* See if we are doing some branch together with setting some register
1359: to some 32-bit value which does (or may) have some of the high-order
1360: 16 bits set. If so, we need to set the register in two stages. One
1361: stage must be done before the branch, and the other one can be done
1362: in the delay slot. */
1363:
1364: if ( (GET_CODE (src) == CONST_INT
1365: && ((unsigned) INTVAL (src) & (unsigned) 0xffff0000) != (unsigned) 0)
1366: || (GET_CODE (src) == SYMBOL_REF)
1367: || (GET_CODE (src) == LABEL_REF)
1368: || (GET_CODE (src) == CONST))
1369: {
1370: rtx xoperands[2];
1371: xoperands[0] = dest;
1372: xoperands[1] = src;
1373:
1374: CC_STATUS_PARTIAL_INIT;
1375: /* Output the `orh' insn. */
1376: output_asm_insn ("orh %H1,%?r0,%0", xoperands);
1377:
1378: /* Output the branch instruction next. */
1379: output_asm_insn (template, operands);
1380:
1381: /* Now output the `or' insn. */
1382: output_asm_insn ("or %L1,%0,%0", xoperands);
1383: }
1384: else if ((GET_CODE (src) == MEM
1385: && CONSTANT_ADDRESS_P (XEXP (src, 0)))
1386: || (GET_CODE (dest) == MEM
1387: && CONSTANT_ADDRESS_P (XEXP (dest, 0))))
1388: {
1389: rtx xoperands[2];
1390: char *split_template;
1391: xoperands[0] = dest;
1392: xoperands[1] = src;
1393:
1394: /* Output the `orh' insn. */
1395: if (GET_CODE (src) == MEM)
1396: {
1397: if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
1398: && (cc_prev_status.flags & CC_HI_R31_ADJ)
1399: && cc_prev_status.mdep == XEXP (operands[1], 0)))
1400: {
1401: CC_STATUS_INIT;
1402: output_asm_insn ("orh %h1,%?r0,%?r31", xoperands);
1403: }
1404: split_template = load_opcode (GET_MODE (dest),
1405: "%L1(%?r31),%0", dest);
1406: }
1407: else
1408: {
1409: if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
1410: && (cc_prev_status.flags & CC_HI_R31_ADJ)
1411: && cc_prev_status.mdep == XEXP (operands[0], 0)))
1412: {
1413: CC_STATUS_INIT;
1414: output_asm_insn ("orh %h0,%?r0,%?r31", xoperands);
1415: }
1416: split_template = store_opcode (GET_MODE (dest),
1417: "%r1,%L0(%?r31)", src);
1418: }
1419:
1420: /* Output the branch instruction next. */
1421: output_asm_insn (template, operands);
1422:
1423: /* Now output the load or store.
1424: No need to do a CC_STATUS_INIT, because we are branching anyway. */
1425: output_asm_insn (split_template, xoperands);
1426: }
1427: else
1428: {
1429: int insn_code_number;
1430: rtx pat = gen_rtx (SET, VOIDmode, dest, src);
1431: rtx delay_insn = gen_rtx (INSN, VOIDmode, 0, 0, 0, pat, -1, 0, 0);
1432: int i;
1433:
1434: /* Output the branch instruction first. */
1435: output_asm_insn (template, operands);
1436:
1437: /* Now recognize the insn which we put in its delay slot.
1438: We must do this after outputting the branch insn,
1439: since operands may just be a pointer to `recog_operand'. */
1440: INSN_CODE (delay_insn) = insn_code_number = recog (pat, delay_insn);
1441: if (insn_code_number == -1)
1442: abort ();
1443:
1444: for (i = 0; i < insn_n_operands[insn_code_number]; i++)
1445: {
1446: if (GET_CODE (recog_operand[i]) == SUBREG)
1447: recog_operand[i] = alter_subreg (recog_operand[i]);
1448: }
1449:
1450: insn_extract (delay_insn);
1451: if (! constrain_operands (insn_code_number, 1))
1452: fatal_insn_not_found (delay_insn);
1453:
1454: template = insn_template[insn_code_number];
1455: if (template == 0)
1456: template = (*insn_outfun[insn_code_number]) (recog_operand, delay_insn);
1457: output_asm_insn (template, recog_operand);
1458: }
1459: CC_STATUS_INIT;
1460: return "";
1461: }
1462:
1463: /* Output a newly constructed insn DELAY_INSN. */
1464: char *
1465: output_delay_insn (delay_insn)
1466: rtx delay_insn;
1467: {
1468: char *template;
1469: int insn_code_number;
1470: int i;
1471:
1472: /* Now recognize the insn which we put in its delay slot.
1473: We must do this after outputting the branch insn,
1474: since operands may just be a pointer to `recog_operand'. */
1475: insn_code_number = recog_memoized (delay_insn);
1476: if (insn_code_number == -1)
1477: abort ();
1478:
1479: /* Extract the operands of this delay insn. */
1480: INSN_CODE (delay_insn) = insn_code_number;
1481: insn_extract (delay_insn);
1482:
1483: /* It is possible that this insn has not been properly scanned by final
1484: yet. If this insn's operands don't appear in the peephole's
1485: actual operands, then they won't be fixed up by final, so we
1486: make sure they get fixed up here. -- This is a kludge. */
1487: for (i = 0; i < insn_n_operands[insn_code_number]; i++)
1488: {
1489: if (GET_CODE (recog_operand[i]) == SUBREG)
1490: recog_operand[i] = alter_subreg (recog_operand[i]);
1491: }
1492:
1493: #ifdef REGISTER_CONSTRAINTS
1494: if (! constrain_operands (insn_code_number))
1495: abort ();
1496: #endif
1497:
1498: cc_prev_status = cc_status;
1499:
1500: /* Update `cc_status' for this instruction.
1501: The instruction's output routine may change it further.
1502: If the output routine for a jump insn needs to depend
1503: on the cc status, it should look at cc_prev_status. */
1504:
1505: NOTICE_UPDATE_CC (PATTERN (delay_insn), delay_insn);
1506:
1507: /* Now get the template for what this insn would
1508: have been, without the branch. */
1509:
1510: template = insn_template[insn_code_number];
1511: if (template == 0)
1512: template = (*insn_outfun[insn_code_number]) (recog_operand, delay_insn);
1513: output_asm_insn (template, recog_operand);
1514: return "";
1515: }
1516:
1517: /* Special routine to convert an SFmode value represented as a
1518: CONST_DOUBLE into its equivalent unsigned long bit pattern.
1519: We convert the value from a double precision floating-point
1520: value to single precision first, and thence to a bit-wise
1521: equivalent unsigned long value. This routine is used when
1522: generating an immediate move of an SFmode value directly
1523: into a general register because the svr4 assembler doesn't
1524: grok floating literals in instruction operand contexts. */
1525:
1526: unsigned long
1527: sfmode_constant_to_ulong (x)
1528: rtx x;
1529: {
1530: REAL_VALUE_TYPE d;
1531: union { float f; unsigned long i; } u2;
1532:
1533: if (GET_CODE (x) != CONST_DOUBLE || GET_MODE (x) != SFmode)
1534: abort ();
1535:
1536: #if TARGET_FLOAT_FORMAT != HOST_FLOAT_FORMAT
1537: error IEEE emulation needed
1538: #endif
1539: REAL_VALUE_FROM_CONST_DOUBLE (d, x);
1540: u2.f = d;
1541: return u2.i;
1542: }
1543:
1544: /* This function generates the assembly code for function entry.
1545: The macro FUNCTION_PROLOGUE in i860.h is defined to call this function.
1546:
1547: ASM_FILE is a stdio stream to output the code to.
1548: SIZE is an int: how many units of temporary storage to allocate.
1549:
1550: Refer to the array `regs_ever_live' to determine which registers
1551: to save; `regs_ever_live[I]' is nonzero if register number I
1552: is ever used in the function. This macro is responsible for
1553: knowing which registers should not be saved even if used.
1554:
1555: NOTE: `frame_lower_bytes' is the count of bytes which will lie
1556: between the new `fp' value and the new `sp' value after the
1557: prologue is done. `frame_upper_bytes' is the count of bytes
1558: that will lie between the new `fp' and the *old* `sp' value
1559: after the new `fp' is setup (in the prologue). The upper
1560: part of each frame always includes at least 2 words (8 bytes)
1561: to hold the saved frame pointer and the saved return address.
1562:
1563: The svr4 ABI for the i860 now requires that the values of the
1564: stack pointer and frame pointer registers be kept aligned to
1565: 16-byte boundaries at all times. We obey that restriction here.
1566:
1567: The svr4 ABI for the i860 is entirely vague when it comes to specifying
1568: exactly where the "preserved" registers should be saved. The native
1569: svr4 C compiler I now have doesn't help to clarify the requirements
1570: very much because it is plainly out-of-date and non-ABI-compliant
1571: (in at least one important way, i.e. how it generates function
1572: epilogues).
1573:
1574: The native svr4 C compiler saves the "preserved" registers (i.e.
1575: r4-r15 and f2-f7) in the lower part of a frame (i.e. at negative
1576: offsets from the frame pointer).
1577:
1578: Previous versions of GCC also saved the "preserved" registers in the
1579: "negative" part of the frame, but they saved them using positive
1580: offsets from the (adjusted) stack pointer (after it had been adjusted
1581: to allocate space for the new frame). That's just plain wrong
1582: because if the current function calls alloca(), the stack pointer
1583: will get moved, and it will be impossible to restore the registers
1584: properly again after that.
1585:
1586: Both compilers handled parameter registers (i.e. r16-r27 and f8-f15)
1587: by copying their values either into various "preserved" registers or
1588: into stack slots in the lower part of the current frame (as seemed
1589: appropriate, depending upon subsequent usage of these values).
1590:
1591: Here we want to save the preserved registers at some offset from the
1592: frame pointer register so as to avoid any possible problems arising
1593: from calls to alloca(). We can either save them at small positive
1594: offsets from the frame pointer, or at small negative offsets from
1595: the frame pointer. If we save them at small negative offsets from
1596: the frame pointer (i.e. in the lower part of the frame) then we
1597: must tell the rest of GCC (via STARTING_FRAME_OFFSET) exactly how
1598: many bytes of space we plan to use in the lower part of the frame
1599: for this purpose. Since other parts of the compiler reference the
1600: value of STARTING_FRAME_OFFSET long before final() calls this function,
1601: we would have to go ahead and assume the worst-case storage requirements
1602: for saving all of the "preserved" registers (and use that number, i.e.
1603: `80', to define STARTING_FRAME_OFFSET) if we wanted to save them in
1604: the lower part of the frame. That could potentially be very wasteful,
1605: and that wastefulness could really hamper people compiling for embedded
1606: i860 targets with very tight limits on stack space. Thus, we choose
1607: here to save the preserved registers in the upper part of the
1608: frame, so that we can decide at the very last minute how much (or how
1609: little) space we must allocate for this purpose.
1610:
1611: To satisfy the needs of the svr4 ABI "tdesc" scheme, preserved
1612: registers must always be saved so that the saved values of registers
1613: with higher numbers are at higher addresses. We obey that restriction
1614: here.
1615:
1616: There are two somewhat different ways that you can generate prologues
1617: here... i.e. pedantically ABI-compliant, and the "other" way. The
1618: "other" way is more consistent with what is currently generated by the
1619: "native" svr4 C compiler for the i860. That's important if you want
1620: to use the current (as of 8/91) incarnation of svr4 SDB for the i860.
1621: The SVR4 SDB for the i860 insists on having function prologues be
1622: non-ABI-compliant!
1623:
1624: To get fully ABI-compliant prologues, define I860_STRICT_ABI_PROLOGUES
1625: in the i860svr4.h file. (By default this is *not* defined).
1626:
1627: The differences between the ABI-compliant and non-ABI-compliant prologues
1628: are that (a) the ABI version seems to require the use of *signed*
1629: (rather than unsigned) adds and subtracts, and (b) the ordering of
1630: the various steps (e.g. saving preserved registers, saving the
1631: return address, setting up the new frame pointer value) is different.
1632:
1633: For strict ABI compliance, it seems to be the case that the very last
1634: thing that is supposed to happen in the prologue is getting the frame
1635: pointer set to its new value (but only after everything else has
1636: already been properly setup). We do that here, but only if the symbol
1637: I860_STRICT_ABI_PROLOGUES is defined.
1638: */
1639:
1640: #ifndef STACK_ALIGNMENT
1641: #define STACK_ALIGNMENT 16
1642: #endif
1643:
1644: extern char call_used_regs[];
1645: extern int leaf_function_p ();
1646:
1647: char *current_function_original_name;
1648:
1649: static int must_preserve_r1;
1650: static unsigned must_preserve_bytes;
1651:
1652: void
1653: function_prologue (asm_file, local_bytes)
1654: register FILE *asm_file;
1655: register unsigned local_bytes;
1656: {
1657: register unsigned frame_lower_bytes;
1658: register unsigned frame_upper_bytes;
1659: register unsigned total_fsize;
1660: register unsigned preserved_reg_bytes = 0;
1661: register unsigned i;
1662: register unsigned preserved_so_far = 0;
1663:
1664: must_preserve_r1 = (optimize < 2 || ! leaf_function_p ());
1665: must_preserve_bytes = 4 + (must_preserve_r1 ? 4 : 0);
1666:
1667: /* Count registers that need preserving. Ignore r0. It never needs
1668: preserving. */
1669:
1670: for (i = 1; i < FIRST_PSEUDO_REGISTER; i++)
1671: {
1672: if (regs_ever_live[i] && ! call_used_regs[i])
1673: preserved_reg_bytes += 4;
1674: }
1675:
1676: /* Round-up the frame_lower_bytes so that it's a multiple of 16. */
1677:
1678: frame_lower_bytes = (local_bytes + STACK_ALIGNMENT - 1) & -STACK_ALIGNMENT;
1679:
1680: /* The upper part of each frame will contain the saved fp,
1681: the saved r1, and stack slots for all of the other "preserved"
1682: registers that we find we will need to save & restore. */
1683:
1684: frame_upper_bytes = must_preserve_bytes + preserved_reg_bytes;
1685:
1686: /* Round-up the frame_upper_bytes so that it's a multiple of 16. */
1687:
1688: frame_upper_bytes
1689: = (frame_upper_bytes + STACK_ALIGNMENT - 1) & -STACK_ALIGNMENT;
1690:
1691: total_fsize = frame_upper_bytes + frame_lower_bytes;
1692:
1693: #ifndef I860_STRICT_ABI_PROLOGUES
1694:
1695: /* There are two kinds of function prologues.
1696: You use the "small" version if the total frame size is
1697: small enough so that it can fit into an immediate 16-bit
1698: value in one instruction. Otherwise, you use the "large"
1699: version of the function prologue. */
1700:
1701: if (total_fsize > 0x7fff)
1702: {
1703: /* Adjust the stack pointer. The ABI sez to do this using `adds',
1704: but the native C compiler on svr4 uses `addu'. */
1705:
1706: fprintf (asm_file, "\taddu -%d,%ssp,%ssp\n",
1707: frame_upper_bytes, i860_reg_prefix, i860_reg_prefix);
1708:
1709: /* Save the old frame pointer. */
1710:
1711: fprintf (asm_file, "\tst.l %sfp,0(%ssp)\n",
1712: i860_reg_prefix, i860_reg_prefix);
1713:
1714: /* Setup the new frame pointer. The ABI sez to do this after
1715: preserving registers (using adds), but that's not what the
1716: native C compiler on svr4 does. */
1717:
1718: fprintf (asm_file, "\taddu 0,%ssp,%sfp\n",
1719: i860_reg_prefix, i860_reg_prefix);
1720:
1721: /* Get the value of frame_lower_bytes into r31. */
1722:
1723: fprintf (asm_file, "\torh %d,%sr0,%sr31\n",
1724: frame_lower_bytes >> 16, i860_reg_prefix, i860_reg_prefix);
1725: fprintf (asm_file, "\tor %d,%sr31,%sr31\n",
1726: frame_lower_bytes & 0xffff, i860_reg_prefix, i860_reg_prefix);
1727:
1728: /* Now re-adjust the stack pointer using the value in r31.
1729: The ABI sez to do this with `subs' but SDB may prefer `subu'. */
1730:
1731: fprintf (asm_file, "\tsubu %ssp,%sr31,%ssp\n",
1732: i860_reg_prefix, i860_reg_prefix, i860_reg_prefix);
1733:
1734: /* Preserve registers. The ABI sez to do this before setting
1735: up the new frame pointer, but that's not what the native
1736: C compiler on svr4 does. */
1737:
1738: for (i = 1; i < 32; i++)
1739: if (regs_ever_live[i] && ! call_used_regs[i])
1740: fprintf (asm_file, "\tst.l %s%s,%d(%sfp)\n",
1741: i860_reg_prefix, reg_names[i],
1742: must_preserve_bytes + (4 * preserved_so_far++),
1743: i860_reg_prefix);
1744:
1745: for (i = 32; i < 64; i++)
1746: if (regs_ever_live[i] && ! call_used_regs[i])
1747: fprintf (asm_file, "\tfst.l %s%s,%d(%sfp)\n",
1748: i860_reg_prefix, reg_names[i],
1749: must_preserve_bytes + (4 * preserved_so_far++),
1750: i860_reg_prefix);
1751:
1752: /* Save the return address. */
1753:
1754: if (must_preserve_r1)
1755: fprintf (asm_file, "\tst.l %sr1,4(%sfp)\n",
1756: i860_reg_prefix, i860_reg_prefix);
1757: }
1758: else
1759: {
1760: /* Adjust the stack pointer. The ABI sez to do this using `adds',
1761: but the native C compiler on svr4 uses `addu'. */
1762:
1763: fprintf (asm_file, "\taddu -%d,%ssp,%ssp\n",
1764: total_fsize, i860_reg_prefix, i860_reg_prefix);
1765:
1766: /* Save the old frame pointer. */
1767:
1768: fprintf (asm_file, "\tst.l %sfp,%d(%ssp)\n",
1769: i860_reg_prefix, frame_lower_bytes, i860_reg_prefix);
1770:
1771: /* Setup the new frame pointer. The ABI sez to do this after
1772: preserving registers and after saving the return address,
1773: (and its saz to do this using adds), but that's not what the
1774: native C compiler on svr4 does. */
1775:
1776: fprintf (asm_file, "\taddu %d,%ssp,%sfp\n",
1777: frame_lower_bytes, i860_reg_prefix, i860_reg_prefix);
1778:
1779: /* Preserve registers. The ABI sez to do this before setting
1780: up the new frame pointer, but that's not what the native
1781: compiler on svr4 does. */
1782:
1783: for (i = 1; i < 32; i++)
1784: if (regs_ever_live[i] && ! call_used_regs[i])
1785: fprintf (asm_file, "\tst.l %s%s,%d(%sfp)\n",
1786: i860_reg_prefix, reg_names[i],
1787: must_preserve_bytes + (4 * preserved_so_far++),
1788: i860_reg_prefix);
1789:
1790: for (i = 32; i < 64; i++)
1791: if (regs_ever_live[i] && ! call_used_regs[i])
1792: fprintf (asm_file, "\tfst.l %s%s,%d(%sfp)\n",
1793: i860_reg_prefix, reg_names[i],
1794: must_preserve_bytes + (4 * preserved_so_far++),
1795: i860_reg_prefix);
1796:
1797: /* Save the return address. The ABI sez to do this earlier,
1798: and also via an offset from %sp, but the native C compiler
1799: on svr4 does it later (i.e. now) and uses an offset from
1800: %fp. */
1801:
1802: if (must_preserve_r1)
1803: fprintf (asm_file, "\tst.l %sr1,4(%sfp)\n",
1804: i860_reg_prefix, i860_reg_prefix);
1805: }
1806:
1807: #else /* defined(I860_STRICT_ABI_PROLOGUES) */
1808:
1809: /* There are two kinds of function prologues.
1810: You use the "small" version if the total frame size is
1811: small enough so that it can fit into an immediate 16-bit
1812: value in one instruction. Otherwise, you use the "large"
1813: version of the function prologue. */
1814:
1815: if (total_fsize > 0x7fff)
1816: {
1817: /* Adjust the stack pointer (thereby allocating a new frame). */
1818:
1819: fprintf (asm_file, "\tadds -%d,%ssp,%ssp\n",
1820: frame_upper_bytes, i860_reg_prefix, i860_reg_prefix);
1821:
1822: /* Save the caller's frame pointer. */
1823:
1824: fprintf (asm_file, "\tst.l %sfp,0(%ssp)\n",
1825: i860_reg_prefix, i860_reg_prefix);
1826:
1827: /* Save return address. */
1828:
1829: if (must_preserve_r1)
1830: fprintf (asm_file, "\tst.l %sr1,4(%ssp)\n",
1831: i860_reg_prefix, i860_reg_prefix);
1832:
1833: /* Get the value of frame_lower_bytes into r31 for later use. */
1834:
1835: fprintf (asm_file, "\torh %d,%sr0,%sr31\n",
1836: frame_lower_bytes >> 16, i860_reg_prefix, i860_reg_prefix);
1837: fprintf (asm_file, "\tor %d,%sr31,%sr31\n",
1838: frame_lower_bytes & 0xffff, i860_reg_prefix, i860_reg_prefix);
1839:
1840: /* Now re-adjust the stack pointer using the value in r31. */
1841:
1842: fprintf (asm_file, "\tsubs %ssp,%sr31,%ssp\n",
1843: i860_reg_prefix, i860_reg_prefix, i860_reg_prefix);
1844:
1845: /* Pre-compute value to be used as the new frame pointer. */
1846:
1847: fprintf (asm_file, "\tadds %ssp,%sr31,%sr31\n",
1848: i860_reg_prefix, i860_reg_prefix, i860_reg_prefix);
1849:
1850: /* Preserve registers. */
1851:
1852: for (i = 1; i < 32; i++)
1853: if (regs_ever_live[i] && ! call_used_regs[i])
1854: fprintf (asm_file, "\tst.l %s%s,%d(%sr31)\n",
1855: i860_reg_prefix, reg_names[i],
1856: must_preserve_bytes + (4 * preserved_so_far++),
1857: i860_reg_prefix);
1858:
1859: for (i = 32; i < 64; i++)
1860: if (regs_ever_live[i] && ! call_used_regs[i])
1861: fprintf (asm_file, "\tfst.l %s%s,%d(%sr31)\n",
1862: i860_reg_prefix, reg_names[i],
1863: must_preserve_bytes + (4 * preserved_so_far++),
1864: i860_reg_prefix);
1865:
1866: /* Actually set the new value of the frame pointer. */
1867:
1868: fprintf (asm_file, "\tmov %sr31,%sfp\n",
1869: i860_reg_prefix, i860_reg_prefix);
1870: }
1871: else
1872: {
1873: /* Adjust the stack pointer. */
1874:
1875: fprintf (asm_file, "\tadds -%d,%ssp,%ssp\n",
1876: total_fsize, i860_reg_prefix, i860_reg_prefix);
1877:
1878: /* Save the caller's frame pointer. */
1879:
1880: fprintf (asm_file, "\tst.l %sfp,%d(%ssp)\n",
1881: i860_reg_prefix, frame_lower_bytes, i860_reg_prefix);
1882:
1883: /* Save the return address. */
1884:
1885: if (must_preserve_r1)
1886: fprintf (asm_file, "\tst.l %sr1,%d(%ssp)\n",
1887: i860_reg_prefix, frame_lower_bytes + 4, i860_reg_prefix);
1888:
1889: /* Preserve registers. */
1890:
1891: for (i = 1; i < 32; i++)
1892: if (regs_ever_live[i] && ! call_used_regs[i])
1893: fprintf (asm_file, "\tst.l %s%s,%d(%ssp)\n",
1894: i860_reg_prefix, reg_names[i],
1895: frame_lower_bytes + must_preserve_bytes + (4 * preserved_so_far++),
1896: i860_reg_prefix);
1897:
1898: for (i = 32; i < 64; i++)
1899: if (regs_ever_live[i] && ! call_used_regs[i])
1900: fprintf (asm_file, "\tfst.l %s%s,%d(%ssp)\n",
1901: i860_reg_prefix, reg_names[i],
1902: frame_lower_bytes + must_preserve_bytes + (4 * preserved_so_far++),
1903: i860_reg_prefix);
1904:
1905: /* Setup the new frame pointer. */
1906:
1907: fprintf (asm_file, "\tadds %d,%ssp,%sfp\n",
1908: frame_lower_bytes, i860_reg_prefix, i860_reg_prefix);
1909: }
1910: #endif /* defined(I860_STRICT_ABI_PROLOGUES) */
1911:
1912: #ifdef ASM_OUTPUT_PROLOGUE_SUFFIX
1913: ASM_OUTPUT_PROLOGUE_SUFFIX (asm_file);
1914: #endif /* defined(ASM_OUTPUT_PROLOGUE_SUFFIX) */
1915: }
1916:
1917: /* This function generates the assembly code for function exit.
1918: The macro FUNCTION_EPILOGUE in i860.h is defined to call this function.
1919:
1920: ASM_FILE is a stdio stream to output the code to.
1921: SIZE is an int: how many units of temporary storage to allocate.
1922:
1923: The function epilogue should not depend on the current stack pointer!
1924: It should use the frame pointer only. This is mandatory because
1925: of alloca; we also take advantage of it to omit stack adjustments
1926: before returning.
1927:
1928: Note that when we go to restore the preserved register values we must
1929: not try to address their slots by using offsets from the stack pointer.
1930: That's because the stack pointer may have been moved during the function
1931: execution due to a call to alloca(). Rather, we must restore all
1932: preserved registers via offsets from the frame pointer value.
1933:
1934: Note also that when the current frame is being "popped" (by adjusting
1935: the value of the stack pointer) on function exit, we must (for the
1936: sake of alloca) set the new value of the stack pointer based upon
1937: the current value of the frame pointer. We can't just add what we
1938: believe to be the (static) frame size to the stack pointer because
1939: if we did that, and alloca() had been called during this function,
1940: we would end up returning *without* having fully deallocated all of
1941: the space grabbed by alloca. If that happened, and a function
1942: containing one or more alloca() calls was called over and over again,
1943: then the stack would grow without limit!
1944:
1945: Finally note that the epilogues generated here are completely ABI
1946: compliant. They go out of their way to insure that the value in
1947: the frame pointer register is never less than the value in the stack
1948: pointer register. It's not clear why this relationship needs to be
1949: maintained at all times, but maintaining it only costs one extra
1950: instruction, so what the hell.
1951: */
1952:
1953: /* This corresponds to a version 4 TDESC structure. Lower numbered
1954: versions successively omit the last word of the structure. We
1955: don't try to handle version 5 here. */
1956:
1957: typedef struct TDESC_flags {
1958: int version:4;
1959: int reg_packing:1;
1960: int callable_block:1;
1961: int reserved:4;
1962: int fregs:6; /* fp regs 2-7 */
1963: int iregs:16; /* regs 0-15 */
1964: } TDESC_flags;
1965:
1966: typedef struct TDESC {
1967: TDESC_flags flags;
1968: int integer_reg_offset; /* same as must_preserve_bytes */
1969: int floating_point_reg_offset;
1970: unsigned int positive_frame_size; /* same as frame_upper_bytes */
1971: unsigned int negative_frame_size; /* same as frame_lower_bytes */
1972: } TDESC;
1973:
1974: void
1975: function_epilogue (asm_file, local_bytes)
1976: register FILE *asm_file;
1977: register unsigned local_bytes;
1978: {
1979: register unsigned frame_upper_bytes;
1980: register unsigned frame_lower_bytes;
1981: register unsigned preserved_reg_bytes = 0;
1982: register unsigned i;
1983: register unsigned restored_so_far = 0;
1984: register unsigned int_restored;
1985: register unsigned mask;
1986: unsigned intflags=0;
1987: register TDESC_flags *flags = (TDESC_flags *) &intflags;
1988:
1989: flags->version = 4;
1990: flags->reg_packing = 1;
1991: flags->iregs = 8; /* old fp always gets saved */
1992:
1993: /* Round-up the frame_lower_bytes so that it's a multiple of 16. */
1994:
1995: frame_lower_bytes = (local_bytes + STACK_ALIGNMENT - 1) & -STACK_ALIGNMENT;
1996:
1997: /* Count the number of registers that were preserved in the prologue.
1998: Ignore r0. It is never preserved. */
1999:
2000: for (i = 1; i < FIRST_PSEUDO_REGISTER; i++)
2001: {
2002: if (regs_ever_live[i] && ! call_used_regs[i])
2003: preserved_reg_bytes += 4;
2004: }
2005:
2006: /* The upper part of each frame will contain only saved fp,
2007: the saved r1, and stack slots for all of the other "preserved"
2008: registers that we find we will need to save & restore. */
2009:
2010: frame_upper_bytes = must_preserve_bytes + preserved_reg_bytes;
2011:
2012: /* Round-up frame_upper_bytes so that t is a multiple of 16. */
2013:
2014: frame_upper_bytes
2015: = (frame_upper_bytes + STACK_ALIGNMENT - 1) & -STACK_ALIGNMENT;
2016:
2017: /* Restore all of the "preserved" registers that need restoring. */
2018:
2019: mask = 2;
2020:
2021: for (i = 1; i < 32; i++, mask<<=1)
2022: if (regs_ever_live[i] && ! call_used_regs[i]) {
2023: fprintf (asm_file, "\tld.l %d(%sfp),%s%s\n",
2024: must_preserve_bytes + (4 * restored_so_far++),
2025: i860_reg_prefix, i860_reg_prefix, reg_names[i]);
2026: if (i > 3 && i < 16)
2027: flags->iregs |= mask;
2028: }
2029:
2030: int_restored = restored_so_far;
2031: mask = 1;
2032:
2033: for (i = 32; i < 64; i++) {
2034: if (regs_ever_live[i] && ! call_used_regs[i]) {
2035: fprintf (asm_file, "\tfld.l %d(%sfp),%s%s\n",
2036: must_preserve_bytes + (4 * restored_so_far++),
2037: i860_reg_prefix, i860_reg_prefix, reg_names[i]);
2038: if (i > 33 & i < 40)
2039: flags->fregs |= mask;
2040: }
2041: if (i > 33 && i < 40)
2042: mask<<=1;
2043: }
2044:
2045: /* Get the value we plan to use to restore the stack pointer into r31. */
2046:
2047: fprintf (asm_file, "\tadds %d,%sfp,%sr31\n",
2048: frame_upper_bytes, i860_reg_prefix, i860_reg_prefix);
2049:
2050: /* Restore the return address and the old frame pointer. */
2051:
2052: if (must_preserve_r1) {
2053: fprintf (asm_file, "\tld.l 4(%sfp),%sr1\n",
2054: i860_reg_prefix, i860_reg_prefix);
2055: flags->iregs |= 2;
2056: }
2057:
2058: fprintf (asm_file, "\tld.l 0(%sfp),%sfp\n",
2059: i860_reg_prefix, i860_reg_prefix);
2060:
2061: /* Return and restore the old stack pointer value. */
2062:
2063: fprintf (asm_file, "\tbri %sr1\n\tmov %sr31,%ssp\n",
2064: i860_reg_prefix, i860_reg_prefix, i860_reg_prefix);
2065:
2066: #ifdef OUTPUT_TDESC /* Output an ABI-compliant TDESC entry */
2067: if (! frame_lower_bytes) {
2068: flags->version--;
2069: if (! frame_upper_bytes) {
2070: flags->version--;
2071: if (restored_so_far == int_restored) /* No FP saves */
2072: flags->version--;
2073: }
2074: }
2075: assemble_name(asm_file,current_function_original_name);
2076: fputs(".TDESC:\n", asm_file);
2077: fprintf(asm_file, "%s 0x%0x\n", ASM_LONG, intflags);
2078: fprintf(asm_file, "%s %d\n", ASM_LONG,
2079: int_restored ? must_preserve_bytes : 0);
2080: if (flags->version > 1) {
2081: fprintf(asm_file, "%s %d\n", ASM_LONG,
2082: (restored_so_far == int_restored) ? 0 : must_preserve_bytes +
2083: (4 * int_restored));
2084: if (flags->version > 2) {
2085: fprintf(asm_file, "%s %d\n", ASM_LONG, frame_upper_bytes);
2086: if (flags->version > 3)
2087: fprintf(asm_file, "%s %d\n", ASM_LONG, frame_lower_bytes);
2088: }
2089: }
2090: tdesc_section();
2091: fprintf(asm_file, "%s ", ASM_LONG);
2092: assemble_name(asm_file, current_function_original_name);
2093: fprintf(asm_file, "\n%s ", ASM_LONG);
2094: assemble_name(asm_file, current_function_original_name);
2095: fputs(".TDESC\n", asm_file);
2096: text_section();
2097: #endif
2098: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.