|
|
1.1 root 1: /* Subroutines used for code generation on ROMP.
2: Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
3: Contributed by Richard Kenner ([email protected])
4:
5: This file is part of GNU CC.
6:
7: GNU CC is free software; you can redistribute it and/or modify
8: it under the terms of the GNU General Public License as published by
9: the Free Software Foundation; either version 2, or (at your option)
10: any later version.
11:
12: GNU CC is distributed in the hope that it will be useful,
13: but WITHOUT ANY WARRANTY; without even the implied warranty of
14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15: GNU General Public License for more details.
16:
17: You should have received a copy of the GNU General Public License
18: along with GNU CC; see the file COPYING. If not, write to
1.1.1.3 ! root 19: the Free Software Foundation, 59 Temple Place - Suite 330,
! 20: Boston, MA 02111-1307, USA. */
1.1 root 21:
22:
23: #include <stdio.h>
24: #include "config.h"
25: #include "rtl.h"
26: #include "regs.h"
27: #include "hard-reg-set.h"
28: #include "real.h"
29: #include "insn-config.h"
30: #include "conditions.h"
31: #include "insn-flags.h"
32: #include "output.h"
33: #include "insn-attr.h"
34: #include "flags.h"
35: #include "recog.h"
36: #include "expr.h"
37: #include "obstack.h"
38: #include "tree.h"
39:
40: #define min(A,B) ((A) < (B) ? (A) : (B))
41: #define max(A,B) ((A) > (B) ? (A) : (B))
42:
43: static int unsigned_comparisons_p ();
44: static void output_loadsave_fpregs ();
45: static void output_fpops ();
46: static void init_fpops ();
47:
48: /* Return 1 if the insn using CC0 set by INSN does not contain
49: any unsigned tests applied to the condition codes.
50:
51: Based on `next_insn_tests_no_inequality' in recog.c. */
52:
53: int
54: next_insn_tests_no_unsigned (insn)
55: rtx insn;
56: {
57: register rtx next = next_cc0_user (insn);
58:
59: if (next == 0)
60: {
61: if (find_reg_note (insn, REG_UNUSED, cc0_rtx))
62: return 1;
63: else
64: abort ();
65: }
66:
67: return ((GET_CODE (next) == JUMP_INSN
68: || GET_CODE (next) == INSN
69: || GET_CODE (next) == CALL_INSN)
70: && ! unsigned_comparisons_p (PATTERN (next)));
71: }
72:
73: static int
74: unsigned_comparisons_p (x)
75: rtx x;
76: {
77: register char *fmt;
78: register int len, i;
79: register enum rtx_code code = GET_CODE (x);
80:
81: switch (code)
82: {
83: case REG:
84: case PC:
85: case CC0:
86: case CONST_INT:
87: case CONST_DOUBLE:
88: case CONST:
89: case LABEL_REF:
90: case SYMBOL_REF:
91: return 0;
92:
93: case LTU:
94: case GTU:
95: case LEU:
96: case GEU:
97: return (XEXP (x, 0) == cc0_rtx || XEXP (x, 1) == cc0_rtx);
98: }
99:
100: len = GET_RTX_LENGTH (code);
101: fmt = GET_RTX_FORMAT (code);
102:
103: for (i = 0; i < len; i++)
104: {
105: if (fmt[i] == 'e')
106: {
107: if (unsigned_comparisons_p (XEXP (x, i)))
108: return 1;
109: }
110: else if (fmt[i] == 'E')
111: {
112: register int j;
113: for (j = XVECLEN (x, i) - 1; j >= 0; j--)
114: if (unsigned_comparisons_p (XVECEXP (x, i, j)))
115: return 1;
116: }
117: }
118:
119: return 0;
120: }
121:
122: /* Update the condition code from the insn. Look mostly at the first
123: byte of the machine-specific insn description information.
124:
125: cc_state.value[12] refer to two possible values that might correspond
126: to the CC. We only store register values. */
127:
128: update_cc (body, insn)
129: rtx body;
130: rtx insn;
131: {
132: switch (get_attr_cc (insn))
133: {
134: case CC_NONE:
135: /* Insn does not affect the CC at all. */
136: break;
137:
138: case CC_CHANGE0:
139: /* Insn doesn't affect the CC but does modify operand[0], known to be
140: a register. */
141: if (cc_status.value1 != 0
142: && reg_overlap_mentioned_p (recog_operand[0], cc_status.value1))
143: cc_status.value1 = 0;
144:
145: if (cc_status.value2 != 0
146: && reg_overlap_mentioned_p (recog_operand[0], cc_status.value2))
147: cc_status.value2 = 0;
148:
149: break;
150:
151: case CC_COPY1TO0:
152: /* Insn copies operand[1] to operand[0], both registers, but doesn't
153: affect the CC. */
154: if (cc_status.value1 != 0
155: && reg_overlap_mentioned_p (recog_operand[0], cc_status.value1))
156: cc_status.value1 = 0;
157:
158: if (cc_status.value2 != 0
159: && reg_overlap_mentioned_p (recog_operand[0], cc_status.value2))
160: cc_status.value2 = 0;
161:
162: if (cc_status.value1 != 0
163: && rtx_equal_p (cc_status.value1, recog_operand[1]))
164: cc_status.value2 = recog_operand[0];
165:
166: if (cc_status.value2 != 0
167: && rtx_equal_p (cc_status.value2, recog_operand[1]))
168: cc_status.value1 = recog_operand[0];
169:
170: break;
171:
172: case CC_CLOBBER:
173: /* Insn clobbers CC. */
174: CC_STATUS_INIT;
175: break;
176:
177: case CC_SETS:
178: /* Insn sets CC to recog_operand[0], but overflow is impossible. */
179: CC_STATUS_INIT;
180: cc_status.flags |= CC_NO_OVERFLOW;
181: cc_status.value1 = recog_operand[0];
182: break;
183:
184: case CC_COMPARE:
185: /* Insn is a compare which sets the CC fully. Update CC_STATUS for this
186: compare and mark whether the test will be signed or unsigned. */
187: {
188: register rtx p = PATTERN (insn);
189:
190: CC_STATUS_INIT;
191:
192: if (GET_CODE (p) == PARALLEL)
193: p = XVECEXP (p, 0, 0);
194: cc_status.value1 = SET_SRC (p);
195:
196: if (GET_CODE (SET_SRC (p)) == REG)
197: cc_status.flags |= CC_NO_OVERFLOW;
198: if (! next_insn_tests_no_unsigned (insn))
199: cc_status.flags |= CC_UNSIGNED;
200: }
201: break;
202:
203: case CC_TBIT:
204: /* Insn sets T bit if result is non-zero. Next insn must be branch. */
205: CC_STATUS_INIT;
206: cc_status.flags = CC_IN_TB | CC_NOT_NEGATIVE;
207: break;
208:
209: default:
210: abort ();
211: }
212: }
213:
214: /* Return 1 if a previous compare needs to be re-issued. This will happen
215: if two compares tested the same objects, but one was signed and the
216: other unsigned. OP is the comparison operation being performed. */
217:
218: int
219: restore_compare_p (op)
220: rtx op;
221: {
222: enum rtx_code code = GET_CODE (op);
223:
224: return (((code == GEU || code == LEU || code == GTU || code == LTU)
225: && ! (cc_status.flags & CC_UNSIGNED))
226: || ((code == GE || code == LE || code == GT || code == LT)
227: && (cc_status.flags & CC_UNSIGNED)));
228: }
229:
230: /* Generate the (long) string corresponding to an inline multiply insn.
231: Note that `r10' does not refer to the register r10, but rather to the
232: SCR used as the MQ. */
233: char *
234: output_in_line_mul ()
235: {
236: static char insns[200];
237: int i;
238:
239: strcpy (insns, "s %0,%0\n");
240: strcat (insns, "\tmts r10,%1\n");
241: for (i = 0; i < 16; i++)
242: strcat (insns, "\tm %0,%2\n");
243: strcat (insns, "\tmfs r10,%0");
244:
245: return insns;
246: }
247:
248: /* Returns 1 if OP is a memory reference with an offset from a register within
249: the range specified. The offset must also be a multiple of the size of the
250: mode. */
251:
252: static int
253: memory_offset_in_range_p (op, mode, low, high)
254: register rtx op;
255: enum machine_mode mode;
256: int low, high;
257: {
258: int offset = 0;
259:
260: if (! memory_operand (op, mode))
261: return 0;
262:
263: while (GET_CODE (op) == SUBREG)
264: {
265: offset += SUBREG_WORD (op) * UNITS_PER_WORD;
266: #if BYTES_BIG_ENDIAN
267: offset -= (min (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (op)))
268: - min (UNITS_PER_WORD,
269: GET_MODE_SIZE (GET_MODE (SUBREG_REG (op)))));
270: #endif
271: op = SUBREG_REG (op);
272: }
273:
274: /* We must now have either (mem (reg (x)), (mem (plus (reg (x)) (c))),
275: or a constant pool address. */
276: if (GET_CODE (op) != MEM)
277: abort ();
278:
279: /* Now use the actual mode and get the address. */
280: mode = GET_MODE (op);
281: op = XEXP (op, 0);
282: if (GET_CODE (op) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (op))
283: offset = get_pool_offset (op) + 12;
284: else if (GET_CODE (op) == PLUS)
285: {
286: if (GET_CODE (XEXP (op, 1)) != CONST_INT
287: || ! register_operand (XEXP (op, 0), Pmode))
288: return 0;
289:
290: offset += INTVAL (XEXP (op, 1));
291: }
292:
293: else if (! register_operand (op, Pmode))
294: return 0;
295:
296: return (offset >= low && offset <= high
297: && (offset % GET_MODE_SIZE (mode) == 0));
298: }
299:
300: /* Return 1 if OP is a valid operand for a memory reference insn that can
301: only reference indirect through a register. */
302:
303: int
304: zero_memory_operand (op, mode)
305: rtx op;
306: enum machine_mode mode;
307: {
308: return memory_offset_in_range_p (op, mode, 0, 0);
309: }
310:
311: /* Return 1 if OP is a valid operand for a `short' memory reference insn. */
312:
313: int
314: short_memory_operand (op, mode)
315: rtx op;
316: enum machine_mode mode;
317: {
318: if (mode == VOIDmode)
319: mode = GET_MODE (op);
320:
321: return memory_offset_in_range_p (op, mode, 0,
322: 15 * min (UNITS_PER_WORD,
323: GET_MODE_SIZE (mode)));
324: }
325:
326: /* Returns 1 if OP is a memory reference involving a symbolic constant
327: that is not in the constant pool. */
328:
329: int
330: symbolic_memory_operand (op, mode)
331: register rtx op;
332: enum machine_mode mode;
333: {
334: if (! memory_operand (op, mode))
335: return 0;
336:
337: while (GET_CODE (op) == SUBREG)
338: op = SUBREG_REG (op);
339:
340: if (GET_CODE (op) != MEM)
341: abort ();
342:
343: op = XEXP (op, 0);
344: if (constant_pool_address_operand (op, VOIDmode))
345: return 0;
346: else
347: return romp_symbolic_operand (op, Pmode)
348: || (GET_CODE (op) == PLUS && register_operand (XEXP (op, 0), Pmode)
349: && romp_symbolic_operand (XEXP (op, 1), Pmode));
350: }
351:
352:
353: /* Returns 1 if OP is a constant pool reference to the current function. */
354:
355: int
356: current_function_operand (op, mode)
357: rtx op;
358: enum machine_mode mode;
359: {
360: if (GET_CODE (op) != MEM || GET_CODE (XEXP (op, 0)) != SYMBOL_REF
361: || ! CONSTANT_POOL_ADDRESS_P (XEXP (op, 0)))
362: return 0;
363:
364: op = get_pool_constant (XEXP (op, 0));
365: return (GET_CODE (op) == SYMBOL_REF
366: && ! strcmp (current_function_name, XSTR (op, 0)));
367: }
368:
369: /* Return non-zero if this function is known to have a null epilogue. */
370:
371: int
372: null_epilogue ()
373: {
374: return (reload_completed
375: && first_reg_to_save () == 16
376: && ! romp_pushes_stack ());
377: }
378:
379: /* Returns 1 if OP is the address of a location in the constant pool. */
380:
381: int
382: constant_pool_address_operand (op, mode)
383: rtx op;
384: enum machine_mode mode;
385: {
386: return ((GET_CODE (op) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (op))
387: || (GET_CODE (op) == CONST && GET_CODE (XEXP (op, 0)) == PLUS
388: && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT
389: && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
390: && CONSTANT_POOL_ADDRESS_P (XEXP (XEXP (op, 0), 0))));
391: }
392:
393: /* Returns 1 if OP is either a symbol reference or a sum of a symbol
394: reference and a constant. */
395:
396: int
397: romp_symbolic_operand (op, mode)
398: register rtx op;
399: enum machine_mode mode;
400: {
401: switch (GET_CODE (op))
402: {
403: case SYMBOL_REF:
404: case LABEL_REF:
405: return ! op->integrated;
406:
407: case CONST:
408: op = XEXP (op, 0);
409: return (GET_CODE (XEXP (op, 0)) == SYMBOL_REF
410: || GET_CODE (XEXP (op, 0)) == LABEL_REF)
411: && GET_CODE (XEXP (op, 1)) == CONST_INT;
412:
413: default:
414: return 0;
415: }
416: }
417:
418: /* Returns 1 if OP is a valid constant for the ROMP. */
419:
420: int
421: constant_operand (op, mode)
422: register rtx op;
423: enum machine_mode mode;
424: {
425: switch (GET_CODE (op))
426: {
427: case LABEL_REF:
428: case SYMBOL_REF:
429: case PLUS:
430: case CONST:
431: return romp_symbolic_operand (op,mode);
432:
433: case CONST_INT:
434: return (unsigned int) (INTVAL (op) + 0x8000) < 0x10000
435: || (INTVAL (op) & 0xffff) == 0 || (INTVAL (op) & 0xffff0000) == 0;
436:
437: default:
438: return 0;
439: }
440: }
441:
442: /* Returns 1 if OP is either a constant integer valid for the ROMP or a
443: register. If a register, it must be in the proper mode unless MODE is
444: VOIDmode. */
445:
446: int
447: reg_or_cint_operand (op, mode)
448: register rtx op;
449: enum machine_mode mode;
450: {
451: if (GET_CODE (op) == CONST_INT)
452: return constant_operand (op, mode);
453:
454: return register_operand (op, mode);
455: }
456:
457: /* Return 1 is the operand is either a register or ANY constant integer. */
458:
459: int
460: reg_or_any_cint_operand (op, mode)
461: register rtx op;
462: enum machine_mode mode;
463: {
464: return GET_CODE (op) == CONST_INT || register_operand (op, mode);
465: }
466:
467: /* Return 1 if the operand is either a register or a valid D-type operand. */
468:
469: int
470: reg_or_D_operand (op, mode)
471: register rtx op;
472: enum machine_mode mode;
473: {
474: if (GET_CODE (op) == CONST_INT)
475: return (unsigned) (INTVAL (op) + 0x8000) < 0x10000;
476:
477: return register_operand (op, mode);
478: }
479:
480: /* Return 1 if the operand is either a register or an item that can be
481: used as the operand of an SI add insn. */
482:
483: int
484: reg_or_add_operand (op, mode)
485: register rtx op;
486: enum machine_mode mode;
487: {
488: return reg_or_D_operand (op, mode) || romp_symbolic_operand (op, mode)
489: || (GET_CODE (op) == CONST_INT && (INTVAL (op) & 0xffff) == 0);
490: }
491:
492: /* Return 1 if the operand is either a register or an item that can be
493: used as the operand of a ROMP logical AND insn. */
494:
495: int
496: reg_or_and_operand (op, mode)
497: register rtx op;
498: enum machine_mode mode;
499: {
500: if (reg_or_cint_operand (op, mode))
501: return 1;
502:
503: if (GET_CODE (op) != CONST_INT)
504: return 0;
505:
506: return (INTVAL (op) & 0xffff) == 0xffff
507: || (INTVAL (op) & 0xffff0000) == 0xffff0000;
508: }
509:
510: /* Return 1 if the operand is a register or memory operand. */
511:
512: int
513: reg_or_mem_operand (op, mode)
514: register rtx op;
515: register enum machine_mode mode;
516: {
517: return register_operand (op, mode) || memory_operand (op, mode);
518: }
519:
520: /* Return 1 if the operand is either a register or a memory operand that is
521: not symbolic. */
522:
523: int
524: reg_or_nonsymb_mem_operand (op, mode)
525: register rtx op;
526: enum machine_mode mode;
527: {
528: if (register_operand (op, mode))
529: return 1;
530:
531: if (memory_operand (op, mode) && ! symbolic_memory_operand (op, mode))
532: return 1;
533:
534: return 0;
535: }
536:
537: /* Return 1 if this operand is valid for the ROMP. This is any operand except
538: certain constant integers. */
539:
540: int
541: romp_operand (op, mode)
542: register rtx op;
543: enum machine_mode mode;
544: {
545: if (GET_CODE (op) == CONST_INT)
546: return constant_operand (op, mode);
547:
548: return general_operand (op, mode);
549: }
550:
551: /* Return 1 if the operand is (reg:mode 0). */
552:
553: int
554: reg_0_operand (op, mode)
555: rtx op;
556: enum machine_mode mode;
557: {
558: return ((mode == VOIDmode || mode == GET_MODE (op))
559: && GET_CODE (op) == REG && REGNO (op) == 0);
560: }
561:
562: /* Return 1 if the operand is (reg:mode 15). */
563:
564: int
565: reg_15_operand (op, mode)
566: rtx op;
567: enum machine_mode mode;
568: {
569: return ((mode == VOIDmode || mode == GET_MODE (op))
570: && GET_CODE (op) == REG && REGNO (op) == 15);
571: }
572:
573: /* Return 1 if this is a binary floating-point operation. */
574:
575: int
576: float_binary (op, mode)
577: register rtx op;
578: enum machine_mode mode;
579: {
580: if (mode != VOIDmode && mode != GET_MODE (op))
581: return 0;
582:
583: if (GET_MODE (op) != SFmode && GET_MODE (op) != DFmode)
584: return 0;
585:
586: switch (GET_CODE (op))
587: {
588: case PLUS:
589: case MINUS:
590: case MULT:
591: case DIV:
592: return GET_MODE (XEXP (op, 0)) == GET_MODE (op)
593: && GET_MODE (XEXP (op, 1)) == GET_MODE (op);
594:
595: default:
596: return 0;
597: }
598: }
599:
600: /* Return 1 if this is a unary floating-point operation. */
601:
602: int
603: float_unary (op, mode)
604: register rtx op;
605: enum machine_mode mode;
606: {
607: if (mode != VOIDmode && mode != GET_MODE (op))
608: return 0;
609:
610: if (GET_MODE (op) != SFmode && GET_MODE (op) != DFmode)
611: return 0;
612:
613: return (GET_CODE (op) == NEG || GET_CODE (op) == ABS)
614: && GET_MODE (XEXP (op, 0)) == GET_MODE (op);
615: }
616:
617: /* Return 1 if this is a valid floating-point conversion that can be done
618: as part of an operation by the RT floating-point routines. */
619:
620: int
621: float_conversion (op, mode)
622: register rtx op;
623: enum machine_mode mode;
624: {
625: if (mode != VOIDmode && mode != GET_MODE (op))
626: return 0;
627:
628: switch (GET_CODE (op))
629: {
630: case FLOAT_TRUNCATE:
631: return GET_MODE (op) == SFmode && GET_MODE (XEXP (op, 0)) == DFmode;
632:
633: case FLOAT_EXTEND:
634: return GET_MODE (op) == DFmode && GET_MODE (XEXP (op, 0)) == SFmode;
635:
636: case FLOAT:
637: return ((GET_MODE (XEXP (op, 0)) == SImode
638: || GET_CODE (XEXP (op, 0)) == CONST_INT)
639: && (GET_MODE (op) == SFmode || GET_MODE (op) == DFmode));
640:
641: case FIX:
642: return ((GET_MODE (op) == SImode
643: || GET_CODE (XEXP (op, 0)) == CONST_INT)
644: && (GET_MODE (XEXP (op, 0)) == SFmode
645: || GET_MODE (XEXP (op, 0)) == DFmode));
646:
647: default:
648: return 0;
649: }
650: }
651:
652: /* Print an operand. Recognize special options, documented below. */
653:
654: void
655: print_operand (file, x, code)
656: FILE *file;
657: rtx x;
658: char code;
659: {
660: int i;
661:
662: switch (code)
663: {
664: case 'B':
665: /* Byte number (const/8) */
666: if (GET_CODE (x) != CONST_INT)
667: output_operand_lossage ("invalid %%B value");
668:
669: fprintf (file, "%d", INTVAL (x) / 8);
670: break;
671:
672: case 'L':
673: /* Low order 16 bits of constant. */
674: if (GET_CODE (x) != CONST_INT)
675: output_operand_lossage ("invalid %%L value");
676:
677: fprintf (file, "%d", INTVAL (x) & 0xffff);
678: break;
679:
680: case 's':
681: /* Null or "16" depending on whether the constant is greater than 16. */
682: if (GET_CODE (x) != CONST_INT)
683: output_operand_lossage ("invalid %%s value");
684:
685: if (INTVAL (x) >= 16)
686: fprintf (file, "16");
687:
688: break;
689:
690: case 'S':
691: /* For shifts: 's' will have given the half. Just give the amount
692: within 16. */
693: if (GET_CODE (x) != CONST_INT)
694: output_operand_lossage ("invalid %%S value");
695:
696: fprintf (file, "%d", INTVAL (x) & 15);
697: break;
698:
699: case 'b':
700: /* The number of a single bit set or cleared, mod 16. Note that the ROMP
701: numbers bits with the high-order bit 31. */
702: if (GET_CODE (x) != CONST_INT)
703: output_operand_lossage ("invalid %%b value");
704:
705: if ((i = exact_log2 (INTVAL (x))) >= 0)
706: fprintf (file, "%d", (31 - i) % 16);
707: else if ((i = exact_log2 (~ INTVAL (x))) >= 0)
708: fprintf (file, "%d", (31 - i) % 16);
709: else
710: output_operand_lossage ("invalid %%b value");
711:
712: break;
713:
714: case 'h':
715: /* "l" or "u" depending on which half of the constant is zero. */
716: if (GET_CODE (x) != CONST_INT)
717: output_operand_lossage ("invalid %%h value");
718:
719: if ((INTVAL (x) & 0xffff0000) == 0)
720: fprintf (file, "l");
721: else if ((INTVAL (x) & 0xffff) == 0)
722: fprintf (file, "u");
723: else
724: output_operand_lossage ("invalid %%h value");
725:
726: break;
727:
728: case 'H':
729: /* Upper or lower half, depending on which half is zero. */
730: if (GET_CODE (x) != CONST_INT)
731: output_operand_lossage ("invalid %%H value");
732:
733: if ((INTVAL (x) & 0xffff0000) == 0)
734: fprintf (file, "%d", INTVAL (x) & 0xffff);
735: else if ((INTVAL (x) & 0xffff) == 0)
736: fprintf (file, "%d", (INTVAL (x) >> 16) & 0xffff);
737: else
738: output_operand_lossage ("invalid %%H value");
739:
740: break;
741:
742: case 'z':
743: /* Write two characters:
744: 'lo' if the high order part is all ones
745: 'lz' if the high order part is all zeros
746: 'uo' if the low order part is all ones
747: 'uz' if the low order part is all zeros
748: */
749: if (GET_CODE (x) != CONST_INT)
750: output_operand_lossage ("invalid %%z value");
751:
752: if ((INTVAL (x) & 0xffff0000) == 0)
753: fprintf (file, "lz");
754: else if ((INTVAL (x) & 0xffff0000) == 0xffff0000)
755: fprintf (file, "lo");
756: else if ((INTVAL (x) & 0xffff) == 0)
757: fprintf (file, "uz");
758: else if ((INTVAL (x) & 0xffff) == 0xffff)
759: fprintf (file, "uo");
760: else
761: output_operand_lossage ("invalid %%z value");
762:
763: break;
764:
765: case 'Z':
766: /* Upper or lower half, depending on which is non-zero or not
767: all ones. Must be consistent with 'z' above. */
768: if (GET_CODE (x) != CONST_INT)
769: output_operand_lossage ("invalid %%Z value");
770:
771: if ((INTVAL (x) & 0xffff0000) == 0
772: || (INTVAL (x) & 0xffff0000) == 0xffff0000)
773: fprintf (file, "%d", INTVAL (x) & 0xffff);
774: else if ((INTVAL (x) & 0xffff) == 0 || (INTVAL (x) & 0xffff) == 0xffff)
775: fprintf (file, "%d", (INTVAL (x) >> 16) & 0xffff);
776: else
777: output_operand_lossage ("invalid %%Z value");
778:
779: break;
780:
781: case 'k':
782: /* Same as 'z', except the trailing 'o' or 'z' is not written. */
783: if (GET_CODE (x) != CONST_INT)
784: output_operand_lossage ("invalid %%k value");
785:
786: if ((INTVAL (x) & 0xffff0000) == 0
787: || (INTVAL (x) & 0xffff0000) == 0xffff0000)
788: fprintf (file, "l");
789: else if ((INTVAL (x) & 0xffff) == 0
790: || (INTVAL (x) & 0xffff) == 0xffff)
791: fprintf (file, "u");
792: else
793: output_operand_lossage ("invalid %%k value");
794:
795: break;
796:
797: case 't':
798: /* Similar to 's', except that we write 'h' or 'u'. */
799: if (GET_CODE (x) != CONST_INT)
800: output_operand_lossage ("invalid %%k value");
801:
802: if (INTVAL (x) < 16)
803: fprintf (file, "u");
804: else
805: fprintf (file, "l");
806: break;
807:
808: case 'M':
809: /* For memory operations, write 's' if the operand is a short
810: memory operand. */
811: if (short_memory_operand (x, VOIDmode))
812: fprintf (file, "s");
813: break;
814:
815: case 'N':
816: /* Like 'M', but check for zero memory offset. */
817: if (zero_memory_operand (x, VOIDmode))
818: fprintf (file, "s");
819: break;
820:
821: case 'O':
822: /* Write low-order part of DImode or DFmode. Supported for MEM
823: and REG only. */
824: if (GET_CODE (x) == REG)
825: fprintf (file, "%s", reg_names[REGNO (x) + 1]);
826: else if (GET_CODE (x) == MEM)
827: print_operand (file, gen_rtx (MEM, GET_MODE (x),
828: plus_constant (XEXP (x, 0), 4)), 0);
829: else
830: abort ();
831: break;
832:
833: case 'C':
834: /* Offset in constant pool for constant pool address. */
835: if (! constant_pool_address_operand (x, VOIDmode))
836: abort ();
837: if (GET_CODE (x) == SYMBOL_REF)
838: fprintf (file, "%d", get_pool_offset (x) + 12);
839: else
840: /* Must be (const (plus (symbol_ref) (const_int))) */
841: fprintf (file, "%d",
842: (get_pool_offset (XEXP (XEXP (x, 0), 0)) + 12
843: + INTVAL (XEXP (XEXP (x, 0), 1))));
844: break;
845:
846: case 'j':
847: /* Branch opcode. Check for condition in test bit for eq/ne. */
848: switch (GET_CODE (x))
849: {
850: case EQ:
851: if (cc_status.flags & CC_IN_TB)
852: fprintf (file, "ntb");
853: else
854: fprintf (file, "eq");
855: break;
856:
857: case NE:
858: if (cc_status.flags & CC_IN_TB)
859: fprintf (file, "tb");
860: else
861: fprintf (file, "ne");
862: break;
863:
864: case GT:
865: case GTU:
866: fprintf (file, "h");
867: break;
868:
869: case LT:
870: case LTU:
871: fprintf (file, "l");
872: break;
873:
874: case GE:
875: case GEU:
876: fprintf (file, "he");
877: break;
878:
879: case LE:
880: case LEU:
881: fprintf (file, "le");
882: break;
883:
884: default:
885: output_operand_lossage ("invalid %%j value");
886: }
887: break;
888:
889: case 'J':
890: /* Reversed branch opcode. */
891: switch (GET_CODE (x))
892: {
893: case EQ:
894: if (cc_status.flags & CC_IN_TB)
895: fprintf (file, "tb");
896: else
897: fprintf (file, "ne");
898: break;
899:
900: case NE:
901: if (cc_status.flags & CC_IN_TB)
902: fprintf (file, "ntb");
903: else
904: fprintf (file, "eq");
905: break;
906:
907: case GT:
908: case GTU:
909: fprintf (file, "le");
910: break;
911:
912: case LT:
913: case LTU:
914: fprintf (file, "he");
915: break;
916:
917: case GE:
918: case GEU:
919: fprintf (file, "l");
920: break;
921:
922: case LE:
923: case LEU:
924: fprintf (file, "h");
925: break;
926:
927: default:
928: output_operand_lossage ("invalid %%j value");
929: }
930: break;
931:
932: case '.':
933: /* Output nothing. Used as delimiter in, e.g., "mc%B1%.3 " */
934: break;
935:
936: case '#':
937: /* Output 'x' if this insn has a delay slot, else nothing. */
938: if (dbr_sequence_length ())
939: fprintf (file, "x");
940: break;
941:
942: case 0:
943: if (GET_CODE (x) == REG)
944: fprintf (file, "%s", reg_names[REGNO (x)]);
945: else if (GET_CODE (x) == MEM)
946: {
947: if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
948: && current_function_operand (x, Pmode))
949: fprintf (file, "r14");
950: else
951: output_address (XEXP (x, 0));
952: }
953: else
954: output_addr_const (file, x);
955: break;
956:
957: default:
958: output_operand_lossage ("invalid %%xn code");
959: }
960: }
961:
962: /* This page contains routines that are used to determine what the function
963: prologue and epilogue code will do and write them out. */
964:
965: /* Return the first register that is required to be saved. 16 if none. */
966:
967: int
968: first_reg_to_save()
969: {
970: int first_reg;
971:
972: /* Find lowest numbered live register. */
973: for (first_reg = 6; first_reg <= 15; first_reg++)
974: if (regs_ever_live[first_reg])
975: break;
976:
977: /* If we think that we do not have to save r14, see if it will be used
978: to be sure. */
979: if (first_reg > 14 && romp_using_r14 ())
980: first_reg = 14;
981:
982: return first_reg;
983: }
984:
985: /* Compute the size of the save area in the stack, including the space for
986: the first four incoming arguments. */
987:
988: int
989: romp_sa_size ()
990: {
991: int size;
992: int i;
993:
994: /* We have the 4 words corresponding to the arguments passed in registers,
995: 4 reserved words, space for static chain, general register save area,
996: and floating-point save area. */
997: size = 4 + 4 + 1 + (16 - first_reg_to_save ());
998:
999: /* The documentation says we have to leave 18 words in the save area if
1000: any floating-point registers at all are saved, not the three words
1001: per register you might otherwise expect. */
1002: for (i = 2 + (TARGET_FP_REGS != 0); i <= 7; i++)
1003: if (regs_ever_live[i + 17])
1004: {
1005: size += 18;
1006: break;
1007: }
1008:
1009: return size * 4;
1010: }
1011:
1012: /* Return non-zero if this function makes calls or has fp operations
1013: (which are really calls). */
1014:
1015: int
1016: romp_makes_calls ()
1017: {
1018: rtx insn;
1019:
1020: for (insn = get_insns (); insn; insn = next_insn (insn))
1021: {
1022: if (GET_CODE (insn) == CALL_INSN)
1023: return 1;
1024: else if (GET_CODE (insn) == INSN)
1025: {
1026: rtx body = PATTERN (insn);
1027:
1028: if (GET_CODE (body) != USE && GET_CODE (body) != CLOBBER
1029: && GET_CODE (body) != ADDR_VEC
1030: && GET_CODE (body) != ADDR_DIFF_VEC
1031: && get_attr_type (insn) == TYPE_FP)
1032: return 1;
1033: }
1034: }
1035:
1036: return 0;
1037: }
1038:
1039: /* Return non-zero if this function will use r14 as a pointer to its
1040: constant pool. */
1041:
1042: int
1043: romp_using_r14 ()
1044: {
1045: /* If we are debugging, profiling, have a non-empty constant pool, or
1046: call a function, we need r14. */
1047: return (write_symbols != NO_DEBUG || profile_flag || get_pool_size () != 0
1048: || romp_makes_calls ());
1049: }
1050:
1051: /* Return non-zero if this function needs to push space on the stack. */
1052:
1053: int
1054: romp_pushes_stack ()
1055: {
1056: /* We need to push the stack if a frame pointer is needed (because the
1057: stack might be dynamically adjusted), if we are debugging, if the
1058: total required size is more than 100 bytes, or if we make calls. */
1059:
1060: return (frame_pointer_needed || write_symbols != NO_DEBUG
1061: || (romp_sa_size () + get_frame_size ()) > 100
1062: || romp_makes_calls ());
1063: }
1064:
1065: /* Write function prologue.
1066:
1067: We compute the size of the fixed area required as follows:
1068:
1069: We always allocate 4 words for incoming arguments, 4 word reserved, 1
1070: word for static link, as many words as required for general register
1071: save area, plus 2 words for each FP reg 2-7 that must be saved. */
1072:
1073: void
1074: output_prolog (file, size)
1075: FILE *file;
1076: int size;
1077: {
1078: int first_reg;
1079: int reg_save_offset;
1080: int fp_save = size + current_function_outgoing_args_size;
1081:
1082: init_fpops ();
1083:
1084: /* Add in fixed size plus output argument area. */
1085: size += romp_sa_size () + current_function_outgoing_args_size;
1086:
1087: /* Compute first register to save and perform the save operation if anything
1088: needs to be saved. */
1089: first_reg = first_reg_to_save();
1090: reg_save_offset = - (4 + 4 + 1 + (16 - first_reg)) * 4;
1091: if (first_reg == 15)
1092: fprintf (file, "\tst r15,%d(r1)\n", reg_save_offset);
1093: else if (first_reg < 16)
1094: fprintf (file, "\tstm r%d,%d(r1)\n", first_reg, reg_save_offset);
1095:
1096: /* Set up pointer to data area if it is needed. */
1097: if (romp_using_r14 ())
1098: fprintf (file, "\tcas r14,r0,r0\n");
1099:
1100: /* Set up frame pointer if needed. */
1101: if (frame_pointer_needed)
1102: fprintf (file, "\tcal r13,-%d(r1)\n", romp_sa_size () + 64);
1103:
1104: /* Push stack if neeeded. There are a couple of ways of doing this. */
1105: if (romp_pushes_stack ())
1106: {
1107: if (size >= 32768)
1108: {
1109: if (size >= 65536)
1110: {
1111: fprintf (file, "\tcau r0,%d(r0)\n", size >> 16);
1112: fprintf (file, "\toil r0,r0,%d\n", size & 0xffff);
1113: }
1114: else
1115: fprintf (file, "\tcal16 r0,%d(r0)\n", size);
1116: fprintf (file, "\ts r1,r0\n");
1117: }
1118: else
1119: fprintf (file, "\tcal r1,-%d(r1)\n", size);
1120: }
1121:
1122: /* Save floating-point registers. */
1123: output_loadsave_fpregs (file, USE,
1124: plus_constant (stack_pointer_rtx, fp_save));
1125: }
1.1.1.2 root 1126:
1127: /* Output the offset information used by debuggers.
1128: This is the exactly the total_size value of output_epilog
1129: which is added to the frame pointer. However the value in the debug
1130: table is encoded in a space-saving way as follows:
1131:
1132: The first byte contains two fields: a 2-bit size field and the first
1133: 6 bits of an offset value. The 2-bit size field is in the high-order
1134: position and specifies how many subsequent bytes follow after
1135: this one. An offset value is at most 4-bytes long.
1136:
1137: The last 6 bits of the first byte initialize the offset value. In many
1138: cases where procedures have small local storage, this is enough and, in
1139: this case, the high-order size field is zero so the byte can (almost) be
1140: used as is (see below). Thus, the byte value of 0x0d is encodes a offset
1141: size of 13 words, or 52 bytes.
1142:
1143: For procedures with a local space larger than 60 bytes, the 6 bits
1144: are the high-order 6 bits. The remaining bytes follow as necessary,
1145: in Big Endian order. Thus, the short value of 16907 (= 16384+523)
1146: encodes an offset of 2092 bytes (523 words).
1147:
1148: The total offset value is in words (not bytes), so the final value has to
1149: be multiplied by 4 before it can be used in address computations by a
1150: debugger. */
1151:
1152: void
1153: output_encoded_offset (file, reg_offset)
1154: FILE *file;
1155: unsigned reg_offset;
1156: {
1157: /* Convert the offset value to 4-byte words rather than bytes. */
1158: reg_offset = (reg_offset + 3) / 4;
1.1 root 1159:
1.1.1.2 root 1160: /* Now output 1-4 bytes in encoded form. */
1161: if (reg_offset < (1 << 6))
1162: /* Fits into one byte */
1163: fprintf (file, "\t.byte %d\n", reg_offset);
1164: else if (reg_offset < (1 << (6 + 8)))
1165: /* Fits into two bytes */
1166: fprintf (file, "\t.short %d\n", (1 << (6 + 8)) + reg_offset);
1167: else if (reg_offset < (1 << (6 + 8 + 8)))
1168: {
1169: /* Fits in three bytes */
1170: fprintf (file, "\t.byte %d\n", (2 << 6) + (reg_offset >> ( 6+ 8)));
1171: fprintf (file, "\t.short %d\n", reg_offset % (1 << (6 + 8)));
1172: }
1173: else
1174: {
1175: /* Use 4 bytes. */
1176: fprintf (file, "\t.short %d", (3 << (6 + 8)) + (reg_offset >> (6 + 8)));
1177: fprintf (file, "\t.short %d\n", reg_offset % (1 << (6 + 8)));
1178: }
1179: }
1180:
1.1 root 1181: /* Write function epilogue. */
1182:
1183: void
1184: output_epilog (file, size)
1185: FILE *file;
1186: int size;
1187: {
1188: int first_reg = first_reg_to_save();
1189: int pushes_stack = romp_pushes_stack ();
1190: int reg_save_offset = - ((16 - first_reg) + 1 + 4 + 4) * 4;
1191: int total_size = (size + romp_sa_size ()
1192: + current_function_outgoing_args_size);
1193: int fp_save = size + current_function_outgoing_args_size;
1194: int long_frame = total_size >= 32768;
1195: rtx insn = get_last_insn ();
1196: int write_code = 1;
1197:
1198: int nargs = 0; /* words of arguments */
1199: tree argptr;
1200:
1201: /* Compute the number of words of arguments. Since this is just for
1202: the traceback table, we ignore arguments that don't have a size or
1203: don't have a fixed size. */
1204:
1205: for (argptr = DECL_ARGUMENTS (current_function_decl);
1206: argptr; argptr = TREE_CHAIN (argptr))
1207: {
1208: int this_size = int_size_in_bytes (TREE_TYPE (argptr));
1209:
1210: if (this_size > 0)
1211: nargs += (this_size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
1212: }
1213:
1214: /* If the last insn was a BARRIER, we don't have to write anything except
1215: the trace table. */
1216: if (GET_CODE (insn) == NOTE)
1217: insn = prev_nonnote_insn (insn);
1218: if (insn && GET_CODE (insn) == BARRIER)
1219: write_code = 0;
1220:
1221: /* Restore floating-point registers. */
1222: if (write_code)
1223: output_loadsave_fpregs (file, CLOBBER,
1224: gen_rtx (PLUS, Pmode, gen_rtx (REG, Pmode, 1),
1225: gen_rtx (CONST_INT, VOIDmode, fp_save)));
1226:
1227: /* If we push the stack and do not have size > 32K, adjust the register
1228: save location to the current position of sp. Otherwise, if long frame,
1229: restore sp from fp. */
1230: if (pushes_stack && ! long_frame)
1231: reg_save_offset += total_size;
1232: else if (long_frame && write_code)
1233: fprintf (file, "\tcal r1,%d(r13)\n", romp_sa_size () + 64);
1234:
1235: /* Restore registers. */
1236: if (first_reg == 15 && write_code)
1237: fprintf (file, "\tl r15,%d(r1)\n", reg_save_offset);
1238: else if (first_reg < 16 && write_code)
1239: fprintf (file, "\tlm r%d,%d(r1)\n", first_reg, reg_save_offset);
1240: if (first_reg == 16) first_reg = 0;
1241:
1242: /* Handle popping stack, if needed and write debug table entry. */
1243: if (pushes_stack)
1244: {
1245: if (write_code)
1246: {
1247: if (long_frame)
1248: fprintf (file, "\tbr r15\n");
1249: else
1250: fprintf (file, "\tbrx r15\n\tcal r1,%d(r1)\n", total_size);
1251: }
1.1.1.2 root 1252:
1253: /* Table header (0xdf), usual-type stack frame (0x07),
1254: table header (0xdf), and first register saved.
1255:
1256: The final 0x08 means that there is a byte following this one
1257: describing the number of parameter words and the register used as
1258: stack pointer.
1259:
1260: If GCC passed floating-point parameters in floating-point registers,
1261: it would be necessary to change the final byte from 0x08 to 0x0c.
1262: Also an additional entry byte would be need to be emitted to specify
1263: the first floating-point register.
1264:
1265: (See also Section 11 (Trace Tables) in ``IBM/4.3 Linkage Convention,''
1266: pages IBM/4.3-PSD:5-7 of Volume III of the IBM Academic Operating
1267: System Manual dated July 1987.) */
1268:
1.1 root 1269: fprintf (file, "\t.long 0x%x\n", 0xdf07df08 + first_reg * 0x10);
1270:
1271: if (nargs > 15) nargs = 15;
1.1.1.2 root 1272:
1273: /* The number of parameter words and the register used as the stack
1274: pointer (encoded here as r1).
1275:
1276: Note: The MetWare Hich C Compiler R2.1y actually gets this wrong;
1277: it erroneously lists r13 but uses r1 as the stack too. But a bug in
1278: dbx 1.5 nullifies this mistake---most of the time.
1279: (Dbx retrieves the value of r13 saved on the stack which is often
1280: the value of r1 before the call.) */
1281:
1282: fprintf (file, "\t.byte 0x%x1\n", nargs);
1283: output_encoded_offset (file, total_size);
1.1 root 1284: }
1285: else
1286: {
1287: if (write_code)
1288: fprintf (file, "\tbr r15\n");
1.1.1.2 root 1289:
1290: /* Table header (0xdf), no stack frame (0x02),
1291: table header (0xdf) and no parameters saved (0x00).
1292:
1293: If GCC passed floating-point parameters in floating-point registers,
1294: it might be necessary to change the final byte from 0x00 to 0x04.
1295: Also a byte would be needed to specify the first floating-point
1296: register. */
1.1 root 1297: fprintf (file, "\t.long 0xdf02df00\n");
1298: }
1299:
1300: /* Output any pending floating-point operations. */
1301: output_fpops (file);
1302: }
1303:
1304: /* For the ROMP we need to make new SYMBOL_REFs for the actual name of a
1305: called routine. To keep them unique we maintain a hash table of all
1306: that have been created so far. */
1307:
1308: struct symref_hashent {
1309: rtx symref; /* Created SYMBOL_REF rtx. */
1310: struct symref_hashent *next; /* Next with same hash code. */
1311: };
1312:
1313: #define SYMHASHSIZE 151
1314: #define HASHBITS 65535
1315:
1316: /* Define the hash table itself. */
1317:
1318: static struct symref_hashent *symref_hash_table[SYMHASHSIZE];
1319:
1320: /* Given a name (allocatable in temporary storage), return a SYMBOL_REF
1321: for the name. The rtx is allocated from the current rtl_obstack, while
1322: the name string is allocated from the permanent obstack. */
1323: rtx
1324: get_symref (name)
1325: register char *name;
1326: {
1327: extern struct obstack permanent_obstack;
1328: register char *sp = name;
1329: unsigned int hash = 0;
1330: struct symref_hashent *p, **last_p;
1331:
1332: /* Compute the hash code for the string. */
1333: while (*sp)
1334: hash = (hash << 4) + *sp++;
1335:
1336: /* Search for a matching entry in the hash table, keeping track of the
1337: insertion location as we do so. */
1338: hash = (hash & HASHBITS) % SYMHASHSIZE;
1339: for (last_p = &symref_hash_table[hash], p = *last_p;
1340: p; last_p = &p->next, p = *last_p)
1341: if (strcmp (name, XSTR (p->symref, 0)) == 0)
1342: break;
1343:
1344: /* If couldn't find matching SYMBOL_REF, make a new one. */
1345: if (p == 0)
1346: {
1347: /* Ensure SYMBOL_REF will stay around. */
1348: end_temporary_allocation ();
1349: p = *last_p = (struct symref_hashent *)
1350: permalloc (sizeof (struct symref_hashent));
1351: p->symref = gen_rtx (SYMBOL_REF, Pmode,
1352: obstack_copy0 (&permanent_obstack,
1353: name, strlen (name)));
1354: p->next = 0;
1355: resume_temporary_allocation ();
1356: }
1357:
1358: return p->symref;
1359: }
1360:
1361: /* Validate the precision of a floating-point operation.
1362:
1363: We merge conversions from integers and between floating-point modes into
1364: the insn. However, this must not effect the desired precision of the
1365: insn. The RT floating-point system uses the widest of the operand modes.
1366: If this should be a double-precision insn, ensure that one operand
1367: passed to the floating-point processor has double mode.
1368:
1369: Note that since we don't check anything if the mode is single precision,
1370: it, strictly speaking, isn't necessary to call this for those insns.
1371: However, we do so in case something else needs to be checked in the
1372: future.
1373:
1374: This routine returns 1 if the operation is OK. */
1375:
1376: int
1377: check_precision (opmode, op1, op2)
1378: enum machine_mode opmode;
1379: rtx op1, op2;
1380: {
1381: if (opmode == SFmode)
1382: return 1;
1383:
1384: /* If operand is not a conversion from an integer mode or an extension from
1385: single-precision, it must be a double-precision value. */
1386: if (GET_CODE (op1) != FLOAT && GET_CODE (op1) != FLOAT_EXTEND)
1387: return 1;
1388:
1389: if (op2 && GET_CODE (op2) != FLOAT && GET_CODE (op2) != FLOAT_EXTEND)
1390: return 1;
1391:
1392: return 0;
1393: }
1394:
1395: /* Floating-point on the RT is done by creating an operation block in the data
1396: area that describes the operation. If two floating-point operations are the
1397: same in a single function, they can use the same block.
1398:
1399: These routines are responsible for managing these blocks. */
1400:
1401: /* Structure to describe a floating-point operation. */
1402:
1403: struct fp_op {
1404: struct fp_op *next_same_hash; /* Next op with same hash code. */
1405: struct fp_op *next_in_mem; /* Next op in memory. */
1406: int mem_offset; /* Offset from data area. */
1407: short size; /* Size of block in bytes. */
1408: short noperands; /* Number of operands in block. */
1409: rtx ops[3]; /* RTL for operands. */
1410: enum rtx_code opcode; /* Operation being performed. */
1411: };
1412:
1413: /* Size of hash table. */
1414: #define FP_HASH_SIZE 101
1415:
1416: /* Hash table of floating-point operation blocks. */
1417: static struct fp_op *fp_hash_table[FP_HASH_SIZE];
1418:
1419: /* First floating-point block in data area. */
1420: static struct fp_op *first_fpop;
1421:
1422: /* Last block in data area so far. */
1423: static struct fp_op *last_fpop_in_mem;
1424:
1425: /* Subroutine number in file, to get unique "LF" labels. */
1426: static int subr_number = 0;
1427:
1428: /* Current word offset in data area (includes header and any constant pool). */
1429: int data_offset;
1430:
1431: /* Compute hash code for an RTX used in floating-point. */
1432:
1433: static unsigned int
1434: hash_rtx (x)
1435: register rtx x;
1436: {
1437: register unsigned int hash = (((int) GET_CODE (x) << 10)
1438: + ((int) GET_MODE (x) << 20));
1439: register int i;
1440: register char *fmt = GET_RTX_FORMAT (GET_CODE (x));
1441:
1442: for (i = 0; i < GET_RTX_LENGTH (GET_CODE (x)); i++)
1443: if (fmt[i] == 'e')
1444: hash += hash_rtx (XEXP (x, i));
1445: else if (fmt[i] == 'u')
1.1.1.3 ! root 1446: hash += (unsigned HOST_WIDE_INT) XEXP (x, i);
1.1 root 1447: else if (fmt[i] == 'i')
1448: hash += XINT (x, i);
1449: else if (fmt[i] == 's')
1.1.1.3 ! root 1450: hash += (unsigned HOST_WIDE_INT) XSTR (x, i);
1.1 root 1451:
1452: return hash;
1453: }
1454:
1455: /* Given an operation code and up to three operands, return a character string
1456: corresponding to the code to emit to branch to a floating-point operation
1457: block. INSN is provided to see if the delay slot has been filled or not.
1458:
1459: A new floating-point operation block is created if this operation has not
1460: been seen before. */
1461:
1462: char *
1463: output_fpop (code, op0, op1, op2, insn)
1464: enum rtx_code code;
1465: rtx op0, op1, op2;
1466: rtx insn;
1467: {
1468: static char outbuf[40];
1469: unsigned int hash, hash0, hash1, hash2;
1470: int size, i;
1471: register struct fp_op *fpop, *last_fpop;
1472: int dyadic = (op2 != 0);
1473: enum machine_mode opmode;
1474: int noperands;
1475: rtx tem;
1476: unsigned int tem_hash;
1477: int fr0_avail = 0;
1478:
1479: /* Compute hash code for each operand. If the operation is commutative,
1480: put the one with the smaller hash code first. This will make us see
1481: more operations as identical. */
1482: hash0 = op0 ? hash_rtx (op0) : 0;
1483: hash1 = op1 ? hash_rtx (op1) : 0;
1484: hash2 = op2 ? hash_rtx (op2) : 0;
1485:
1486: if (hash0 > hash1 && code == EQ)
1487: {
1488: tem = op0; op0 = op1; op1 = tem;
1489: tem_hash = hash0; hash0 = hash1; hash1 = tem_hash;
1490: }
1491: else if (hash1 > hash2 && (code == PLUS || code == MULT))
1492: {
1493: tem = op1; op1 = op2; op2 = tem;
1494: tem_hash = hash1; hash1 = hash2; hash2 = tem_hash;
1495: }
1496:
1497: /* If operation is commutative and the first and third operands are equal,
1498: swap the second and third operands. Note that we must consider two
1499: operands equal if they are the same register even if different modes. */
1500: if (op2 && (code == PLUS || code == MULT)
1501: && (rtx_equal_p (op0, op2)
1502: || (GET_CODE (op0) == REG && GET_CODE (op2) == REG
1503: && REGNO (op0) == REGNO (op2))))
1504: {
1505: tem = op1; op1 = op2; op2 = tem;
1506: tem_hash = hash1; hash1 = hash2; hash2 = tem_hash;
1507: }
1508:
1509: /* If the first and second operands are the same, merge them. Don't do this
1510: for SFmode or SImode in general registers because this triggers a bug in
1511: the RT fp code. */
1512: if (op1 && rtx_equal_p (op0, op1)
1513: && code != EQ && code != GE && code != SET
1514: && ((GET_MODE (op1) != SFmode && GET_MODE (op1) != SImode)
1515: || GET_CODE (op0) != REG || FP_REGNO_P (REGNO (op0))))
1516: {
1517: op1 = op2;
1518: op2 = 0;
1519: }
1520:
1521: noperands = 1 + (op1 != 0) + (op2 != 0);
1522:
1523: /* Compute hash code for entire expression and see if operation block
1524: already exists. */
1525: hash = ((int) code << 13) + (hash0 << 2) + (hash1 << 1) + hash2;
1526:
1527: hash %= FP_HASH_SIZE;
1528: for (fpop = fp_hash_table[hash], last_fpop = 0;
1529: fpop;
1530: last_fpop = fpop, fpop = fpop->next_same_hash)
1531: if (fpop->opcode == code && noperands == fpop->noperands
1532: && (op0 == 0 || rtx_equal_p (op0, fpop->ops[0]))
1533: && (op1 == 0 || rtx_equal_p (op1, fpop->ops[1]))
1534: && (op2 == 0 || rtx_equal_p (op2, fpop->ops[2])))
1535: goto win;
1536:
1537: /* We have never seen this operation before. */
1538: fpop = (struct fp_op *) oballoc (sizeof (struct fp_op));
1539: fpop->mem_offset = data_offset;
1540: fpop->opcode = code;
1541: fpop->noperands = noperands;
1542: fpop->ops[0] = op0;
1543: fpop->ops[1] = op1;
1544: fpop->ops[2] = op2;
1545:
1546: /* Compute the size using the rules in Appendix A of the RT Linkage
1547: Convention (4.3/RT-PSD:5) manual. These rules are a bit ambiguous,
1548: but if we guess wrong, it will effect only efficiency, not correctness. */
1549:
1550: /* Size = 24 + 32 for each non-fp (or fr7) */
1551: size = 24;
1552: if (op0 && (GET_CODE (op0) != REG
1553: || ! FP_REGNO_P (REGNO (op0)) || REGNO (op0) == 23))
1554: size += 32;
1555:
1556: if (op1 && (GET_CODE (op1) != REG
1557: || ! FP_REGNO_P (REGNO (op1)) || REGNO (op1) == 23))
1558: size += 32;
1559:
1560: if (op2 && (GET_CODE (op2) != REG
1561: || ! FP_REGNO_P (REGNO (op2)) || REGNO (op2) == 23))
1562: size += 32;
1563:
1564: /* Size + 12 for each conversion. First get operation mode. */
1565: if ((op0 && GET_MODE (op0) == DFmode)
1566: || (op1 && GET_MODE (op1) == DFmode)
1567: || (op2 && GET_MODE (op2) == DFmode))
1568: opmode = DFmode;
1569: else
1570: opmode = SFmode;
1571:
1572: if (op0 && GET_MODE (op0) != opmode)
1573: size += 12;
1574: if (op1 && GET_MODE (op1) != opmode)
1575: size += 12;
1576: if (op2 && GET_MODE (op2) != opmode)
1577: size += 12;
1578:
1579: /* 12 more if first and third operand types not the same. */
1580: if (op2 && GET_MODE (op0) != GET_MODE (op2))
1581: size += 12;
1582:
1583: /* CMP and CMPT need additional. Also, compute size of save/restore here. */
1584: if (code == EQ)
1585: size += 32;
1586: else if (code == GE)
1587: size += 64;
1588: else if (code == USE || code == CLOBBER)
1589: {
1590: /* 34 + 24 for each additional register plus 8 if fr7 saved. (We
1591: call it 36 because we need to keep the block length a multiple
1592: of four. */
1593: size = 36 - 24;
1594: for (i = 0; i <= 7; i++)
1595: if (INTVAL (op0) & (1 << (7-i)))
1596: size += 24 + 8 * (i == 7);
1597: }
1598:
1599: /* We provide no general-purpose scratch registers. */
1600: size +=16;
1601:
1602: /* No floating-point scratch registers are provided. Compute extra
1603: length due to this. This logic is that shown in the referenced
1604: appendix. */
1605:
1606: i = 0;
1607: if (op0 && GET_CODE (op0) == REG && FP_REGNO_P (REGNO (op0)))
1608: i++;
1609: if (op1 && GET_CODE (op1) == REG && FP_REGNO_P (REGNO (op1)))
1610: i++;
1611: if (op2 && GET_CODE (op2) == REG && FP_REGNO_P (REGNO (op2)))
1612: i++;
1613:
1614: if ((op0 == 0 || GET_CODE (op0) != REG || REGNO(op0) != 17)
1615: && (op1 == 0 || GET_CODE (op1) != REG || REGNO(op1) != 17)
1616: && (op2 == 0 || GET_CODE (op2) != REG || REGNO(op2) != 17))
1617: fr0_avail = 1;
1618:
1619: if (dyadic)
1620: {
1621: if (i == 0)
1622: size += fr0_avail ? 64 : 112;
1623: else if (fpop->noperands == 2 && i == 1)
1624: size += fr0_avail ? 0 : 64;
1625: else if (fpop->noperands == 3)
1626: {
1627: if (GET_CODE (op0) == REG && FP_REGNO_P (REGNO (op0))
1628: && GET_CODE (op2) == REG && FP_REGNO_P (REGNO (op2)))
1629: {
1630: if (REGNO (op0) == REGNO (op2))
1631: #if 1
1632: /* This triggers a bug on the RT. */
1633: abort ();
1634: #else
1635: size += fr0_avail ? 0 : 64;
1636: #endif
1637: }
1638: else
1639: {
1640: i = 0;
1641: if (GET_CODE (op0) == REG && FP_REGNO_P (REGNO (op0)))
1642: i++;
1643: if (GET_CODE (op2) == REG && FP_REGNO_P (REGNO (op2)))
1644: i++;
1645: if (i == 0)
1646: size += fr0_avail ? 64 : 112;
1647: else if (i == 1)
1648: size += fr0_avail ? 0 : 64;
1649: }
1650: }
1651: }
1652: else if (code != USE && code != CLOBBER
1653: && (GET_CODE (op0) != REG || ! FP_REGNO_P (REGNO (op0))))
1654: size += 64;
1655:
1656: if (! TARGET_FULL_FP_BLOCKS)
1657: {
1658: /* If we are not to pad the blocks, just compute its actual length. */
1659: size = 12; /* Header + opcode */
1660: if (code == USE || code == CLOBBER)
1661: size += 2;
1662: else
1663: {
1664: if (op0) size += 2;
1665: if (op1) size += 2;
1666: if (op2) size += 2;
1667: }
1668:
1669: /* If in the middle of a word, round. */
1670: if (size % UNITS_PER_WORD)
1671: size += 2;
1672:
1673: /* Handle any immediates. */
1674: if (code != USE && code != CLOBBER && op0 && GET_CODE (op0) != REG)
1675: size += 4;
1676: if (op1 && GET_CODE (op1) != REG)
1677: size += 4;
1678: if (op2 && GET_CODE (op2) != REG)
1679: size += 4;
1680:
1681: if (code != USE && code != CLOBBER &&
1682: op0 && GET_CODE (op0) == CONST_DOUBLE && GET_MODE (op0) == DFmode)
1683: size += 4;
1684: if (op1 && GET_CODE (op1) == CONST_DOUBLE && GET_MODE (op1) == DFmode)
1685: size += 4;
1686: if (op2 && GET_CODE (op2) == CONST_DOUBLE && GET_MODE (op2) == DFmode)
1687: size += 4;
1688: }
1689:
1690: /* Done with size computation! Chain this in. */
1691: fpop->size = size;
1692: data_offset += size / UNITS_PER_WORD;
1693: fpop->next_in_mem = 0;
1694: fpop->next_same_hash = 0;
1695:
1696: if (last_fpop_in_mem)
1697: last_fpop_in_mem->next_in_mem = fpop;
1698: else
1699: first_fpop = fpop;
1700: last_fpop_in_mem = fpop;
1701:
1702: if (last_fpop)
1703: last_fpop->next_same_hash = fpop;
1704: else
1705: fp_hash_table[hash] = fpop;
1706:
1707: win:
1708: /* FPOP describes the operation to be performed. Return a string to branch
1709: to it. */
1710: if (fpop->mem_offset < 32768 / UNITS_PER_WORD)
1711: sprintf (outbuf, "cal r15,%d(r14)\n\tbalr%s r15,r15",
1712: fpop->mem_offset * UNITS_PER_WORD,
1713: dbr_sequence_length () ? "x" : "");
1714: else
1715: sprintf (outbuf, "get r15,$L%dF%d\n\tbalr%s r15,r15",
1716: subr_number, fpop->mem_offset * UNITS_PER_WORD,
1717: dbr_sequence_length () ? "x" : "");
1718: return outbuf;
1719: }
1720:
1721: /* If necessary, output a floating-point operation to save or restore all
1722: floating-point registers.
1723:
1724: file is the file to write the operation to, CODE is USE for save, CLOBBER
1725: for restore, and ADDR is the address of the same area, as RTL. */
1726:
1727: static void
1728: output_loadsave_fpregs (file, code, addr)
1729: FILE *file;
1730: enum rtx_code code;
1731: rtx addr;
1732: {
1733: register int i;
1734: register int mask = 0;
1735:
1736: for (i = 2 + (TARGET_FP_REGS != 0); i <= 7; i++)
1737: if (regs_ever_live[i + 17])
1738: mask |= 1 << (7 - i);
1739:
1740: if (mask)
1741: fprintf (file, "\t%s\n",
1742: output_fpop (code, gen_rtx (CONST_INT, VOIDmode, mask),
1743: gen_rtx (MEM, Pmode, addr),
1744: 0, const0_rtx));
1745:
1746: }
1747:
1748: /* Output any floating-point operations at the end of the routine. */
1749:
1750: static void
1751: output_fpops (file)
1752: FILE *file;
1753: {
1754: register struct fp_op *fpop;
1755: register int size_so_far;
1756: register int i;
1757: rtx immed[3];
1758:
1759: if (first_fpop == 0)
1760: return;
1761:
1762: data_section ();
1763:
1764: ASM_OUTPUT_ALIGN (file, 2);
1765:
1766: for (fpop = first_fpop; fpop; fpop = fpop->next_in_mem)
1767: {
1768: if (fpop->mem_offset < 32768 / UNITS_PER_WORD)
1769: fprintf (file, "# data area offset = %d\n",
1770: fpop->mem_offset * UNITS_PER_WORD);
1771: else
1772: fprintf (file, "L%dF%d:\n",
1773: subr_number, fpop->mem_offset * UNITS_PER_WORD);
1774:
1775: fprintf (file, "\tcas r0,r15,r0\n");
1776: fprintf (file, "\t.long FPGLUE\n");
1777: switch (fpop->opcode)
1778: {
1779: case USE:
1780: fprintf (file, "\t.byte 0x1d\t# STOREM\n");
1781: break;
1782: case CLOBBER:
1783: fprintf (file, "\t.byte 0x0f\t# LOADM\n");
1784: break;
1785: case ABS:
1786: fprintf (file, "\t.byte 0x00\t# ABS\n");
1787: break;
1788: case PLUS:
1789: fprintf (file, "\t.byte 0x02\t# ADD\n");
1790: break;
1791: case EQ:
1792: fprintf (file, "\t.byte 0x07\t# CMP\n");
1793: break;
1794: case GE:
1795: fprintf (file, "\t.byte 0x08\t# CMPT\n");
1796: break;
1797: case DIV:
1798: fprintf (file, "\t.byte 0x0c\t# DIV\n");
1799: break;
1800: case SET:
1801: fprintf (file, "\t.byte 0x14\t# MOVE\n");
1802: break;
1803: case MULT:
1804: fprintf (file, "\t.byte 0x15\t# MUL\n");
1805: break;
1806: case NEG:
1807: fprintf (file, "\t.byte 0x16\t# NEG\n");
1808: break;
1809: case SQRT:
1810: fprintf (file, "\t.byte 0x1c\t# SQRT\n");
1811: break;
1812: case MINUS:
1813: fprintf (file, "\t.byte 0x1e\t# SUB\n");
1814: break;
1815: default:
1816: abort ();
1817: }
1818:
1819: fprintf (file, "\t.byte %d\n", fpop->noperands);
1820: fprintf (file, "\t.short 0x8001\n");
1821:
1822: if ((fpop->ops[0] == 0
1823: || GET_CODE (fpop->ops[0]) != REG || REGNO(fpop->ops[0]) != 17)
1824: && (fpop->ops[1] == 0 || GET_CODE (fpop->ops[1]) != REG
1825: || REGNO(fpop->ops[1]) != 17)
1826: && (fpop->ops[2] == 0 || GET_CODE (fpop->ops[2]) != REG
1827: || REGNO(fpop->ops[2]) != 17))
1828: fprintf (file, "\t.byte %d, 0x80\n", fpop->size);
1829: else
1830: fprintf (file, "\t.byte %d, 0\n", fpop->size);
1831: size_so_far = 12;
1832: for (i = 0; i < fpop->noperands; i++)
1833: {
1834: register int type;
1835: register int opbyte;
1836: register char *desc0;
1837: char desc1[50];
1838:
1839: immed[i] = 0;
1840: switch (GET_MODE (fpop->ops[i]))
1841: {
1842: case SImode:
1843: case VOIDmode:
1844: desc0 = "int";
1845: type = 0;
1846: break;
1847: case SFmode:
1848: desc0 = "float";
1849: type = 2;
1850: break;
1851: case DFmode:
1852: desc0 = "double";
1853: type = 3;
1854: break;
1855: default:
1856: abort ();
1857: }
1858:
1859: switch (GET_CODE (fpop->ops[i]))
1860: {
1861: case REG:
1862: strcpy(desc1, reg_names[REGNO (fpop->ops[i])]);
1863: if (FP_REGNO_P (REGNO (fpop->ops[i])))
1864: {
1865: type += 0x10;
1866: opbyte = REGNO (fpop->ops[i]) - 17;
1867: }
1868: else
1869: {
1870: type += 0x00;
1871: opbyte = REGNO (fpop->ops[i]);
1872: if (type == 3)
1873: opbyte = (opbyte << 4) + opbyte + 1;
1874: }
1875: break;
1876:
1877: case MEM:
1878: type += 0x30;
1879: if (GET_CODE (XEXP (fpop->ops[i], 0)) == PLUS)
1880: {
1881: immed[i] = XEXP (XEXP (fpop->ops[i], 0), 1);
1882: opbyte = REGNO (XEXP (XEXP (fpop->ops[i], 0), 0));
1883: if (GET_CODE (immed[i]) == CONST_INT)
1884: sprintf (desc1, "%d(%s)", INTVAL (immed[i]),
1885: reg_names[opbyte]);
1886: else
1887: sprintf (desc1, "<memory> (%s)", reg_names[opbyte]);
1888: }
1889: else if (GET_CODE (XEXP (fpop->ops[i], 0)) == REG)
1890: {
1891: opbyte = REGNO (XEXP (fpop->ops[i], 0));
1892: immed[i] = const0_rtx;
1893: sprintf (desc1, "(%s)", reg_names[opbyte]);
1894: }
1895: else
1896: {
1897: immed[i] = XEXP (fpop->ops[i], 0);
1898: opbyte = 0;
1899: sprintf(desc1, "<memory>");
1900: }
1901: break;
1902:
1903: case CONST_INT:
1904: case CONST_DOUBLE:
1905: case CONST:
1906: case SYMBOL_REF:
1907: case LABEL_REF:
1908: type += 0x20;
1909: opbyte = 0;
1910: immed[i] = fpop->ops[i];
1911: desc1[0] = '$';
1912: desc1[1] = '\0';
1913: break;
1914:
1915: default:
1916: abort ();
1917: }
1918:
1919: /* Save/restore is special. */
1920: if (i == 0 && (fpop->opcode == USE || fpop->opcode == CLOBBER))
1921: type = 0xff, opbyte = INTVAL (fpop->ops[0]), immed[i] = 0;
1922:
1923: fprintf (file, "\t.byte 0x%x,0x%x # (%s) %s\n",
1924: type, opbyte, desc0, desc1);
1925:
1926: size_so_far += 2;
1927: }
1928:
1929: /* If in the middle of a word, round. */
1930: if (size_so_far % UNITS_PER_WORD)
1931: {
1932: fprintf (file, "\t.space 2\n");
1933: size_so_far += 2;
1934: }
1935:
1936: for (i = 0; i < fpop->noperands; i++)
1937: if (immed[i])
1938: switch (GET_MODE (immed[i]))
1939: {
1940: case SImode:
1941: case VOIDmode:
1942: size_so_far += 4;
1943: fprintf (file, "\t.long ");
1944: output_addr_const (file, immed[i]);
1945: fprintf (file, "\n");
1946: break;
1947:
1948: case DFmode:
1949: size_so_far += 4;
1950: case SFmode:
1951: size_so_far += 4;
1952: if (GET_CODE (immed[i]) == CONST_DOUBLE)
1953: {
1954: union real_extract u;
1955:
1.1.1.3 ! root 1956: bcopy ((char *) &CONST_DOUBLE_LOW (immed[i]),
! 1957: (char *) &u, sizeof u);
1.1 root 1958: if (GET_MODE (immed[i]) == DFmode)
1959: ASM_OUTPUT_DOUBLE (file, u.d);
1960: else
1961: ASM_OUTPUT_FLOAT (file, u.d);
1962: }
1963: else
1964: abort ();
1965: break;
1966:
1967: default:
1968: abort ();
1969: }
1970:
1971: if (size_so_far != fpop->size)
1972: {
1973: if (TARGET_FULL_FP_BLOCKS)
1974: fprintf (file, "\t.space %d\n", fpop->size - size_so_far);
1975: else
1976: abort ();
1977: }
1978: }
1979:
1980: /* Update for next subroutine. */
1981: subr_number++;
1982: text_section ();
1983: }
1984:
1985: /* Initialize floating-point operation table. */
1986:
1987: static void
1988: init_fpops()
1989: {
1990: register int i;
1991:
1992: first_fpop = last_fpop_in_mem = 0;
1993: for (i = 0; i < FP_HASH_SIZE; i++)
1994: fp_hash_table[i] = 0;
1995: }
1.1.1.2 root 1996:
1997: /* Return the offset value of an automatic variable (N_LSYM) having
1998: the given offset. Basically, we correct by going from a frame pointer to
1999: stack pointer value.
2000: */
2001:
2002: int
2003: romp_debugger_auto_correction(offset)
2004: int offset;
2005: {
2006: int fp_to_sp;
2007:
2008: /* We really want to go from STACK_POINTER_REGNUM to
2009: FRAME_POINTER_REGNUM, but this isn't defined. So go the other
2010: direction and negate. */
2011: INITIAL_ELIMINATION_OFFSET (FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM,
2012: fp_to_sp);
2013:
2014: /* The offset value points somewhere between the frame pointer and
2015: the stack pointer. What is up from the frame pointer is down from the
2016: stack pointer. Therefore the negation in the offset value too. */
2017:
2018: return -(offset+fp_to_sp+4);
2019: }
2020:
2021: /* Return the offset value of an argument having
2022: the given offset. Basically, we correct by going from a arg pointer to
2023: stack pointer value. */
2024:
2025: int
2026: romp_debugger_arg_correction (offset)
2027: int offset;
2028: {
2029: int fp_to_argp;
2030:
2031: INITIAL_ELIMINATION_OFFSET (ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM,
2032: fp_to_argp);
2033:
2034: /* Actually, something different happens if offset is from a floating-point
2035: register argument, but we don't handle it here. */
2036:
2037: return (offset - fp_to_argp);
2038: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.