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