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