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