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