|
|
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: /* Return the best assembler insn template
473: for moving operands[1] into operands[0] as a fullword. */
474:
475: static char *
476: singlemove_string (operands)
477: rtx *operands;
478: {
479: if (GET_CODE (operands[0]) == MEM)
480: {
481: if (GET_CODE (operands[1]) != MEM)
482: if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
483: {
484: if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
485: && (cc_prev_status.flags & CC_HI_R31_ADJ)
486: && cc_prev_status.mdep == XEXP (operands[0], 0)))
487: {
488: CC_STATUS_INIT;
489: output_asm_insn ("orh %h0,%?r0,%?r31", operands);
490: }
491: cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
492: cc_status.mdep = XEXP (operands[0], 0);
493: return "st.l %r1,%L0(%?r31)";
494: }
495: else
496: return "st.l %r1,%0";
497: else
498: abort ();
499: #if 0
500: {
501: rtx xoperands[2];
502:
503: cc_status.flags &= ~CC_F0_IS_0;
504: xoperands[0] = gen_rtx (REG, SFmode, 32);
505: xoperands[1] = operands[1];
506: output_asm_insn (singlemove_string (xoperands), xoperands);
507: xoperands[1] = xoperands[0];
508: xoperands[0] = operands[0];
509: output_asm_insn (singlemove_string (xoperands), xoperands);
510: return "";
511: }
512: #endif
513: }
514: if (GET_CODE (operands[1]) == MEM)
515: {
516: if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
517: {
518: if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
519: && (cc_prev_status.flags & CC_HI_R31_ADJ)
520: && cc_prev_status.mdep == XEXP (operands[1], 0)))
521: {
522: CC_STATUS_INIT;
523: output_asm_insn ("orh %h1,%?r0,%?r31", operands);
524: }
525: cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
526: cc_status.mdep = XEXP (operands[1], 0);
527: return "ld.l %L1(%?r31),%0";
528: }
529: return "ld.l %m1,%0";
530: }
531: if (GET_CODE (operands[1]) == CONST_INT)
532: {
1.1.1.3 root 533: if (operands[1] == const0_rtx)
534: return "mov %?r0,%0";
1.1 root 535: if((INTVAL (operands[1]) & 0xffff0000) == 0)
536: return "or %L1,%?r0,%0";
1.1.1.3 root 537: if((INTVAL (operands[1]) & 0xffff8000) == 0xffff8000)
538: return "adds %1,%?r0,%0";
1.1 root 539: if((INTVAL (operands[1]) & 0x0000ffff) == 0)
540: return "orh %H1,%?r0,%0";
541: }
542: return "mov %1,%0";
543: }
544:
545: /* Output assembler code to perform a doubleword move insn
546: with operands OPERANDS. */
547:
548: char *
549: output_move_double (operands)
550: rtx *operands;
551: {
552: enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
553: rtx latehalf[2];
554: rtx addreg0 = 0, addreg1 = 0;
555:
556: /* First classify both operands. */
557:
558: if (REG_P (operands[0]))
559: optype0 = REGOP;
560: else if (offsettable_memref_p (operands[0]))
561: optype0 = OFFSOP;
562: else if (GET_CODE (operands[0]) == MEM)
563: optype0 = MEMOP;
564: else
565: optype0 = RNDOP;
566:
567: if (REG_P (operands[1]))
568: optype1 = REGOP;
569: else if (CONSTANT_P (operands[1]))
570: optype1 = CNSTOP;
571: else if (offsettable_memref_p (operands[1]))
572: optype1 = OFFSOP;
573: else if (GET_CODE (operands[1]) == MEM)
574: optype1 = MEMOP;
575: else
576: optype1 = RNDOP;
577:
578: /* Check for the cases that the operand constraints are not
579: supposed to allow to happen. Abort if we get one,
580: because generating code for these cases is painful. */
581:
582: if (optype0 == RNDOP || optype1 == RNDOP)
583: abort ();
584:
585: /* If an operand is an unoffsettable memory ref, find a register
586: we can increment temporarily to make it refer to the second word. */
587:
588: if (optype0 == MEMOP)
589: addreg0 = find_addr_reg (XEXP (operands[0], 0));
590:
591: if (optype1 == MEMOP)
592: addreg1 = find_addr_reg (XEXP (operands[1], 0));
593:
594: /* ??? Perhaps in some cases move double words
595: if there is a spare pair of floating regs. */
596:
597: /* Ok, we can do one word at a time.
598: Normally we do the low-numbered word first,
599: but if either operand is autodecrementing then we
600: do the high-numbered word first.
601:
602: In either case, set up in LATEHALF the operands to use
603: for the high-numbered word and in some cases alter the
604: operands in OPERANDS to be suitable for the low-numbered word. */
605:
606: if (optype0 == REGOP)
607: latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
608: else if (optype0 == OFFSOP)
609: latehalf[0] = adj_offsettable_operand (operands[0], 4);
610: else
611: latehalf[0] = operands[0];
612:
613: if (optype1 == REGOP)
614: latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
615: else if (optype1 == OFFSOP)
616: latehalf[1] = adj_offsettable_operand (operands[1], 4);
617: else if (optype1 == CNSTOP)
618: {
619: if (GET_CODE (operands[1]) == CONST_DOUBLE)
620: split_double (operands[1], &operands[1], &latehalf[1]);
621: else if (CONSTANT_P (operands[1]))
622: latehalf[1] = const0_rtx;
623: }
624: else
625: latehalf[1] = operands[1];
626:
627: /* If the first move would clobber the source of the second one,
628: do them in the other order.
629:
630: RMS says "This happens only for registers;
631: such overlap can't happen in memory unless the user explicitly
632: sets it up, and that is an undefined circumstance."
633:
634: but it happens on the sparc when loading parameter registers,
635: so I am going to define that circumstance, and make it work
636: as expected. */
637:
638: if (optype0 == REGOP && optype1 == REGOP
639: && REGNO (operands[0]) == REGNO (latehalf[1]))
640: {
641: CC_STATUS_PARTIAL_INIT;
642: /* Make any unoffsettable addresses point at high-numbered word. */
643: if (addreg0)
644: output_asm_insn ("adds 0x4,%0,%0", &addreg0);
645: if (addreg1)
646: output_asm_insn ("adds 0x4,%0,%0", &addreg1);
647:
648: /* Do that word. */
649: output_asm_insn (singlemove_string (latehalf), latehalf);
650:
651: /* Undo the adds we just did. */
652: if (addreg0)
653: output_asm_insn ("adds -0x4,%0,%0", &addreg0);
654: if (addreg1)
655: output_asm_insn ("adds -0x4,%0,%0", &addreg1);
656:
657: /* Do low-numbered word. */
658: return singlemove_string (operands);
659: }
660: else if (optype0 == REGOP && optype1 != REGOP
661: && reg_overlap_mentioned_p (operands[0], operands[1]))
662: {
663: /* Do the late half first. */
664: output_asm_insn (singlemove_string (latehalf), latehalf);
665: /* Then clobber. */
666: return singlemove_string (operands);
667: }
668:
669: /* Normal case: do the two words, low-numbered first. */
670:
671: output_asm_insn (singlemove_string (operands), operands);
672:
673: CC_STATUS_PARTIAL_INIT;
674: /* Make any unoffsettable addresses point at high-numbered word. */
675: if (addreg0)
676: output_asm_insn ("adds 0x4,%0,%0", &addreg0);
677: if (addreg1)
678: output_asm_insn ("adds 0x4,%0,%0", &addreg1);
679:
680: /* Do that word. */
681: output_asm_insn (singlemove_string (latehalf), latehalf);
682:
683: /* Undo the adds we just did. */
684: if (addreg0)
685: output_asm_insn ("adds -0x4,%0,%0", &addreg0);
686: if (addreg1)
687: output_asm_insn ("adds -0x4,%0,%0", &addreg1);
688:
689: return "";
690: }
691:
692: char *
693: output_fp_move_double (operands)
694: rtx *operands;
695: {
696: /* If the source operand is any sort of zero, use f0 instead. */
697:
698: if (operands[1] == CONST0_RTX (GET_MODE (operands[1])))
699: operands[1] = gen_rtx (REG, DFmode, F0_REGNUM);
700:
701: if (FP_REG_P (operands[0]))
702: {
703: if (FP_REG_P (operands[1]))
704: return "fmov.dd %1,%0";
705: if (GET_CODE (operands[1]) == REG)
706: {
707: output_asm_insn ("ixfr %1,%0", operands);
708: operands[0] = gen_rtx (REG, VOIDmode, REGNO (operands[0]) + 1);
709: operands[1] = gen_rtx (REG, VOIDmode, REGNO (operands[1]) + 1);
710: return "ixfr %1,%0";
711: }
712: if (operands[1] == CONST0_RTX (DFmode))
713: return "fmov.dd f0,%0";
714: if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
715: {
716: if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
717: && (cc_prev_status.flags & CC_HI_R31_ADJ)
718: && cc_prev_status.mdep == XEXP (operands[1], 0)))
719: {
720: CC_STATUS_INIT;
721: output_asm_insn ("orh %h1,%?r0,%?r31", operands);
722: }
723: cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
724: cc_status.mdep = XEXP (operands[1], 0);
725: return "fld.d %L1(%?r31),%0";
726: }
727: return "fld.d %1,%0";
728: }
729: else if (FP_REG_P (operands[1]))
730: {
731: if (GET_CODE (operands[0]) == REG)
732: {
733: output_asm_insn ("fxfr %1,%0", operands);
734: operands[0] = gen_rtx (REG, VOIDmode, REGNO (operands[0]) + 1);
735: operands[1] = gen_rtx (REG, VOIDmode, REGNO (operands[1]) + 1);
736: return "fxfr %1,%0";
737: }
738: if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
739: {
740: if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
741: && (cc_prev_status.flags & CC_HI_R31_ADJ)
742: && cc_prev_status.mdep == XEXP (operands[0], 0)))
743: {
744: CC_STATUS_INIT;
745: output_asm_insn ("orh %h0,%?r0,%?r31", operands);
746: }
747: cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
748: cc_status.mdep = XEXP (operands[0], 0);
749: return "fst.d %1,%L0(%?r31)";
750: }
751: return "fst.d %1,%0";
752: }
753: else
754: abort ();
755: /* NOTREACHED */
756: return NULL;
757: }
758:
759: /* Return a REG that occurs in ADDR with coefficient 1.
760: ADDR can be effectively incremented by incrementing REG. */
761:
762: static rtx
763: find_addr_reg (addr)
764: rtx addr;
765: {
766: while (GET_CODE (addr) == PLUS)
767: {
768: if (GET_CODE (XEXP (addr, 0)) == REG)
769: addr = XEXP (addr, 0);
770: else if (GET_CODE (XEXP (addr, 1)) == REG)
771: addr = XEXP (addr, 1);
772: else if (CONSTANT_P (XEXP (addr, 0)))
773: addr = XEXP (addr, 1);
774: else if (CONSTANT_P (XEXP (addr, 1)))
775: addr = XEXP (addr, 0);
776: else
777: abort ();
778: }
779: if (GET_CODE (addr) == REG)
780: return addr;
781: abort ();
782: /* NOTREACHED */
783: return NULL;
784: }
785:
786: /* Return a template for a load instruction with mode MODE and
787: arguments from the string ARGS.
788:
789: This string is in static storage. */
790:
791: static char *
792: load_opcode (mode, args, reg)
793: enum machine_mode mode;
794: char *args;
795: rtx reg;
796: {
797: static char buf[30];
798: char *opcode;
799:
800: switch (mode)
801: {
802: case QImode:
803: opcode = "ld.b";
804: break;
805:
806: case HImode:
807: opcode = "ld.s";
808: break;
809:
810: case SImode:
811: case SFmode:
812: if (FP_REG_P (reg))
813: opcode = "fld.l";
814: else
815: opcode = "ld.l";
816: break;
817:
818: case DImode:
819: if (!FP_REG_P (reg))
820: abort ();
821: case DFmode:
822: opcode = "fld.d";
823: break;
824:
825: default:
826: abort ();
827: }
828:
829: sprintf (buf, "%s %s", opcode, args);
830: return buf;
831: }
832:
833: /* Return a template for a store instruction with mode MODE and
834: arguments from the string ARGS.
835:
836: This string is in static storage. */
837:
838: static char *
839: store_opcode (mode, args, reg)
840: enum machine_mode mode;
841: char *args;
842: rtx reg;
843: {
844: static char buf[30];
845: char *opcode;
846:
847: switch (mode)
848: {
849: case QImode:
850: opcode = "st.b";
851: break;
852:
853: case HImode:
854: opcode = "st.s";
855: break;
856:
857: case SImode:
858: case SFmode:
859: if (FP_REG_P (reg))
860: opcode = "fst.l";
861: else
862: opcode = "st.l";
863: break;
864:
865: case DImode:
866: if (!FP_REG_P (reg))
867: abort ();
868: case DFmode:
869: opcode = "fst.d";
870: break;
871:
872: default:
873: abort ();
874: }
875:
876: sprintf (buf, "%s %s", opcode, args);
877: return buf;
878: }
879:
880: /* Output a store-in-memory whose operands are OPERANDS[0,1].
881: OPERANDS[0] is a MEM, and OPERANDS[1] is a reg or zero.
882:
883: This function returns a template for an insn.
884: This is in static storage.
885:
886: It may also output some insns directly.
887: It may alter the values of operands[0] and operands[1]. */
888:
889: char *
890: output_store (operands)
891: rtx *operands;
892: {
893: enum machine_mode mode = GET_MODE (operands[0]);
894: rtx address = XEXP (operands[0], 0);
895: char *string;
896:
897: cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
898: cc_status.mdep = address;
899:
900: if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
901: && (cc_prev_status.flags & CC_HI_R31_ADJ)
902: && address == cc_prev_status.mdep))
903: {
904: CC_STATUS_INIT;
905: output_asm_insn ("orh %h0,%?r0,%?r31", operands);
906: cc_prev_status.mdep = address;
907: }
908:
909: /* Store zero in two parts when appropriate. */
910: if (mode == DFmode && operands[1] == CONST0_RTX (DFmode))
911: return store_opcode (DFmode, "%r1,%L0(%?r31)", operands[1]);
912:
913: /* Code below isn't smart enough to move a doubleword in two parts,
914: so use output_move_double to do that in the cases that require it. */
915: if ((mode == DImode || mode == DFmode)
916: && ! FP_REG_P (operands[1]))
917: return output_move_double (operands);
918:
919: return store_opcode (mode, "%r1,%L0(%?r31)", operands[1]);
920: }
921:
922: /* Output a load-from-memory whose operands are OPERANDS[0,1].
923: OPERANDS[0] is a reg, and OPERANDS[1] is a mem.
924:
925: This function returns a template for an insn.
926: This is in static storage.
927:
928: It may also output some insns directly.
929: It may alter the values of operands[0] and operands[1]. */
930:
931: char *
932: output_load (operands)
933: rtx *operands;
934: {
935: enum machine_mode mode = GET_MODE (operands[0]);
936: rtx address = XEXP (operands[1], 0);
937:
938: /* We don't bother trying to see if we know %hi(address).
939: This is because we are doing a load, and if we know the
940: %hi value, we probably also know that value in memory. */
941: cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
942: cc_status.mdep = address;
943:
944: if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
945: && (cc_prev_status.flags & CC_HI_R31_ADJ)
946: && address == cc_prev_status.mdep
947: && cc_prev_status.mdep == cc_status.mdep))
948: {
949: CC_STATUS_INIT;
950: output_asm_insn ("orh %h1,%?r0,%?r31", operands);
951: cc_prev_status.mdep = address;
952: }
953:
954: /* Code below isn't smart enough to move a doubleword in two parts,
955: so use output_move_double to do that in the cases that require it. */
956: if ((mode == DImode || mode == DFmode)
957: && ! FP_REG_P (operands[0]))
958: return output_move_double (operands);
959:
960: return load_opcode (mode, "%L1(%?r31),%0", operands[0]);
961: }
962:
963: #if 0
964: /* Load the address specified by OPERANDS[3] into the register
965: specified by OPERANDS[0].
966:
967: OPERANDS[3] may be the result of a sum, hence it could either be:
968:
969: (1) CONST
970: (2) REG
971: (2) REG + CONST_INT
972: (3) REG + REG + CONST_INT
973: (4) REG + REG (special case of 3).
974:
975: Note that (3) is not a legitimate address.
976: All cases are handled here. */
977:
978: void
979: output_load_address (operands)
980: rtx *operands;
981: {
982: rtx base, offset;
983:
984: if (CONSTANT_P (operands[3]))
985: {
986: output_asm_insn ("mov %3,%0", operands);
987: return;
988: }
989:
990: if (REG_P (operands[3]))
991: {
992: if (REGNO (operands[0]) != REGNO (operands[3]))
993: output_asm_insn ("shl %?r0,%3,%0", operands);
994: return;
995: }
996:
997: if (GET_CODE (operands[3]) != PLUS)
998: abort ();
999:
1000: base = XEXP (operands[3], 0);
1001: offset = XEXP (operands[3], 1);
1002:
1003: if (GET_CODE (base) == CONST_INT)
1004: {
1005: rtx tmp = base;
1006: base = offset;
1007: offset = tmp;
1008: }
1009:
1010: if (GET_CODE (offset) != CONST_INT)
1011: {
1012: /* Operand is (PLUS (REG) (REG)). */
1013: base = operands[3];
1014: offset = const0_rtx;
1015: }
1016:
1017: if (REG_P (base))
1018: {
1019: operands[6] = base;
1020: operands[7] = offset;
1021: CC_STATUS_PARTIAL_INIT;
1022: if (SMALL_INT (offset))
1023: output_asm_insn ("adds %7,%6,%0", operands);
1024: else
1025: output_asm_insn ("mov %7,%0\n\tadds %0,%6,%0", operands);
1026: }
1027: else if (GET_CODE (base) == PLUS)
1028: {
1029: operands[6] = XEXP (base, 0);
1030: operands[7] = XEXP (base, 1);
1031: operands[8] = offset;
1032:
1033: CC_STATUS_PARTIAL_INIT;
1034: if (SMALL_INT (offset))
1035: output_asm_insn ("adds %6,%7,%0\n\tadds %8,%0,%0", operands);
1036: else
1037: output_asm_insn ("mov %8,%0\n\tadds %0,%6,%0\n\tadds %0,%7,%0", operands);
1038: }
1039: else
1040: abort ();
1041: }
1042: #endif
1043:
1044: /* Output code to place a size count SIZE in register REG.
1045: Because block moves are pipelined, we don't include the
1046: first element in the transfer of SIZE to REG.
1047: For this, we subtract ALIGN. (Actually, I think it is not
1048: right to subtract on this machine, so right now we don't.) */
1049:
1050: static void
1051: output_size_for_block_move (size, reg, align)
1052: rtx size, reg, align;
1053: {
1054: rtx xoperands[3];
1055:
1056: xoperands[0] = reg;
1057: xoperands[1] = size;
1058: xoperands[2] = align;
1059:
1060: #if 1
1061: cc_status.flags &= ~ CC_KNOW_HI_R31;
1.1.1.3 root 1062: output_asm_insn (singlemove_string (xoperands), xoperands);
1.1 root 1063: #else
1064: if (GET_CODE (size) == REG)
1065: output_asm_insn ("sub %2,%1,%0", xoperands);
1066: else
1067: {
1068: xoperands[1]
1069: = gen_rtx (CONST_INT, VOIDmode, INTVAL (size) - INTVAL (align));
1070: cc_status.flags &= ~ CC_KNOW_HI_R31;
1071: output_asm_insn ("mov %1,%0", xoperands);
1072: }
1073: #endif
1074: }
1075:
1076: /* Emit code to perform a block move.
1077:
1078: OPERANDS[0] is the destination.
1079: OPERANDS[1] is the source.
1080: OPERANDS[2] is the size.
1081: OPERANDS[3] is the known safe alignment.
1082: OPERANDS[4..6] are pseudos we can safely clobber as temps. */
1083:
1084: char *
1085: output_block_move (operands)
1086: rtx *operands;
1087: {
1088: /* A vector for our computed operands. Note that load_output_address
1089: makes use of (and can clobber) up to the 8th element of this vector. */
1090: rtx xoperands[10];
1091: rtx zoperands[10];
1092: static int movstrsi_label = 0;
1093: int i, j;
1094: rtx temp1 = operands[4];
1095: rtx alignrtx = operands[3];
1096: int align = INTVAL (alignrtx);
1097: int chunk_size;
1098:
1099: xoperands[0] = operands[0];
1100: xoperands[1] = operands[1];
1101: xoperands[2] = temp1;
1102:
1103: /* We can't move more than four bytes at a time
1104: because we have only one register to move them through. */
1105: if (align > 4)
1106: {
1107: align = 4;
1108: alignrtx = gen_rtx (CONST_INT, VOIDmode, 4);
1109: }
1110:
1111: /* Recognize special cases of block moves. These occur
1112: when GNU C++ is forced to treat something as BLKmode
1113: to keep it in memory, when its mode could be represented
1114: with something smaller.
1115:
1116: We cannot do this for global variables, since we don't know
1117: what pages they don't cross. Sigh. */
1118: if (GET_CODE (operands[2]) == CONST_INT
1119: && ! CONSTANT_ADDRESS_P (operands[0])
1120: && ! CONSTANT_ADDRESS_P (operands[1]))
1121: {
1122: int size = INTVAL (operands[2]);
1123: rtx op0 = xoperands[0];
1124: rtx op1 = xoperands[1];
1125:
1126: if ((align & 3) == 0 && (size & 3) == 0 && (size >> 2) <= 16)
1127: {
1128: if (memory_address_p (SImode, plus_constant (op0, size))
1129: && memory_address_p (SImode, plus_constant (op1, size)))
1130: {
1131: cc_status.flags &= ~CC_KNOW_HI_R31;
1132: for (i = (size>>2)-1; i >= 0; i--)
1133: {
1134: xoperands[0] = plus_constant (op0, i * 4);
1135: xoperands[1] = plus_constant (op1, i * 4);
1136: output_asm_insn ("ld.l %a1,%?r31\n\tst.l %?r31,%a0",
1137: xoperands);
1138: }
1139: return "";
1140: }
1141: }
1142: else if ((align & 1) == 0 && (size & 1) == 0 && (size >> 1) <= 16)
1143: {
1144: if (memory_address_p (HImode, plus_constant (op0, size))
1145: && memory_address_p (HImode, plus_constant (op1, size)))
1146: {
1147: cc_status.flags &= ~CC_KNOW_HI_R31;
1148: for (i = (size>>1)-1; i >= 0; i--)
1149: {
1150: xoperands[0] = plus_constant (op0, i * 2);
1151: xoperands[1] = plus_constant (op1, i * 2);
1152: output_asm_insn ("ld.s %a1,%?r31\n\tst.s %?r31,%a0",
1153: xoperands);
1154: }
1155: return "";
1156: }
1157: }
1158: else if (size <= 16)
1159: {
1160: if (memory_address_p (QImode, plus_constant (op0, size))
1161: && memory_address_p (QImode, plus_constant (op1, size)))
1162: {
1163: cc_status.flags &= ~CC_KNOW_HI_R31;
1164: for (i = size-1; i >= 0; i--)
1165: {
1166: xoperands[0] = plus_constant (op0, i);
1167: xoperands[1] = plus_constant (op1, i);
1168: output_asm_insn ("ld.b %a1,%?r31\n\tst.b %?r31,%a0",
1169: xoperands);
1170: }
1171: return "";
1172: }
1173: }
1174: }
1175:
1176: /* Since we clobber untold things, nix the condition codes. */
1177: CC_STATUS_INIT;
1178:
1179: /* This is the size of the transfer.
1180: Either use the register which already contains the size,
1181: or use a free register (used by no operands). */
1182: output_size_for_block_move (operands[2], operands[4], alignrtx);
1183:
1184: #if 0
1185: /* Also emit code to decrement the size value by ALIGN. */
1186: zoperands[0] = operands[0];
1187: zoperands[3] = plus_constant (operands[0], align);
1188: output_load_address (zoperands);
1189: #endif
1190:
1191: /* Generate number for unique label. */
1192:
1193: xoperands[3] = gen_rtx (CONST_INT, VOIDmode, movstrsi_label++);
1194:
1195: /* Calculate the size of the chunks we will be trying to move first. */
1196:
1197: #if 0
1198: if ((align & 3) == 0)
1199: chunk_size = 4;
1200: else if ((align & 1) == 0)
1201: chunk_size = 2;
1202: else
1203: #endif
1204: chunk_size = 1;
1205:
1206: /* Copy the increment (negative) to a register for bla insn. */
1207:
1208: xoperands[4] = gen_rtx (CONST_INT, VOIDmode, - chunk_size);
1209: xoperands[5] = operands[5];
1210: output_asm_insn ("adds %4,%?r0,%5", xoperands);
1211:
1212: /* Predecrement the loop counter. This happens again also in the `bla'
1.1.1.2 root 1213: instruction which precedes the loop, but we need to have it done
1214: two times before we enter the loop because of the bizarre semantics
1.1 root 1215: of the bla instruction. */
1216:
1217: output_asm_insn ("adds %5,%2,%2", xoperands);
1218:
1219: /* Check for the case where the original count was less than or equal to
1220: zero. Avoid going through the loop at all if the original count was
1221: indeed less than or equal to zero. Note that we treat the count as
1222: if it were a signed 32-bit quantity here, rather than an unsigned one,
1223: even though we really shouldn't. We have to do this because of the
1224: semantics of the `ble' instruction, which assume that the count is
1225: a signed 32-bit value. Anyway, in practice it won't matter because
1226: nobody is going to try to do a memcpy() of more than half of the
1227: entire address space (i.e. 2 gigabytes) anyway. */
1228:
1229: output_asm_insn ("bc .Le%3", xoperands);
1230:
1231: /* Make available a register which is a temporary. */
1232:
1233: xoperands[6] = operands[6];
1234:
1235: /* Now the actual loop.
1236: In xoperands, elements 1 and 0 are the input and output vectors.
1237: Element 2 is the loop index. Element 5 is the increment. */
1238:
1239: output_asm_insn ("subs %1,%5,%1", xoperands);
1240: output_asm_insn ("bla %5,%2,.Lm%3", xoperands);
1241: output_asm_insn ("adds %0,%2,%6", xoperands);
1242: output_asm_insn ("\n.Lm%3:", xoperands); /* Label for bla above. */
1243: output_asm_insn ("\n.Ls%3:", xoperands); /* Loop start label. */
1244: output_asm_insn ("adds %5,%6,%6", xoperands);
1245:
1246: /* NOTE: The code here which is supposed to handle the cases where the
1247: sources and destinations are known to start on a 4 or 2 byte boundary
1248: are currently broken. They fail to do anything about the overflow
1249: bytes which might still need to be copied even after we have copied
1250: some number of words or halfwords. Thus, for now we use the lowest
1251: common denominator, i.e. the code which just copies some number of
1252: totally unaligned individual bytes. (See the calculation of
1253: chunk_size above. */
1254:
1255: if (chunk_size == 4)
1256: {
1257: output_asm_insn ("ld.l %2(%1),%?r31", xoperands);
1258: output_asm_insn ("bla %5,%2,.Ls%3", xoperands);
1259: output_asm_insn ("st.l %?r31,8(%6)", xoperands);
1260: }
1261: else if (chunk_size == 2)
1262: {
1263: output_asm_insn ("ld.s %2(%1),%?r31", xoperands);
1264: output_asm_insn ("bla %5,%2,.Ls%3", xoperands);
1265: output_asm_insn ("st.s %?r31,4(%6)", xoperands);
1266: }
1267: else /* chunk_size == 1 */
1268: {
1269: output_asm_insn ("ld.b %2(%1),%?r31", xoperands);
1270: output_asm_insn ("bla %5,%2,.Ls%3", xoperands);
1271: output_asm_insn ("st.b %?r31,2(%6)", xoperands);
1272: }
1273: output_asm_insn ("\n.Le%3:", xoperands); /* Here if count <= 0. */
1274:
1275: return "";
1276: }
1277:
1278: /* Output a delayed branch insn with the delay insn in its
1279: branch slot. The delayed branch insn template is in TEMPLATE,
1280: with operands OPERANDS. The insn in its delay slot is INSN.
1281:
1282: As a special case, since we know that all memory transfers are via
1283: ld/st insns, if we see a (MEM (SYMBOL_REF ...)) we divide the memory
1284: reference around the branch as
1285:
1286: orh ha%x,%?r0,%?r31
1287: b ...
1288: ld/st l%x(%?r31),...
1289:
1290: As another special case, we handle loading (SYMBOL_REF ...) and
1291: other large constants around branches as well:
1292:
1293: orh h%x,%?r0,%0
1294: b ...
1295: or l%x,%0,%1
1296:
1297: */
1298:
1299: char *
1300: output_delayed_branch (template, operands, insn)
1301: char *template;
1302: rtx *operands;
1303: rtx insn;
1304: {
1305: rtx src = XVECEXP (PATTERN (insn), 0, 1);
1306: rtx dest = XVECEXP (PATTERN (insn), 0, 0);
1307:
1308: /* See if we are doing some branch together with setting some register
1309: to some 32-bit value which does (or may) have some of the high-order
1310: 16 bits set. If so, we need to set the register in two stages. One
1311: stage must be done before the branch, and the other one can be done
1312: in the delay slot. */
1313:
1314: if ( (GET_CODE (src) == CONST_INT
1315: && ((unsigned) INTVAL (src) & (unsigned) 0xffff0000) != (unsigned) 0)
1316: || (GET_CODE (src) == SYMBOL_REF)
1317: || (GET_CODE (src) == LABEL_REF)
1318: || (GET_CODE (src) == CONST))
1319: {
1320: rtx xoperands[2];
1321: xoperands[0] = dest;
1322: xoperands[1] = src;
1323:
1324: CC_STATUS_PARTIAL_INIT;
1325: /* Output the `orh' insn. */
1326: output_asm_insn ("orh %H1,%?r0,%0", xoperands);
1327:
1328: /* Output the branch instruction next. */
1329: output_asm_insn (template, operands);
1330:
1331: /* Now output the `or' insn. */
1332: output_asm_insn ("or %L1,%0,%0", xoperands);
1333: }
1334: else if ((GET_CODE (src) == MEM
1335: && CONSTANT_ADDRESS_P (XEXP (src, 0)))
1336: || (GET_CODE (dest) == MEM
1337: && CONSTANT_ADDRESS_P (XEXP (dest, 0))))
1338: {
1339: rtx xoperands[2];
1340: char *split_template;
1341: xoperands[0] = dest;
1342: xoperands[1] = src;
1343:
1344: /* Output the `orh' insn. */
1345: if (GET_CODE (src) == MEM)
1346: {
1347: if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
1348: && (cc_prev_status.flags & CC_HI_R31_ADJ)
1349: && cc_prev_status.mdep == XEXP (operands[1], 0)))
1350: {
1351: CC_STATUS_INIT;
1352: output_asm_insn ("orh %h1,%?r0,%?r31", xoperands);
1353: }
1354: split_template = load_opcode (GET_MODE (dest),
1355: "%L1(%?r31),%0", dest);
1356: }
1357: else
1358: {
1359: if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
1360: && (cc_prev_status.flags & CC_HI_R31_ADJ)
1361: && cc_prev_status.mdep == XEXP (operands[0], 0)))
1362: {
1363: CC_STATUS_INIT;
1364: output_asm_insn ("orh %h0,%?r0,%?r31", xoperands);
1365: }
1366: split_template = store_opcode (GET_MODE (dest),
1367: "%r1,%L0(%?r31)", src);
1368: }
1369:
1370: /* Output the branch instruction next. */
1371: output_asm_insn (template, operands);
1372:
1373: /* Now output the load or store.
1374: No need to do a CC_STATUS_INIT, because we are branching anyway. */
1375: output_asm_insn (split_template, xoperands);
1376: }
1377: else
1378: {
1379: int insn_code_number;
1380: rtx pat = gen_rtx (SET, VOIDmode, dest, src);
1381: rtx delay_insn = gen_rtx (INSN, VOIDmode, 0, 0, 0, pat, -1, 0, 0);
1382: int i;
1383:
1384: /* Output the branch instruction first. */
1385: output_asm_insn (template, operands);
1386:
1387: /* Now recognize the insn which we put in its delay slot.
1.1.1.2 root 1388: We must do this after outputting the branch insn,
1.1 root 1389: since operands may just be a pointer to `recog_operand'. */
1390: INSN_CODE (delay_insn) = insn_code_number = recog (pat, delay_insn);
1391: if (insn_code_number == -1)
1392: abort ();
1393:
1394: for (i = 0; i < insn_n_operands[insn_code_number]; i++)
1395: {
1396: if (GET_CODE (recog_operand[i]) == SUBREG)
1397: recog_operand[i] = alter_subreg (recog_operand[i]);
1398: }
1399:
1400: insn_extract (delay_insn);
1401: if (! constrain_operands (insn_code_number, 1))
1402: fatal_insn_not_found (delay_insn);
1403:
1404: template = insn_template[insn_code_number];
1405: if (template == 0)
1406: template = (*insn_outfun[insn_code_number]) (recog_operand, delay_insn);
1407: output_asm_insn (template, recog_operand);
1408: }
1409: CC_STATUS_INIT;
1410: return "";
1411: }
1412:
1413: /* Output a newly constructed insn DELAY_INSN. */
1414: char *
1415: output_delay_insn (delay_insn)
1416: rtx delay_insn;
1417: {
1418: char *template;
1419: int insn_code_number;
1420: int i;
1421:
1422: /* Now recognize the insn which we put in its delay slot.
1.1.1.2 root 1423: We must do this after outputting the branch insn,
1.1 root 1424: since operands may just be a pointer to `recog_operand'. */
1425: insn_code_number = recog_memoized (delay_insn);
1426: if (insn_code_number == -1)
1427: abort ();
1428:
1429: /* Extract the operands of this delay insn. */
1430: INSN_CODE (delay_insn) = insn_code_number;
1431: insn_extract (delay_insn);
1432:
1.1.1.2 root 1433: /* It is possible that this insn has not been properly scanned by final
1.1 root 1434: yet. If this insn's operands don't appear in the peephole's
1435: actual operands, then they won't be fixed up by final, so we
1436: make sure they get fixed up here. -- This is a kludge. */
1437: for (i = 0; i < insn_n_operands[insn_code_number]; i++)
1438: {
1439: if (GET_CODE (recog_operand[i]) == SUBREG)
1440: recog_operand[i] = alter_subreg (recog_operand[i]);
1441: }
1442:
1443: #ifdef REGISTER_CONSTRAINTS
1444: if (! constrain_operands (insn_code_number))
1445: abort ();
1446: #endif
1447:
1448: cc_prev_status = cc_status;
1449:
1450: /* Update `cc_status' for this instruction.
1451: The instruction's output routine may change it further.
1452: If the output routine for a jump insn needs to depend
1453: on the cc status, it should look at cc_prev_status. */
1454:
1455: NOTICE_UPDATE_CC (PATTERN (delay_insn), delay_insn);
1456:
1457: /* Now get the template for what this insn would
1458: have been, without the branch. */
1459:
1460: template = insn_template[insn_code_number];
1461: if (template == 0)
1462: template = (*insn_outfun[insn_code_number]) (recog_operand, delay_insn);
1463: output_asm_insn (template, recog_operand);
1464: return "";
1465: }
1466:
1467: /* Special routine to convert an SFmode value represented as a
1468: CONST_DOUBLE into its equivalent unsigned long bit pattern.
1469: We convert the value from a double precision floating-point
1470: value to single precision first, and thence to a bit-wise
1471: equivalent unsigned long value. This routine is used when
1472: generating an immediate move of an SFmode value directly
1473: into a general register because the svr4 assembler doesn't
1474: grok floating literals in instruction operand contexts. */
1475:
1476: unsigned long
1477: sfmode_constant_to_ulong (x)
1478: rtx x;
1479: {
1.1.1.2 root 1480: REAL_VALUE_TYPE d;
1.1 root 1481: union { float f; unsigned long i; } u2;
1482:
1483: if (GET_CODE (x) != CONST_DOUBLE || GET_MODE (x) != SFmode)
1484: abort ();
1485:
1.1.1.2 root 1486: #if TARGET_FLOAT_FORMAT != HOST_FLOAT_FORMAT
1.1.1.3 root 1487: error IEEE emulation needed
1.1 root 1488: #endif
1.1.1.2 root 1489: REAL_VALUE_FROM_CONST_DOUBLE (d, x);
1490: u2.f = d;
1.1 root 1491: return u2.i;
1492: }
1493:
1494: /* This function generates the assembly code for function entry.
1495: The macro FUNCTION_PROLOGUE in i860.h is defined to call this function.
1496:
1497: ASM_FILE is a stdio stream to output the code to.
1498: SIZE is an int: how many units of temporary storage to allocate.
1499:
1500: Refer to the array `regs_ever_live' to determine which registers
1501: to save; `regs_ever_live[I]' is nonzero if register number I
1502: is ever used in the function. This macro is responsible for
1503: knowing which registers should not be saved even if used.
1504:
1505: NOTE: `frame_lower_bytes' is the count of bytes which will lie
1506: between the new `fp' value and the new `sp' value after the
1507: prologue is done. `frame_upper_bytes' is the count of bytes
1508: that will lie between the new `fp' and the *old* `sp' value
1509: after the new `fp' is setup (in the prologue). The upper
1510: part of each frame always includes at least 2 words (8 bytes)
1511: to hold the saved frame pointer and the saved return address.
1512:
1513: The svr4 ABI for the i860 now requires that the values of the
1514: stack pointer and frame pointer registers be kept aligned to
1515: 16-byte boundaries at all times. We obey that restriction here.
1516:
1517: The svr4 ABI for the i860 is entirely vague when it comes to specifying
1518: exactly where the "preserved" registers should be saved. The native
1519: svr4 C compiler I now have doesn't help to clarify the requirements
1520: very much because it is plainly out-of-date and non-ABI-compliant
1521: (in at least one important way, i.e. how it generates function
1522: epilogues).
1523:
1524: The native svr4 C compiler saves the "preserved" registers (i.e.
1525: r4-r15 and f2-f7) in the lower part of a frame (i.e. at negative
1526: offsets from the frame pointer).
1527:
1528: Previous versions of GCC also saved the "preserved" registers in the
1.1.1.2 root 1529: "negative" part of the frame, but they saved them using positive
1.1 root 1530: offsets from the (adjusted) stack pointer (after it had been adjusted
1531: to allocate space for the new frame). That's just plain wrong
1532: because if the current function calls alloca(), the stack pointer
1533: will get moved, and it will be impossible to restore the registers
1534: properly again after that.
1535:
1536: Both compilers handled parameter registers (i.e. r16-r27 and f8-f15)
1537: by copying their values either into various "preserved" registers or
1538: into stack slots in the lower part of the current frame (as seemed
1539: appropriate, depending upon subsequent usage of these values).
1540:
1541: Here we want to save the preserved registers at some offset from the
1542: frame pointer register so as to avoid any possible problems arising
1543: from calls to alloca(). We can either save them at small positive
1544: offsets from the frame pointer, or at small negative offsets from
1545: the frame pointer. If we save them at small negative offsets from
1546: the frame pointer (i.e. in the lower part of the frame) then we
1547: must tell the rest of GCC (via STARTING_FRAME_OFFSET) exactly how
1548: many bytes of space we plan to use in the lower part of the frame
1549: for this purpose. Since other parts of the compiler reference the
1550: value of STARTING_FRAME_OFFSET long before final() calls this function,
1551: we would have to go ahead and assume the worst-case storage requirements
1552: for saving all of the "preserved" registers (and use that number, i.e.
1553: `80', to define STARTING_FRAME_OFFSET) if we wanted to save them in
1554: the lower part of the frame. That could potentially be very wasteful,
1555: and that wastefulness could really hamper people compiling for embedded
1556: i860 targets with very tight limits on stack space. Thus, we choose
1557: here to save the preserved registers in the upper part of the
1558: frame, so that we can decide at the very last minute how much (or how
1559: little) space we must allocate for this purpose.
1560:
1561: To satisfy the needs of the svr4 ABI "tdesc" scheme, preserved
1562: registers must always be saved so that the saved values of registers
1563: with higher numbers are at higher addresses. We obey that restriction
1564: here.
1565:
1566: There are two somewhat different ways that you can generate prologues
1567: here... i.e. pedantically ABI-compliant, and the "other" way. The
1.1.1.2 root 1568: "other" way is more consistent with what is currently generated by the
1.1 root 1569: "native" svr4 C compiler for the i860. That's important if you want
1570: to use the current (as of 8/91) incarnation of svr4 SDB for the i860.
1571: The SVR4 SDB for the i860 insists on having function prologues be
1572: non-ABI-compliant!
1573:
1574: To get fully ABI-compliant prologues, define I860_STRICT_ABI_PROLOGUES
1575: in the i860svr4.h file. (By default this is *not* defined).
1576:
1577: The differences between the ABI-compliant and non-ABI-compliant prologues
1578: are that (a) the ABI version seems to require the use of *signed*
1579: (rather than unsigned) adds and subtracts, and (b) the ordering of
1580: the various steps (e.g. saving preserved registers, saving the
1581: return address, setting up the new frame pointer value) is different.
1582:
1583: For strict ABI compliance, it seems to be the case that the very last
1584: thing that is supposed to happen in the prologue is getting the frame
1585: pointer set to its new value (but only after everything else has
1586: already been properly setup). We do that here, but only if the symbol
1587: I860_STRICT_ABI_PROLOGUES is defined.
1588: */
1589:
1590: #ifndef STACK_ALIGNMENT
1591: #define STACK_ALIGNMENT 16
1592: #endif
1593:
1594: extern char call_used_regs[];
1595: extern int leaf_function_p ();
1596:
1597: char *current_function_original_name;
1598:
1599: static int must_preserve_r1;
1600: static unsigned must_preserve_bytes;
1601:
1602: void
1603: function_prologue (asm_file, local_bytes)
1604: register FILE *asm_file;
1605: register unsigned local_bytes;
1606: {
1607: register unsigned frame_lower_bytes;
1608: register unsigned frame_upper_bytes;
1609: register unsigned total_fsize;
1610: register unsigned preserved_reg_bytes = 0;
1611: register unsigned i;
1612: register unsigned preserved_so_far = 0;
1613:
1614: must_preserve_r1 = (optimize < 2 || ! leaf_function_p ());
1615: must_preserve_bytes = 4 + (must_preserve_r1 ? 4 : 0);
1616:
1617: /* Count registers that need preserving. Ignore r0. It never needs
1618: preserving. */
1619:
1620: for (i = 1; i < FIRST_PSEUDO_REGISTER; i++)
1621: {
1622: if (regs_ever_live[i] && ! call_used_regs[i])
1623: preserved_reg_bytes += 4;
1624: }
1625:
1626: /* Round-up the frame_lower_bytes so that it's a multiple of 16. */
1627:
1628: frame_lower_bytes = (local_bytes + STACK_ALIGNMENT - 1) & -STACK_ALIGNMENT;
1629:
1630: /* The upper part of each frame will contain the saved fp,
1631: the saved r1, and stack slots for all of the other "preserved"
1632: registers that we find we will need to save & restore. */
1633:
1634: frame_upper_bytes = must_preserve_bytes + preserved_reg_bytes;
1635:
1636: /* Round-up the frame_upper_bytes so that it's a multiple of 16. */
1637:
1638: frame_upper_bytes
1639: = (frame_upper_bytes + STACK_ALIGNMENT - 1) & -STACK_ALIGNMENT;
1640:
1641: total_fsize = frame_upper_bytes + frame_lower_bytes;
1642:
1643: #ifndef I860_STRICT_ABI_PROLOGUES
1644:
1645: /* There are two kinds of function prologues.
1646: You use the "small" version if the total frame size is
1647: small enough so that it can fit into an immediate 16-bit
1648: value in one instruction. Otherwise, you use the "large"
1649: version of the function prologue. */
1650:
1651: if (total_fsize > 0x7fff)
1652: {
1653: /* Adjust the stack pointer. The ABI sez to do this using `adds',
1654: but the native C compiler on svr4 uses `addu'. */
1655:
1656: fprintf (asm_file, "\taddu -%d,%ssp,%ssp\n",
1657: frame_upper_bytes, i860_reg_prefix, i860_reg_prefix);
1658:
1659: /* Save the old frame pointer. */
1660:
1661: fprintf (asm_file, "\tst.l %sfp,0(%ssp)\n",
1662: i860_reg_prefix, i860_reg_prefix);
1663:
1664: /* Setup the new frame pointer. The ABI sez to do this after
1665: preserving registers (using adds), but that's not what the
1666: native C compiler on svr4 does. */
1667:
1668: fprintf (asm_file, "\taddu 0,%ssp,%sfp\n",
1669: i860_reg_prefix, i860_reg_prefix);
1670:
1671: /* Get the value of frame_lower_bytes into r31. */
1672:
1673: fprintf (asm_file, "\torh %d,%sr0,%sr31\n",
1674: frame_lower_bytes >> 16, i860_reg_prefix, i860_reg_prefix);
1675: fprintf (asm_file, "\tor %d,%sr31,%sr31\n",
1676: frame_lower_bytes & 0xffff, i860_reg_prefix, i860_reg_prefix);
1677:
1678: /* Now re-adjust the stack pointer using the value in r31.
1679: The ABI sez to do this with `subs' but SDB may prefer `subu'. */
1680:
1681: fprintf (asm_file, "\tsubu %ssp,%sr31,%ssp\n",
1682: i860_reg_prefix, i860_reg_prefix, i860_reg_prefix);
1683:
1684: /* Preserve registers. The ABI sez to do this before setting
1685: up the new frame pointer, but that's not what the native
1686: C compiler on svr4 does. */
1687:
1688: for (i = 1; i < 32; i++)
1689: if (regs_ever_live[i] && ! call_used_regs[i])
1690: fprintf (asm_file, "\tst.l %s%s,%d(%sfp)\n",
1691: i860_reg_prefix, reg_names[i],
1692: must_preserve_bytes + (4 * preserved_so_far++),
1693: i860_reg_prefix);
1694:
1695: for (i = 32; i < 64; i++)
1696: if (regs_ever_live[i] && ! call_used_regs[i])
1697: fprintf (asm_file, "\tfst.l %s%s,%d(%sfp)\n",
1698: i860_reg_prefix, reg_names[i],
1699: must_preserve_bytes + (4 * preserved_so_far++),
1700: i860_reg_prefix);
1701:
1702: /* Save the return address. */
1703:
1704: if (must_preserve_r1)
1705: fprintf (asm_file, "\tst.l %sr1,4(%sfp)\n",
1706: i860_reg_prefix, i860_reg_prefix);
1707: }
1708: else
1709: {
1710: /* Adjust the stack pointer. The ABI sez to do this using `adds',
1711: but the native C compiler on svr4 uses `addu'. */
1712:
1713: fprintf (asm_file, "\taddu -%d,%ssp,%ssp\n",
1714: total_fsize, i860_reg_prefix, i860_reg_prefix);
1715:
1716: /* Save the old frame pointer. */
1717:
1718: fprintf (asm_file, "\tst.l %sfp,%d(%ssp)\n",
1719: i860_reg_prefix, frame_lower_bytes, i860_reg_prefix);
1720:
1721: /* Setup the new frame pointer. The ABI sez to do this after
1722: preserving registers and after saving the return address,
1723: (and its saz to do this using adds), but that's not what the
1724: native C compiler on svr4 does. */
1725:
1726: fprintf (asm_file, "\taddu %d,%ssp,%sfp\n",
1727: frame_lower_bytes, i860_reg_prefix, i860_reg_prefix);
1728:
1729: /* Preserve registers. The ABI sez to do this before setting
1730: up the new frame pointer, but that's not what the native
1731: compiler on svr4 does. */
1732:
1733: for (i = 1; i < 32; i++)
1734: if (regs_ever_live[i] && ! call_used_regs[i])
1735: fprintf (asm_file, "\tst.l %s%s,%d(%sfp)\n",
1736: i860_reg_prefix, reg_names[i],
1737: must_preserve_bytes + (4 * preserved_so_far++),
1738: i860_reg_prefix);
1739:
1740: for (i = 32; i < 64; i++)
1741: if (regs_ever_live[i] && ! call_used_regs[i])
1742: fprintf (asm_file, "\tfst.l %s%s,%d(%sfp)\n",
1743: i860_reg_prefix, reg_names[i],
1744: must_preserve_bytes + (4 * preserved_so_far++),
1745: i860_reg_prefix);
1746:
1747: /* Save the return address. The ABI sez to do this earlier,
1748: and also via an offset from %sp, but the native C compiler
1749: on svr4 does it later (i.e. now) and uses an offset from
1750: %fp. */
1751:
1752: if (must_preserve_r1)
1753: fprintf (asm_file, "\tst.l %sr1,4(%sfp)\n",
1754: i860_reg_prefix, i860_reg_prefix);
1755: }
1756:
1757: #else /* defined(I860_STRICT_ABI_PROLOGUES) */
1758:
1759: /* There are two kinds of function prologues.
1760: You use the "small" version if the total frame size is
1761: small enough so that it can fit into an immediate 16-bit
1762: value in one instruction. Otherwise, you use the "large"
1763: version of the function prologue. */
1764:
1765: if (total_fsize > 0x7fff)
1766: {
1767: /* Adjust the stack pointer (thereby allocating a new frame). */
1768:
1769: fprintf (asm_file, "\tadds -%d,%ssp,%ssp\n",
1770: frame_upper_bytes, i860_reg_prefix, i860_reg_prefix);
1771:
1772: /* Save the caller's frame pointer. */
1773:
1774: fprintf (asm_file, "\tst.l %sfp,0(%ssp)\n",
1775: i860_reg_prefix, i860_reg_prefix);
1776:
1777: /* Save return address. */
1778:
1779: if (must_preserve_r1)
1780: fprintf (asm_file, "\tst.l %sr1,4(%ssp)\n",
1781: i860_reg_prefix, i860_reg_prefix);
1782:
1783: /* Get the value of frame_lower_bytes into r31 for later use. */
1784:
1785: fprintf (asm_file, "\torh %d,%sr0,%sr31\n",
1786: frame_lower_bytes >> 16, i860_reg_prefix, i860_reg_prefix);
1787: fprintf (asm_file, "\tor %d,%sr31,%sr31\n",
1788: frame_lower_bytes & 0xffff, i860_reg_prefix, i860_reg_prefix);
1789:
1790: /* Now re-adjust the stack pointer using the value in r31. */
1791:
1792: fprintf (asm_file, "\tsubs %ssp,%sr31,%ssp\n",
1793: i860_reg_prefix, i860_reg_prefix, i860_reg_prefix);
1794:
1795: /* Pre-compute value to be used as the new frame pointer. */
1796:
1797: fprintf (asm_file, "\tadds %ssp,%sr31,%sr31\n",
1798: i860_reg_prefix, i860_reg_prefix, i860_reg_prefix);
1799:
1800: /* Preserve registers. */
1801:
1802: for (i = 1; i < 32; i++)
1803: if (regs_ever_live[i] && ! call_used_regs[i])
1804: fprintf (asm_file, "\tst.l %s%s,%d(%sr31)\n",
1805: i860_reg_prefix, reg_names[i],
1806: must_preserve_bytes + (4 * preserved_so_far++),
1807: i860_reg_prefix);
1808:
1809: for (i = 32; i < 64; i++)
1810: if (regs_ever_live[i] && ! call_used_regs[i])
1811: fprintf (asm_file, "\tfst.l %s%s,%d(%sr31)\n",
1812: i860_reg_prefix, reg_names[i],
1813: must_preserve_bytes + (4 * preserved_so_far++),
1814: i860_reg_prefix);
1815:
1816: /* Actually set the new value of the frame pointer. */
1817:
1818: fprintf (asm_file, "\tmov %sr31,%sfp\n",
1819: i860_reg_prefix, i860_reg_prefix);
1820: }
1821: else
1822: {
1823: /* Adjust the stack pointer. */
1824:
1825: fprintf (asm_file, "\tadds -%d,%ssp,%ssp\n",
1826: total_fsize, i860_reg_prefix, i860_reg_prefix);
1827:
1828: /* Save the caller's frame pointer. */
1829:
1830: fprintf (asm_file, "\tst.l %sfp,%d(%ssp)\n",
1831: i860_reg_prefix, frame_lower_bytes, i860_reg_prefix);
1832:
1833: /* Save the return address. */
1834:
1835: if (must_preserve_r1)
1836: fprintf (asm_file, "\tst.l %sr1,%d(%ssp)\n",
1837: i860_reg_prefix, frame_lower_bytes + 4, i860_reg_prefix);
1838:
1839: /* Preserve registers. */
1840:
1841: for (i = 1; i < 32; i++)
1842: if (regs_ever_live[i] && ! call_used_regs[i])
1843: fprintf (asm_file, "\tst.l %s%s,%d(%ssp)\n",
1844: i860_reg_prefix, reg_names[i],
1845: frame_lower_bytes + must_preserve_bytes + (4 * preserved_so_far++),
1846: i860_reg_prefix);
1847:
1848: for (i = 32; i < 64; i++)
1849: if (regs_ever_live[i] && ! call_used_regs[i])
1850: fprintf (asm_file, "\tfst.l %s%s,%d(%ssp)\n",
1851: i860_reg_prefix, reg_names[i],
1852: frame_lower_bytes + must_preserve_bytes + (4 * preserved_so_far++),
1853: i860_reg_prefix);
1854:
1855: /* Setup the new frame pointer. */
1856:
1857: fprintf (asm_file, "\tadds %d,%ssp,%sfp\n",
1858: frame_lower_bytes, i860_reg_prefix, i860_reg_prefix);
1859: }
1860: #endif /* defined(I860_STRICT_ABI_PROLOGUES) */
1861:
1862: #ifdef ASM_OUTPUT_PROLOGUE_SUFFIX
1863: ASM_OUTPUT_PROLOGUE_SUFFIX (asm_file);
1864: #endif /* defined(ASM_OUTPUT_PROLOGUE_SUFFIX) */
1865: }
1866:
1867: /* This function generates the assembly code for function exit.
1868: The macro FUNCTION_EPILOGUE in i860.h is defined to call this function.
1869:
1870: ASM_FILE is a stdio stream to output the code to.
1871: SIZE is an int: how many units of temporary storage to allocate.
1872:
1873: The function epilogue should not depend on the current stack pointer!
1874: It should use the frame pointer only. This is mandatory because
1875: of alloca; we also take advantage of it to omit stack adjustments
1876: before returning.
1877:
1878: Note that when we go to restore the preserved register values we must
1879: not try to address their slots by using offsets from the stack pointer.
1880: That's because the stack pointer may have been moved during the function
1881: execution due to a call to alloca(). Rather, we must restore all
1882: preserved registers via offsets from the frame pointer value.
1883:
1884: Note also that when the current frame is being "popped" (by adjusting
1885: the value of the stack pointer) on function exit, we must (for the
1886: sake of alloca) set the new value of the stack pointer based upon
1887: the current value of the frame pointer. We can't just add what we
1888: believe to be the (static) frame size to the stack pointer because
1889: if we did that, and alloca() had been called during this function,
1890: we would end up returning *without* having fully deallocated all of
1891: the space grabbed by alloca. If that happened, and a function
1892: containing one or more alloca() calls was called over and over again,
1893: then the stack would grow without limit!
1894:
1895: Finally note that the epilogues generated here are completely ABI
1896: compliant. They go out of their way to insure that the value in
1897: the frame pointer register is never less than the value in the stack
1898: pointer register. It's not clear why this relationship needs to be
1899: maintained at all times, but maintaining it only costs one extra
1900: instruction, so what the hell.
1901: */
1902:
1.1.1.3 root 1903: /* This corresponds to a version 4 TDESC structure. Lower numbered
1904: versions successively omit the last word of the structure. We
1905: don't try to handle version 5 here. */
1906:
1907: typedef struct TDESC_flags {
1908: int version:4;
1909: int reg_packing:1;
1910: int callable_block:1;
1911: int reserved:4;
1912: int fregs:6; /* fp regs 2-7 */
1913: int iregs:16; /* regs 0-15 */
1914: } TDESC_flags;
1915:
1916: typedef struct TDESC {
1917: TDESC_flags flags;
1918: int integer_reg_offset; /* same as must_preserve_bytes */
1919: int floating_point_reg_offset;
1920: unsigned int positive_frame_size; /* same as frame_upper_bytes */
1921: unsigned int negative_frame_size; /* same as frame_lower_bytes */
1922: } TDESC;
1923:
1.1 root 1924: void
1925: function_epilogue (asm_file, local_bytes)
1926: register FILE *asm_file;
1927: register unsigned local_bytes;
1928: {
1929: register unsigned frame_upper_bytes;
1.1.1.3 root 1930: register unsigned frame_lower_bytes;
1.1 root 1931: register unsigned preserved_reg_bytes = 0;
1932: register unsigned i;
1933: register unsigned restored_so_far = 0;
1.1.1.3 root 1934: register unsigned int_restored;
1935: register unsigned mask;
1936: unsigned intflags=0;
1937: register TDESC_flags *flags = (TDESC_flags *) &intflags;
1938:
1939: flags->version = 4;
1940: flags->reg_packing = 1;
1941: flags->iregs = 8; /* old fp always gets saved */
1942:
1943: /* Round-up the frame_lower_bytes so that it's a multiple of 16. */
1944:
1945: frame_lower_bytes = (local_bytes + STACK_ALIGNMENT - 1) & -STACK_ALIGNMENT;
1.1 root 1946:
1947: /* Count the number of registers that were preserved in the prologue.
1948: Ignore r0. It is never preserved. */
1949:
1950: for (i = 1; i < FIRST_PSEUDO_REGISTER; i++)
1951: {
1952: if (regs_ever_live[i] && ! call_used_regs[i])
1953: preserved_reg_bytes += 4;
1954: }
1955:
1956: /* The upper part of each frame will contain only saved fp,
1957: the saved r1, and stack slots for all of the other "preserved"
1958: registers that we find we will need to save & restore. */
1959:
1960: frame_upper_bytes = must_preserve_bytes + preserved_reg_bytes;
1961:
1962: /* Round-up frame_upper_bytes so that t is a multiple of 16. */
1963:
1964: frame_upper_bytes
1965: = (frame_upper_bytes + STACK_ALIGNMENT - 1) & -STACK_ALIGNMENT;
1966:
1967: /* Restore all of the "preserved" registers that need restoring. */
1968:
1.1.1.3 root 1969: mask = 2;
1970:
1971: for (i = 1; i < 32; i++, mask<<=1)
1972: if (regs_ever_live[i] && ! call_used_regs[i]) {
1.1 root 1973: fprintf (asm_file, "\tld.l %d(%sfp),%s%s\n",
1974: must_preserve_bytes + (4 * restored_so_far++),
1975: i860_reg_prefix, i860_reg_prefix, reg_names[i]);
1.1.1.3 root 1976: if (i > 3 && i < 16)
1977: flags->iregs |= mask;
1978: }
1.1 root 1979:
1.1.1.3 root 1980: int_restored = restored_so_far;
1981: mask = 1;
1982:
1983: for (i = 32; i < 64; i++) {
1984: if (regs_ever_live[i] && ! call_used_regs[i]) {
1.1 root 1985: fprintf (asm_file, "\tfld.l %d(%sfp),%s%s\n",
1986: must_preserve_bytes + (4 * restored_so_far++),
1987: i860_reg_prefix, i860_reg_prefix, reg_names[i]);
1.1.1.3 root 1988: if (i > 33 & i < 40)
1989: flags->fregs |= mask;
1990: }
1991: if (i > 33 && i < 40)
1992: mask<<=1;
1993: }
1.1 root 1994:
1995: /* Get the value we plan to use to restore the stack pointer into r31. */
1996:
1997: fprintf (asm_file, "\tadds %d,%sfp,%sr31\n",
1998: frame_upper_bytes, i860_reg_prefix, i860_reg_prefix);
1999:
2000: /* Restore the return address and the old frame pointer. */
2001:
1.1.1.3 root 2002: if (must_preserve_r1) {
1.1 root 2003: fprintf (asm_file, "\tld.l 4(%sfp),%sr1\n",
2004: i860_reg_prefix, i860_reg_prefix);
1.1.1.3 root 2005: flags->iregs |= 2;
2006: }
1.1 root 2007:
2008: fprintf (asm_file, "\tld.l 0(%sfp),%sfp\n",
2009: i860_reg_prefix, i860_reg_prefix);
2010:
2011: /* Return and restore the old stack pointer value. */
2012:
2013: fprintf (asm_file, "\tbri %sr1\n\tmov %sr31,%ssp\n",
2014: i860_reg_prefix, i860_reg_prefix, i860_reg_prefix);
1.1.1.3 root 2015:
2016: #ifdef OUTPUT_TDESC /* Output an ABI-compliant TDESC entry */
2017: if (! frame_lower_bytes) {
2018: flags->version--;
2019: if (! frame_upper_bytes) {
2020: flags->version--;
2021: if (restored_so_far == int_restored) /* No FP saves */
2022: flags->version--;
2023: }
2024: }
2025: assemble_name(asm_file,current_function_original_name);
2026: fputs(".TDESC:\n", asm_file);
2027: fprintf(asm_file, "%s 0x%0x\n", ASM_LONG, intflags);
2028: fprintf(asm_file, "%s %d\n", ASM_LONG,
2029: int_restored ? must_preserve_bytes : 0);
2030: if (flags->version > 1) {
2031: fprintf(asm_file, "%s %d\n", ASM_LONG,
2032: (restored_so_far == int_restored) ? 0 : must_preserve_bytes +
2033: (4 * int_restored));
2034: if (flags->version > 2) {
2035: fprintf(asm_file, "%s %d\n", ASM_LONG, frame_upper_bytes);
2036: if (flags->version > 3)
2037: fprintf(asm_file, "%s %d\n", ASM_LONG, frame_lower_bytes);
2038: }
2039: }
2040: tdesc_section();
2041: fprintf(asm_file, "%s ", ASM_LONG);
2042: assemble_name(asm_file, current_function_original_name);
2043: fprintf(asm_file, "\n%s ", ASM_LONG);
2044: assemble_name(asm_file, current_function_original_name);
2045: fputs(".TDESC\n", asm_file);
2046: text_section();
2047: #endif
1.1 root 2048: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.