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