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