2003-12-26 Guilhem Lavaux <guilhem@kaffe.org>
[official-gcc.git] / gcc / config / i370 / i370.c
blob2cfe4fe3269013f889dad8d0c4c01b2c5f545723
1 /* Subroutines for insn-output.c for System/370.
2 Copyright (C) 1989, 1993, 1995, 1997, 1998, 1999, 2000, 2002
3 Free Software Foundation, Inc.
4 Contributed by Jan Stein (jan@cd.chalmers.se).
5 Modified for OS/390 LanguageEnvironment C by Dave Pitts (dpitts@cozx.com)
6 Hacked for Linux-ELF/390 by Linas Vepstas (linas@linas.org)
8 This file is part of GCC.
10 GCC is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
13 any later version.
15 GCC is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with GCC; see the file COPYING. If not, write to
22 the Free Software Foundation, 59 Temple Place - Suite 330,
23 Boston, MA 02111-1307, USA. */
25 #include "config.h"
26 #include "system.h"
27 #include "coretypes.h"
28 #include "tm.h"
29 #include "rtl.h"
30 #include "tree.h"
31 #include "regs.h"
32 #include "hard-reg-set.h"
33 #include "real.h"
34 #include "insn-config.h"
35 #include "conditions.h"
36 #include "output.h"
37 #include "insn-attr.h"
38 #include "function.h"
39 #include "expr.h"
40 #include "flags.h"
41 #include "recog.h"
42 #include "toplev.h"
43 #include "cpplib.h"
44 #include "tm_p.h"
45 #include "target.h"
46 #include "target-def.h"
48 extern FILE *asm_out_file;
50 /* Label node. This structure is used to keep track of labels
51 on the various pages in the current routine.
52 The label_id is the numeric ID of the label,
53 The label_page is the page on which it actually appears,
54 The first_ref_page is the page on which the true first ref appears.
55 The label_addr is an estimate of its location in the current routine,
56 The label_first & last_ref are estimates of where the earliest and
57 latest references to this label occur. */
59 typedef struct label_node
61 struct label_node *label_next;
62 int label_id;
63 int label_page;
64 int first_ref_page;
66 int label_addr;
67 int label_first_ref;
68 int label_last_ref;
70 label_node_t;
72 /* Is 1 when a label has been generated and the base register must be reloaded. */
73 int mvs_need_base_reload = 0;
75 /* Current function starting base page. */
76 int function_base_page;
78 /* Length of the current page code. */
79 int mvs_page_code;
81 /* Length of the current page literals. */
82 int mvs_page_lit;
84 /* Current function name. */
85 char *mvs_function_name = 0;
87 /* Current function name length. */
88 size_t mvs_function_name_length = 0;
90 /* Page number for multi-page functions. */
91 int mvs_page_num = 0;
93 /* Label node list anchor. */
94 static label_node_t *label_anchor = 0;
96 /* Label node free list anchor. */
97 static label_node_t *free_anchor = 0;
99 /* Assembler source file descriptor. */
100 static FILE *assembler_source = 0;
102 static label_node_t * mvs_get_label (int);
103 static void i370_label_scan (void);
104 #ifdef TARGET_HLASM
105 static bool i370_hlasm_assemble_integer (rtx, unsigned int, int);
106 static void i370_globalize_label (FILE *, const char *);
107 #endif
108 static void i370_output_function_prologue (FILE *, HOST_WIDE_INT);
109 static void i370_output_function_epilogue (FILE *, HOST_WIDE_INT);
110 static void i370_file_start (void);
111 static void i370_file_end (void);
113 #ifdef LONGEXTERNAL
114 static int mvs_hash_alias (const char *);
115 #endif
116 static void i370_internal_label (FILE *, const char *, unsigned long);
117 static bool i370_rtx_costs (rtx, int, int, int *);
119 /* ===================================================== */
120 /* defines and functions specific to the HLASM assembler */
121 #ifdef TARGET_HLASM
123 #define MVS_HASH_PRIME 999983
124 #if HOST_CHARSET == HOST_CHARSET_EBCDIC
125 #define MVS_SET_SIZE 256
126 #else
127 #define MVS_SET_SIZE 128
128 #endif
130 #ifndef MAX_MVS_LABEL_SIZE
131 #define MAX_MVS_LABEL_SIZE 8
132 #endif
134 #define MAX_LONG_LABEL_SIZE 255
136 /* Alias node, this structure is used to keep track of aliases to external
137 variables. The IBM assembler allows an alias to an external name
138 that is longer that 8 characters; but only once per assembly.
139 Also, this structure stores the #pragma map info. */
140 typedef struct alias_node
142 struct alias_node *alias_next;
143 int alias_emitted;
144 char alias_name [MAX_MVS_LABEL_SIZE + 1];
145 char real_name [MAX_LONG_LABEL_SIZE + 1];
147 alias_node_t;
149 /* Alias node list anchor. */
150 static alias_node_t *alias_anchor = 0;
152 /* Define the length of the internal MVS function table. */
153 #define MVS_FUNCTION_TABLE_LENGTH 32
155 /* C/370 internal function table. These functions use non-standard linkage
156 and must handled in a special manner. */
157 static const char *const mvs_function_table[MVS_FUNCTION_TABLE_LENGTH] =
159 #if HOST_CHARSET == HOST_CHARSET_EBCDIC /* Changed for EBCDIC collating sequence */
160 "ceil", "edc_acos", "edc_asin", "edc_atan", "edc_ata2", "edc_cos",
161 "edc_cosh", "edc_erf", "edc_erfc", "edc_exp", "edc_gamm", "edc_lg10",
162 "edc_log", "edc_sin", "edc_sinh", "edc_sqrt", "edc_tan", "edc_tanh",
163 "fabs", "floor", "fmod", "frexp", "hypot", "jn",
164 "j0", "j1", "ldexp", "modf", "pow", "yn",
165 "y0", "y1"
166 #else
167 "ceil", "edc_acos", "edc_asin", "edc_ata2", "edc_atan", "edc_cos",
168 "edc_cosh", "edc_erf", "edc_erfc", "edc_exp", "edc_gamm", "edc_lg10",
169 "edc_log", "edc_sin", "edc_sinh", "edc_sqrt", "edc_tan", "edc_tanh",
170 "fabs", "floor", "fmod", "frexp", "hypot", "j0",
171 "j1", "jn", "ldexp", "modf", "pow", "y0",
172 "y1", "yn"
173 #endif
176 #endif /* TARGET_HLASM */
177 /* ===================================================== */
180 /* Initialize the GCC target structure. */
181 #ifdef TARGET_HLASM
182 #undef TARGET_ASM_BYTE_OP
183 #define TARGET_ASM_BYTE_OP NULL
184 #undef TARGET_ASM_ALIGNED_HI_OP
185 #define TARGET_ASM_ALIGNED_HI_OP NULL
186 #undef TARGET_ASM_ALIGNED_SI_OP
187 #define TARGET_ASM_ALIGNED_SI_OP NULL
188 #undef TARGET_ASM_INTEGER
189 #define TARGET_ASM_INTEGER i370_hlasm_assemble_integer
190 #undef TARGET_ASM_GLOBALIZE_LABEL
191 #define TARGET_ASM_GLOBALIZE_LABEL i370_globalize_label
192 #endif
194 #undef TARGET_ASM_FUNCTION_PROLOGUE
195 #define TARGET_ASM_FUNCTION_PROLOGUE i370_output_function_prologue
196 #undef TARGET_ASM_FUNCTION_EPILOGUE
197 #define TARGET_ASM_FUNCTION_EPILOGUE i370_output_function_epilogue
198 #undef TARGET_ASM_FILE_START
199 #define TARGET_ASM_FILE_START i370_file_start
200 #undef TARGET_ASM_FILE_END
201 #define TARGET_ASM_FILE_END i370_file_end
202 #undef TARGET_ASM_INTERNAL_LABEL
203 #define TARGET_ASM_INTERNAL_LABEL i370_internal_label
204 #undef TARGET_RTX_COSTS
205 #define TARGET_RTX_COSTS i370_rtx_costs
207 struct gcc_target targetm = TARGET_INITIALIZER;
209 /* Set global variables as needed for the options enabled. */
211 void
212 override_options ()
214 /* We're 370 floating point, not IEEE floating point. */
215 memset (real_format_for_mode, 0, sizeof real_format_for_mode);
216 REAL_MODE_FORMAT (SFmode) = &i370_single_format;
217 REAL_MODE_FORMAT (DFmode) = &i370_double_format;
220 /* ===================================================== */
221 /* The following three routines are used to determine whther
222 forward branch is on this page, or is a far jump. We use
223 the "length" attr on an insn [(set_atter "length" "4")]
224 to store the largest possible code length that insn
225 could have. This gives us a hint of the address of a
226 branch destination, and from that, we can work out
227 the length of the jump, and whether its on page or not.
230 /* Return the destination address of a branch. */
233 i370_branch_dest (branch)
234 rtx branch;
236 rtx dest = SET_SRC (PATTERN (branch));
237 int dest_uid;
238 int dest_addr;
240 /* first, compute the estimated address of the branch target */
241 if (GET_CODE (dest) == IF_THEN_ELSE)
242 dest = XEXP (dest, 1);
243 dest = XEXP (dest, 0);
244 dest_uid = INSN_UID (dest);
245 dest_addr = INSN_ADDRESSES (dest_uid);
247 /* next, record the address of this insn as the true addr of first ref */
249 label_node_t *lp;
250 rtx label = JUMP_LABEL (branch);
251 int labelno = CODE_LABEL_NUMBER (label);
253 if (!label || CODE_LABEL != GET_CODE (label)) abort ();
255 lp = mvs_get_label (labelno);
256 if (-1 == lp -> first_ref_page) lp->first_ref_page = mvs_page_num;
258 return dest_addr;
262 i370_branch_length (insn)
263 rtx insn;
265 int here, there;
266 here = INSN_ADDRESSES (INSN_UID (insn));
267 there = i370_branch_dest (insn);
268 return (there - here);
273 i370_short_branch (insn)
274 rtx insn;
276 int base_offset;
278 base_offset = i370_branch_length(insn);
279 if (0 > base_offset)
281 base_offset += mvs_page_code;
283 else
285 /* avoid bumping into lit pool; use 2x to estimate max possible lits */
286 base_offset *= 2;
287 base_offset += mvs_page_code + mvs_page_lit;
290 /* make a conservative estimate of room left on page */
291 if ((4060 >base_offset) && ( 0 < base_offset)) return 1;
292 return 0;
295 /* The i370_label_scan() routine is supposed to loop over
296 all labels and label references in a compilation unit,
297 and determine whether all label refs appear on the same
298 code page as the label. If they do, then we can avoid
299 a reload of the base register for that label.
301 Note that the instruction addresses used here are only
302 approximate, and make the sizes of the jumps appear
303 farther apart then they will actually be. This makes
304 this code far more conservative than it needs to be.
307 #define I370_RECORD_LABEL_REF(label,addr) { \
308 label_node_t *lp; \
309 int labelno = CODE_LABEL_NUMBER (label); \
310 lp = mvs_get_label (labelno); \
311 if (addr < lp -> label_first_ref) lp->label_first_ref = addr; \
312 if (addr > lp -> label_last_ref) lp->label_last_ref = addr; \
315 static void
316 i370_label_scan ()
318 rtx insn;
319 label_node_t *lp;
320 int tablejump_offset = 0;
322 for (insn = get_insns(); insn; insn = NEXT_INSN(insn))
324 int here = INSN_ADDRESSES (INSN_UID (insn));
325 enum rtx_code code = GET_CODE(insn);
327 /* ??? adjust for tables embedded in the .text section that
328 * the compiler didn't take into account */
329 here += tablejump_offset;
330 INSN_ADDRESSES (INSN_UID (insn)) = here;
332 /* check to see if this insn is a label ... */
333 if (CODE_LABEL == code)
335 int labelno = CODE_LABEL_NUMBER (insn);
337 lp = mvs_get_label (labelno);
338 lp -> label_addr = here;
339 #if 0
340 /* Supposedly, labels are supposed to have circular
341 lists of label-refs that reference them,
342 setup in flow.c, but this does not appear to be the case. */
343 rtx labelref = LABEL_REFS (insn);
344 rtx ref = labelref;
347 rtx linsn = CONTAINING_INSN(ref);
348 ref = LABEL_NEXTREF(ref);
349 } while (ref && (ref != labelref));
350 #endif
352 else
353 if (JUMP_INSN == code)
355 rtx label = JUMP_LABEL (insn);
357 /* If there is no label for this jump, then this
358 had better be a ADDR_VEC or an ADDR_DIFF_VEC
359 and there had better be a vector of labels. */
360 if (!label)
362 int j;
363 rtx body = PATTERN (insn);
364 if (ADDR_VEC == GET_CODE(body))
366 for (j=0; j < XVECLEN (body, 0); j++)
368 rtx lref = XVECEXP (body, 0, j);
369 if (LABEL_REF != GET_CODE (lref)) abort ();
370 label = XEXP (lref,0);
371 if (CODE_LABEL != GET_CODE (label)) abort ();
372 tablejump_offset += 4;
373 here += 4;
374 I370_RECORD_LABEL_REF(label,here);
376 /* finished with the vector go do next insn */
377 continue;
379 else
380 if (ADDR_DIFF_VEC == GET_CODE(body))
382 /* XXX hack alert.
383 Right now, we leave this as a no-op, but strictly speaking,
384 this is incorrect. It is possible that a table-jump
385 driven off of a relative address could take us off-page,
386 to a place where we need to reload the base reg. So really,
387 we need to examing both labels, and compare thier values
388 to the current basereg value.
390 More generally, this brings up a troubling issue overall:
391 what happens if a tablejump is split across two pages? I do
392 not beleive that this case is handled correctly at all, and
393 can only lead to horrible results if this were to occur.
395 However, the current situation is not any worse than it was
396 last week, and so we punt for now. */
398 debug_rtx (insn);
399 for (j=0; j < XVECLEN (body, 0); j++)
402 /* finished with the vector go do next insn */
403 continue;
405 else
407 /* XXX hack alert.
408 Compiling the exception handling (L_eh) in libgcc2.a will trip
409 up right here, with something that looks like
410 (set (pc) (mem:SI (plus:SI (reg/v:SI 1 r1) (const_int 4))))
411 {indirect_jump}
412 I'm not sure of what leads up to this, but it looks like
413 the makings of a long jump which will surely get us into trouble
414 because the base & page registers don't get reloaded. For now
415 I'm not sure of what to do ... again we punt ... we are not worse
416 off than yesterday. */
418 /* print_rtl_single (stdout, insn); */
419 debug_rtx (insn);
420 /* abort(); */
421 continue;
424 else
426 /* At this point, this jump_insn had better be a plain-old
427 ordinary one, grap the label id and go */
428 if (CODE_LABEL != GET_CODE (label)) abort ();
429 I370_RECORD_LABEL_REF(label,here);
433 /* Sometimes, we take addresses of labels and use them
434 as instruction operands ... these show up as REG_NOTES */
435 else
436 if (INSN == code)
438 if ('i' == GET_RTX_CLASS (code))
440 rtx note;
441 for (note = REG_NOTES (insn); note; note = XEXP(note,1))
443 if (REG_LABEL == REG_NOTE_KIND(note))
445 rtx label = XEXP (note,0);
446 if (!label || CODE_LABEL != GET_CODE (label)) abort ();
448 I370_RECORD_LABEL_REF(label,here);
456 /* ===================================================== */
458 /* Emit reload of base register if indicated. This is to eliminate multiple
459 reloads when several labels are generated pointing to the same place
460 in the code.
462 The page table is written at the end of the function.
463 The entries in the page table look like
464 .LPGT0: // PGT0 EQU *
465 .long .LPG0 // DC A(PG0)
466 .long .LPG1 // DC A(PG1)
467 while the prologue generates
468 L r4,=A(.LPGT0)
470 Note that this paging scheme breaks down if a single subroutine
471 has more than about 10MB of code in it ... as long as humans write
472 code, this shouldn't be a problem ...
475 void
476 check_label_emit ()
478 if (mvs_need_base_reload)
480 mvs_need_base_reload = 0;
482 mvs_page_code += 4;
483 fprintf (assembler_source, "\tL\t%d,%d(,%d)\n",
484 BASE_REGISTER, (mvs_page_num - function_base_page) * 4,
485 PAGE_REGISTER);
489 /* Add the label to the current page label list. If a free element is available
490 it will be used for the new label. Otherwise, a label element will be
491 allocated from memory.
492 ID is the label number of the label being added to the list. */
494 static label_node_t *
495 mvs_get_label (id)
496 int id;
498 label_node_t *lp;
500 /* first, lets see if we already go one, if so, use that. */
501 for (lp = label_anchor; lp; lp = lp->label_next)
503 if (lp->label_id == id) return lp;
506 /* not found, get a new one */
507 if (free_anchor)
509 lp = free_anchor;
510 free_anchor = lp->label_next;
512 else
514 lp = (label_node_t *) xmalloc (sizeof (label_node_t));
517 /* initialize for new label */
518 lp->label_id = id;
519 lp->label_page = -1;
520 lp->label_next = label_anchor;
521 lp->label_first_ref = 2000123123;
522 lp->label_last_ref = -1;
523 lp->label_addr = -1;
524 lp->first_ref_page = -1;
525 label_anchor = lp;
527 return lp;
530 void
531 mvs_add_label (id)
532 int id;
534 label_node_t *lp;
535 int fwd_distance;
537 lp = mvs_get_label (id);
538 lp->label_page = mvs_page_num;
540 /* OK, we just saw the label. Determine if this label
541 * needs a reload of the base register */
542 if ((-1 != lp->first_ref_page) &&
543 (lp->first_ref_page != mvs_page_num))
545 /* Yep; the first label_ref was on a different page. */
546 mvs_need_base_reload ++;
547 return;
550 /* Hmm. Try to see if the estimated address of the last
551 label_ref is on the current page. If it is, then we
552 don't need a base reg reload. Note that this estimate
553 is very conservatively handled; we'll tend to have
554 a good bit more reloads than actually needed. Someday,
555 we should tighten the estimates (which are driven by
556 the (set_att "length") insn attibute.
558 Currently, we estimate that number of page literals
559 same as number of insns, which is a vast overestimate,
560 esp that the estimate of each insn size is its max size. */
562 /* if latest ref comes before label, we are clear */
563 if (lp->label_last_ref < lp->label_addr) return;
565 fwd_distance = lp->label_last_ref - lp->label_addr;
567 if (mvs_page_code + 2 * fwd_distance + mvs_page_lit < 4060) return;
569 mvs_need_base_reload ++;
572 /* Check to see if the label is in the list and in the current
573 page. If not found, we have to make worst case assumption
574 that label will be on a different page, and thus will have to
575 generate a load and branch on register. This is rather
576 ugly for forward-jumps, but what can we do? For backward
577 jumps on the same page we can branch directly to address.
578 ID is the label number of the label being checked. */
581 mvs_check_label (id)
582 int id;
584 label_node_t *lp;
586 for (lp = label_anchor; lp; lp = lp->label_next)
588 if (lp->label_id == id)
590 if (lp->label_page == mvs_page_num)
592 return 1;
594 else
596 return 0;
600 return 0;
603 /* Get the page on which the label sits. This will be used to
604 determine is a register reload is really needed. */
606 #if 0
608 mvs_get_label_page(int id)
610 label_node_t *lp;
612 for (lp = label_anchor; lp; lp = lp->label_next)
614 if (lp->label_id == id)
615 return lp->label_page;
617 return -1;
619 #endif
621 /* The label list for the current page freed by linking the list onto the free
622 label element chain. */
624 void
625 mvs_free_label_list ()
628 if (label_anchor)
630 label_node_t *last_lp = label_anchor;
631 while (last_lp->label_next) last_lp = last_lp->label_next;
632 last_lp->label_next = free_anchor;
633 free_anchor = label_anchor;
635 label_anchor = 0;
638 /* ====================================================================== */
639 /* If the page size limit is reached a new code page is started, and the base
640 register is set to it. This page break point is counted conservatively,
641 most literals that have the same value are collapsed by the assembler.
642 True is returned when a new page is started.
643 FILE is the assembler output file descriptor.
644 CODE is the length, in bytes, of the instruction to be emitted.
645 LIT is the length of the literal to be emitted. */
647 #ifdef TARGET_HLASM
649 mvs_check_page (file, code, lit)
650 FILE *file;
651 int code, lit;
653 if (file)
654 assembler_source = file;
656 if (mvs_page_code + code + mvs_page_lit + lit > MAX_MVS_PAGE_LENGTH)
658 fprintf (assembler_source, "\tB\tPGE%d\n", mvs_page_num);
659 fprintf (assembler_source, "\tDS\t0F\n");
660 fprintf (assembler_source, "\tLTORG\n");
661 fprintf (assembler_source, "\tDS\t0F\n");
662 fprintf (assembler_source, "PGE%d\tEQU\t*\n", mvs_page_num);
663 fprintf (assembler_source, "\tDROP\t%d\n", BASE_REGISTER);
664 mvs_page_num++;
665 /* Safe to use BASR not BALR, since we are
666 * not switching addressing mode here ... */
667 fprintf (assembler_source, "\tBASR\t%d,0\n", BASE_REGISTER);
668 fprintf (assembler_source, "PG%d\tEQU\t*\n", mvs_page_num);
669 fprintf (assembler_source, "\tUSING\t*,%d\n", BASE_REGISTER);
670 mvs_page_code = code;
671 mvs_page_lit = lit;
672 return 1;
674 mvs_page_code += code;
675 mvs_page_lit += lit;
676 return 0;
678 #endif /* TARGET_HLASM */
681 #ifdef TARGET_ELF_ABI
683 mvs_check_page (file, code, lit)
684 FILE *file;
685 int code, lit;
687 if (file)
688 assembler_source = file;
690 if (mvs_page_code + code + mvs_page_lit + lit > MAX_MVS_PAGE_LENGTH)
692 /* hop past the literal pool */
693 fprintf (assembler_source, "\tB\t.LPGE%d\n", mvs_page_num);
695 /* dump the literal pool. The .baligns are optional, since
696 * ltorg will align to the size of the largest literal
697 * (which is possibly 8 bytes) */
698 fprintf (assembler_source, "\t.balign\t4\n");
699 fprintf (assembler_source, "\t.LTORG\n");
700 fprintf (assembler_source, "\t.balign\t4\n");
702 /* we continue execution here ... */
703 fprintf (assembler_source, ".LPGE%d:\n", mvs_page_num);
704 fprintf (assembler_source, "\t.DROP\t%d\n", BASE_REGISTER);
705 mvs_page_num++;
707 /* BASR puts the contents of the PSW into r3
708 * that is, r3 will be loaded with the address of "." */
709 fprintf (assembler_source, "\tBASR\tr%d,0\n", BASE_REGISTER);
710 fprintf (assembler_source, ".LPG%d:\n", mvs_page_num);
711 fprintf (assembler_source, "\t.USING\t.,r%d\n", BASE_REGISTER);
712 mvs_page_code = code;
713 mvs_page_lit = lit;
714 return 1;
716 mvs_page_code += code;
717 mvs_page_lit += lit;
718 return 0;
720 #endif /* TARGET_ELF_ABI */
722 /* ===================================================== */
723 /* defines and functions specific to the HLASM assembler */
724 #ifdef TARGET_HLASM
726 /* Check for C/370 runtime function, they don't use standard calling
727 conventions. True is returned if the function is in the table.
728 NAME is the name of the current function. */
731 mvs_function_check (name)
732 const char *name;
734 int lower, middle, upper;
735 int i;
737 lower = 0;
738 upper = MVS_FUNCTION_TABLE_LENGTH - 1;
739 while (lower <= upper)
741 middle = (lower + upper) / 2;
742 i = strcmp (name, mvs_function_table[middle]);
743 if (i == 0)
744 return 1;
745 if (i < 0)
746 upper = middle - 1;
747 else
748 lower = middle + 1;
750 return 0;
753 /* Generate a hash for a given key. */
755 #ifdef LONGEXTERNAL
756 static int
757 mvs_hash_alias (key)
758 const char *key;
760 int h;
761 int i;
762 int l = strlen (key);
764 h = key[0];
765 for (i = 1; i < l; i++)
766 h = ((h * MVS_SET_SIZE) + key[i]) % MVS_HASH_PRIME;
767 return (h);
769 #endif
771 /* Add the alias to the current alias list. */
773 void
774 mvs_add_alias (realname, aliasname, emitted)
775 const char *realname;
776 const char *aliasname;
777 int emitted;
779 alias_node_t *ap;
781 ap = (alias_node_t *) xmalloc (sizeof (alias_node_t));
782 if (strlen (realname) > MAX_LONG_LABEL_SIZE)
784 warning ("real name is too long - alias ignored");
785 return;
787 if (strlen (aliasname) > MAX_MVS_LABEL_SIZE)
789 warning ("alias name is too long - alias ignored");
790 return;
793 strcpy (ap->real_name, realname);
794 strcpy (ap->alias_name, aliasname);
795 ap->alias_emitted = emitted;
796 ap->alias_next = alias_anchor;
797 alias_anchor = ap;
800 /* Check to see if the name needs aliasing. ie. the name is either:
801 1. Longer than 8 characters
802 2. Contains an underscore
803 3. Is mixed case */
806 mvs_need_alias (realname)
807 const char *realname;
809 int i, j = strlen (realname);
811 if (mvs_function_check (realname))
812 return 0;
813 #if 0
814 if (!strcmp (realname, "gccmain"))
815 return 0;
816 if (!strcmp (realname, "main"))
817 return 0;
818 #endif
819 if (j > MAX_MVS_LABEL_SIZE)
820 return 1;
821 if (strchr (realname, '_') != 0)
822 return 1;
823 if (ISUPPER (realname[0]))
825 for (i = 1; i < j; i++)
827 if (ISLOWER (realname[i]))
828 return 1;
831 else
833 for (i = 1; i < j; i++)
835 if (ISUPPER (realname[i]))
836 return 1;
840 return 0;
843 /* Get the alias from the list.
844 If 1 is returned then it's in the alias list, 0 if it was not */
847 mvs_get_alias (realname, aliasname)
848 const char *realname;
849 char *aliasname;
851 #ifdef LONGEXTERNAL
852 alias_node_t *ap;
854 for (ap = alias_anchor; ap; ap = ap->alias_next)
856 if (!strcmp (ap->real_name, realname))
858 strcpy (aliasname, ap->alias_name);
859 return 1;
862 if (mvs_need_alias (realname))
864 char c1, c2;
866 c1 = realname[0];
867 c2 = realname[1];
868 if (ISLOWER (c1)) c1 = TOUPPER (c1);
869 else if (c1 == '_') c1 = 'A';
870 if (ISLOWER (c2)) c2 = TOUPPER (c2);
871 else if (c2 == '_' || c2 == '\0') c2 = '#';
873 sprintf (aliasname, "%c%c%06d", c1, c2, mvs_hash_alias (realname));
874 mvs_add_alias (realname, aliasname, 0);
875 return 1;
877 #else
878 if (strlen (realname) > MAX_MVS_LABEL_SIZE)
880 strncpy (aliasname, realname, MAX_MVS_LABEL_SIZE);
881 aliasname[MAX_MVS_LABEL_SIZE] = '\0';
882 return 1;
884 #endif
885 return 0;
888 /* Check to see if the alias is in the list.
889 If 1 is returned then it's in the alias list, 2 it was emitted */
892 mvs_check_alias (realname, aliasname)
893 const char *realname;
894 char *aliasname;
896 #ifdef LONGEXTERNAL
897 alias_node_t *ap;
899 for (ap = alias_anchor; ap; ap = ap->alias_next)
901 if (!strcmp (ap->real_name, realname))
903 int rc = (ap->alias_emitted == 1) ? 1 : 2;
904 strcpy (aliasname, ap->alias_name);
905 ap->alias_emitted = 1;
906 return rc;
909 if (mvs_need_alias (realname))
911 char c1, c2;
913 c1 = realname[0];
914 c2 = realname[1];
915 if (ISLOWER (c1)) c1 = TOUPPER (c1);
916 else if (c1 == '_') c1 = 'A';
917 if (ISLOWER (c2)) c2 = TOUPPER (c2);
918 else if (c2 == '_' || c2 == '\0') c2 = '#';
920 sprintf (aliasname, "%c%c%06d", c1, c2, mvs_hash_alias (realname));
921 mvs_add_alias (realname, aliasname, 0);
922 alias_anchor->alias_emitted = 1;
923 return 2;
925 #else
926 if (strlen (realname) > MAX_MVS_LABEL_SIZE)
928 strncpy (aliasname, realname, MAX_MVS_LABEL_SIZE);
929 aliasname[MAX_MVS_LABEL_SIZE] = '\0';
930 return 1;
932 #endif
933 return 0;
936 /* defines and functions specific to the HLASM assembler */
937 #endif /* TARGET_HLASM */
938 /* ===================================================== */
939 /* ===================================================== */
940 /* defines and functions specific to the gas assembler */
941 #ifdef TARGET_ELF_ABI
943 /* Check for C/370 runtime function, they don't use standard calling
944 conventions. True is returned if the function is in the table.
945 NAME is the name of the current function. */
946 /* no special calling conventions (yet ??) */
949 mvs_function_check (name)
950 const char *name ATTRIBUTE_UNUSED;
952 return 0;
955 #endif /* TARGET_ELF_ABI */
956 /* ===================================================== */
959 /* Return 1 if OP is a valid S operand for an RS, SI or SS type instruction.
960 OP is the current operation.
961 MODE is the current operation mode. */
964 s_operand (op, mode)
965 register rtx op;
966 enum machine_mode mode;
968 extern int volatile_ok;
969 register enum rtx_code code = GET_CODE (op);
971 if (CONSTANT_ADDRESS_P (op))
972 return 1;
973 if (mode == VOIDmode || GET_MODE (op) != mode)
974 return 0;
975 if (code == MEM)
977 register rtx x = XEXP (op, 0);
979 if (!volatile_ok && op->volatil)
980 return 0;
981 if (REG_P (x) && REG_OK_FOR_BASE_P (x))
982 return 1;
983 if (GET_CODE (x) == PLUS
984 && REG_P (XEXP (x, 0)) && REG_OK_FOR_BASE_P (XEXP (x, 0))
985 && GET_CODE (XEXP (x, 1)) == CONST_INT
986 && (unsigned) INTVAL (XEXP (x, 1)) < 4096)
987 return 1;
989 return 0;
993 /* Return 1 if OP is a valid R or S operand for an RS, SI or SS type
994 instruction.
995 OP is the current operation.
996 MODE is the current operation mode. */
999 r_or_s_operand (op, mode)
1000 register rtx op;
1001 enum machine_mode mode;
1003 extern int volatile_ok;
1004 register enum rtx_code code = GET_CODE (op);
1006 if (CONSTANT_ADDRESS_P (op))
1007 return 1;
1008 if (mode == VOIDmode || GET_MODE (op) != mode)
1009 return 0;
1010 if (code == REG)
1011 return 1;
1012 else if (code == MEM)
1014 register rtx x = XEXP (op, 0);
1016 if (!volatile_ok && op->volatil)
1017 return 0;
1018 if (REG_P (x) && REG_OK_FOR_BASE_P (x))
1019 return 1;
1020 if (GET_CODE (x) == PLUS
1021 && REG_P (XEXP (x, 0)) && REG_OK_FOR_BASE_P (XEXP (x, 0))
1022 && GET_CODE (XEXP (x, 1)) == CONST_INT
1023 && (unsigned) INTVAL (XEXP (x, 1)) < 4096)
1024 return 1;
1026 return 0;
1030 /* Some remarks about unsigned_jump_follows_p():
1031 gcc is built around the assumption that branches are signed
1032 or unsigned, whereas the 370 doesn't care; its the compares that
1033 are signed or unsigned. Thus, we need to somehow know if we
1034 need to do a signed or an unsigned compare, and we do this by
1035 looking ahead in the instruction sequence until we find a jump.
1036 We then note whether this jump is signed or unsigned, and do the
1037 compare appropriately. Note that we have to scan ahead indefinitley,
1038 as the gcc optimizer may insert any number of instructions between
1039 the compare and the jump.
1041 Note that using conditional branch expanders seems to be be a more
1042 elegant/correct way of doing this. See, for instance, the Alpha
1043 cmpdi and bgt patterns. Note also that for the i370, various
1044 arithmetic insn's set the condition code as well.
1046 The unsigned_jump_follows_p() routine returns a 1 if the next jump
1047 is unsigned. INSN is the current instruction. */
1050 unsigned_jump_follows_p (insn)
1051 register rtx insn;
1053 rtx orig_insn = insn;
1054 while (1)
1056 register rtx tmp_insn;
1057 enum rtx_code coda;
1059 insn = NEXT_INSN (insn);
1060 if (!insn) fatal_insn ("internal error--no jump follows compare:", orig_insn);
1062 if (GET_CODE (insn) != JUMP_INSN) continue;
1064 tmp_insn = XEXP (insn, 3);
1065 if (GET_CODE (tmp_insn) != SET) continue;
1067 if (GET_CODE (XEXP (tmp_insn, 0)) != PC) continue;
1069 tmp_insn = XEXP (tmp_insn, 1);
1070 if (GET_CODE (tmp_insn) != IF_THEN_ELSE) continue;
1072 /* if we got to here, this instruction is a jump. Is it signed? */
1073 tmp_insn = XEXP (tmp_insn, 0);
1074 coda = GET_CODE (tmp_insn);
1076 return coda != GE && coda != GT && coda != LE && coda != LT;
1080 #ifdef TARGET_HLASM
1082 /* Target hook for assembling integer objects. This version handles all
1083 objects when TARGET_HLASM is defined. */
1085 static bool
1086 i370_hlasm_assemble_integer (x, size, aligned_p)
1087 rtx x;
1088 unsigned int size;
1089 int aligned_p;
1091 const char *int_format = NULL;
1093 if (aligned_p)
1094 switch (size)
1096 case 1:
1097 int_format = "\tDC\tX'%02X'\n";
1098 break;
1100 case 2:
1101 int_format = "\tDC\tX'%04X'\n";
1102 break;
1104 case 4:
1105 if (GET_CODE (x) == CONST_INT)
1107 fputs ("\tDC\tF'", asm_out_file);
1108 output_addr_const (asm_out_file, x);
1109 fputs ("'\n", asm_out_file);
1111 else
1113 fputs ("\tDC\tA(", asm_out_file);
1114 output_addr_const (asm_out_file, x);
1115 fputs (")\n", asm_out_file);
1117 return true;
1120 if (int_format && GET_CODE (x) == CONST_INT)
1122 fprintf (asm_out_file, int_format, INTVAL (x));
1123 return true;
1125 return default_assemble_integer (x, size, aligned_p);
1128 /* Generate the assembly code for function entry. FILE is a stdio
1129 stream to output the code to. SIZE is an int: how many units of
1130 temporary storage to allocate.
1132 Refer to the array `regs_ever_live' to determine which registers to
1133 save; `regs_ever_live[I]' is nonzero if register number I is ever
1134 used in the function. This function is responsible for knowing
1135 which registers should not be saved even if used. */
1137 static void
1138 i370_output_function_prologue (f, l)
1139 FILE *f;
1140 HOST_WIDE_INT l;
1142 #if MACROPROLOGUE == 1
1143 fprintf (f, "* Function %s prologue\n", mvs_function_name);
1144 fprintf (f, "\tEDCPRLG USRDSAL=%d,BASEREG=%d\n",
1145 STACK_POINTER_OFFSET + l - 120 +
1146 current_function_outgoing_args_size, BASE_REGISTER);
1147 #else /* MACROPROLOGUE != 1 */
1148 static int function_label_index = 1;
1149 static int function_first = 0;
1150 static int function_year, function_month, function_day;
1151 static int function_hour, function_minute, function_second;
1152 #if defined(LE370)
1153 if (!function_first)
1155 struct tm *function_time;
1156 time_t lcltime;
1157 time (&lcltime);
1158 function_time = localtime (&lcltime);
1159 function_year = function_time->tm_year + 1900;
1160 function_month = function_time->tm_mon + 1;
1161 function_day = function_time->tm_mday;
1162 function_hour = function_time->tm_hour;
1163 function_minute = function_time->tm_min;
1164 function_second = function_time->tm_sec;
1166 fprintf (f, "* Function %s prologue\n", mvs_function_name);
1167 fprintf (f, "FDSE%03d\tDSECT\n", function_label_index);
1168 fprintf (f, "\tDS\tD\n");
1169 fprintf (f, "\tDS\tCL(" HOST_WIDE_INT_PRINT_DEC ")\n",
1170 STACK_POINTER_OFFSET + l
1171 + current_function_outgoing_args_size);
1172 fprintf (f, "\tORG\tFDSE%03d\n", function_label_index);
1173 fprintf (f, "\tDS\tCL(120+8)\n");
1174 fprintf (f, "\tORG\n");
1175 fprintf (f, "\tDS\t0D\n");
1176 fprintf (f, "FDSL%03d\tEQU\t*-FDSE%03d-8\n", function_label_index,
1177 function_label_index);
1178 fprintf (f, "\tDS\t0H\n");
1179 assemble_name (f, mvs_function_name);
1180 fprintf (f, "\tCSECT\n");
1181 fprintf (f, "\tUSING\t*,15\n");
1182 fprintf (f, "\tB\tFENT%03d\n", function_label_index);
1183 fprintf (f, "\tDC\tAL1(FNAM%03d+4-*)\n", function_label_index);
1184 fprintf (f, "\tDC\tX'CE',X'A0',AL1(16)\n");
1185 fprintf (f, "\tDC\tAL4(FPPA%03d)\n", function_label_index);
1186 fprintf (f, "\tDC\tAL4(0)\n");
1187 fprintf (f, "\tDC\tAL4(FDSL%03d)\n", function_label_index);
1188 fprintf (f, "FNAM%03d\tEQU\t*\n", function_label_index);
1189 fprintf (f, "\tDC\tAL2(%d),C'%s'\n", strlen (mvs_function_name),
1190 mvs_function_name);
1191 fprintf (f, "FPPA%03d\tDS\t0F\n", function_label_index);
1192 fprintf (f, "\tDC\tX'03',X'00',X'33',X'00'\n");
1193 fprintf (f, "\tDC\tV(CEESTART)\n");
1194 fprintf (f, "\tDC\tAL4(0)\n");
1195 fprintf (f, "\tDC\tAL4(FTIM%03d)\n", function_label_index);
1196 fprintf (f, "FTIM%03d\tDS\t0F\n", function_label_index);
1197 fprintf (f, "\tDC\tCL4'%d',CL4'%02d%02d',CL6'%02d%02d00'\n",
1198 function_year, function_month, function_day,
1199 function_hour, function_minute);
1200 fprintf (f, "\tDC\tCL2'01',CL4'0100'\n");
1201 fprintf (f, "FENT%03d\tDS\t0H\n", function_label_index);
1202 fprintf (f, "\tSTM\t14,12,12(13)\n");
1203 fprintf (f, "\tL\t2,76(,13)\n");
1204 fprintf (f, "\tL\t0,16(,15)\n");
1205 fprintf (f, "\tALR\t0,2\n");
1206 fprintf (f, "\tCL\t0,12(,12)\n");
1207 fprintf (f, "\tBNH\t*+10\n");
1208 fprintf (f, "\tL\t15,116(,12)\n");
1209 fprintf (f, "\tBALR\t14,15\n");
1210 fprintf (f, "\tL\t15,72(,13)\n");
1211 fprintf (f, "\tSTM\t15,0,72(2)\n");
1212 fprintf (f, "\tMVI\t0(2),X'10'\n");
1213 fprintf (f, "\tST\t2,8(,13)\n ");
1214 fprintf (f, "\tST\t13,4(,2)\n ");
1215 fprintf (f, "\tLR\t13,2\n");
1216 fprintf (f, "\tDROP\t15\n");
1217 fprintf (f, "\tBALR\t%d,0\n", BASE_REGISTER);
1218 fprintf (f, "\tUSING\t*,%d\n", BASE_REGISTER);
1219 function_first = 1;
1220 function_label_index ++;
1221 #else /* !LE370 */
1222 if (!function_first)
1224 struct tm *function_time;
1225 time_t lcltime;
1226 time (&lcltime);
1227 function_time = localtime (&lcltime);
1228 function_year = function_time->tm_year + 1900;
1229 function_month = function_time->tm_mon + 1;
1230 function_day = function_time->tm_mday;
1231 function_hour = function_time->tm_hour;
1232 function_minute = function_time->tm_min;
1233 function_second = function_time->tm_sec;
1234 fprintf (f, "PPA2\tDS\t0F\n");
1235 fprintf (f, "\tDC\tX'03',X'00',X'33',X'00'\n");
1236 fprintf (f, "\tDC\tV(CEESTART),A(0)\n");
1237 fprintf (f, "\tDC\tA(CEETIMES)\n");
1238 fprintf (f, "CEETIMES\tDS\t0F\n");
1239 fprintf (f, "\tDC\tCL4'%d',CL4'%02d%02d',CL6'%02d%02d00'\n",
1240 function_year, function_month, function_day,
1241 function_hour, function_minute, function_second);
1242 fprintf (f, "\tDC\tCL2'01',CL4'0100'\n");
1244 fprintf (f, "* Function %s prologue\n", mvs_function_name);
1245 fprintf (f, "FDSD%03d\tDSECT\n", function_label_index);
1246 fprintf (f, "\tDS\tD\n");
1247 fprintf (f, "\tDS\tCL(%d)\n", STACK_POINTER_OFFSET + l
1248 + current_function_outgoing_args_size);
1249 fprintf (f, "\tORG\tFDSD%03d\n", function_label_index);
1250 fprintf (f, "\tDS\tCL(120+8)\n");
1251 fprintf (f, "\tORG\n");
1252 fprintf (f, "\tDS\t0D\n");
1253 fprintf (f, "FDSL%03d\tEQU\t*-FDSD%03d-8\n", function_label_index,
1254 function_label_index);
1255 fprintf (f, "\tDS\t0H\n");
1256 assemble_name (f, mvs_function_name);
1257 fprintf (f, "\tCSECT\n");
1258 fprintf (f, "\tUSING\t*,15\n");
1259 fprintf (f, "\tB\tFPL%03d\n", function_label_index);
1260 fprintf (f, "\tDC\tAL1(FPL%03d+4-*)\n", function_label_index + 1);
1261 fprintf (f, "\tDC\tX'CE',X'A0',AL1(16)\n");
1262 fprintf (f, "\tDC\tAL4(PPA2)\n");
1263 fprintf (f, "\tDC\tAL4(0)\n");
1264 fprintf (f, "\tDC\tAL4(FDSL%03d)\n", function_label_index);
1265 fprintf (f, "FPL%03d\tEQU\t*\n", function_label_index + 1);
1266 fprintf (f, "\tDC\tAL2(%d),C'%s'\n", strlen (mvs_function_name),
1267 mvs_function_name);
1268 fprintf (f, "FPL%03d\tDS\t0H\n", function_label_index);
1269 fprintf (f, "\tSTM\t14,12,12(13)\n");
1270 fprintf (f, "\tL\t2,76(,13)\n");
1271 fprintf (f, "\tL\t0,16(,15)\n");
1272 fprintf (f, "\tALR\t0,2\n");
1273 fprintf (f, "\tCL\t0,12(,12)\n");
1274 fprintf (f, "\tBNH\t*+10\n");
1275 fprintf (f, "\tL\t15,116(,12)\n");
1276 fprintf (f, "\tBALR\t14,15\n");
1277 fprintf (f, "\tL\t15,72(,13)\n");
1278 fprintf (f, "\tSTM\t15,0,72(2)\n");
1279 fprintf (f, "\tMVI\t0(2),X'10'\n");
1280 fprintf (f, "\tST\t2,8(,13)\n ");
1281 fprintf (f, "\tST\t13,4(,2)\n ");
1282 fprintf (f, "\tLR\t13,2\n");
1283 fprintf (f, "\tDROP\t15\n");
1284 fprintf (f, "\tBALR\t%d,0\n", BASE_REGISTER);
1285 fprintf (f, "\tUSING\t*,%d\n", BASE_REGISTER);
1286 function_first = 1;
1287 function_label_index += 2;
1288 #endif /* !LE370 */
1289 #endif /* MACROPROLOGUE */
1290 fprintf (f, "PG%d\tEQU\t*\n", mvs_page_num );
1291 fprintf (f, "\tLR\t11,1\n");
1292 fprintf (f, "\tL\t%d,=A(PGT%d)\n", PAGE_REGISTER, mvs_page_num);
1293 fprintf (f, "* Function %s code\n", mvs_function_name);
1295 mvs_free_label_list ();
1296 mvs_page_code = 6;
1297 mvs_page_lit = 4;
1298 mvs_check_page (f, 0, 0);
1299 function_base_page = mvs_page_num;
1301 /* find all labels in this routine */
1302 i370_label_scan ();
1305 static void
1306 i370_globalize_label (stream, name)
1307 FILE *stream;
1308 const char *name;
1310 char temp[MAX_MVS_LABEL_SIZE + 1];
1311 if (mvs_check_alias (name, temp) == 2)
1312 fprintf (stream, "%s\tALIAS\tC'%s'\n", temp, name);
1313 fputs ("\tENTRY\t", stream);
1314 assemble_name (stream, name);
1315 putc ('\n', stream);
1317 #endif /* TARGET_HLASM */
1320 #ifdef TARGET_ELF_ABI
1322 The 370_function_prolog() routine generates the current ELF ABI ES/390 prolog.
1323 It implements a stack that grows downward.
1324 It performs the following steps:
1325 -- saves the callers non-volatile registers on the callers stack.
1326 -- subtracts stackframe size from the stack pointer.
1327 -- stores backpointer to old caller stack.
1329 XXX hack alert -- if the global var int leaf_function is nonzero,
1330 then this is a leaf, and it might be possible to optimize the prologue
1331 into doing even less, e.g. not grabbing a new stackframe or maybe just a
1332 partial stack frame.
1334 XXX hack alert -- the current stack frame is bloated into twice the
1335 needed size by unused entries. These entries make it marginally
1336 compatible with MVS/OE/USS C environment, but really they're not used
1337 and could probably chopped out. Modifications to i370.md would be needed
1338 also, to quite using addresses 136, 140, etc.
1341 static void
1342 i370_output_function_prologue (f, frame_size)
1343 FILE *f;
1344 HOST_WIDE_INT frame_size;
1346 static int function_label_index = 1;
1347 static int function_first = 0;
1348 int stackframe_size, aligned_size;
1350 fprintf (f, "# Function prologue\n");
1351 /* define the stack, put it into its own data segment
1352 FDSE == Function Stack Entry
1353 FDSL == Function Stack Length */
1354 stackframe_size =
1355 STACK_POINTER_OFFSET + current_function_outgoing_args_size + frame_size;
1356 aligned_size = (stackframe_size + 7) >> 3;
1357 aligned_size <<= 3;
1359 fprintf (f, "# arg_size=0x%x frame_size=" HOST_WIDE_INT_PRINT_HEX
1360 " aligned size=0x%x\n",
1361 current_function_outgoing_args_size, frame_size, aligned_size);
1363 fprintf (f, "\t.using\t.,r15\n");
1365 /* Branch to exectuable part of prologue. */
1366 fprintf (f, "\tB\t.LFENT%03d\n", function_label_index);
1368 /* write the length of the stackframe */
1369 fprintf (f, "\t.long\t%d\n", aligned_size);
1371 /* FENT == function prologue entry */
1372 fprintf (f, "\t.balign 2\n.LFENT%03d:\n",
1373 function_label_index);
1375 /* store multiple registers 14,15,0,...12 at 12 bytes from sp */
1376 fprintf (f, "\tSTM\tr14,r12,12(sp)\n");
1378 /* r3 == saved callee stack pointer */
1379 fprintf (f, "\tLR\tr3,sp\n");
1381 /* 4(r15) == stackframe size */
1382 fprintf (f, "\tSL\tsp,4(,r15)\n");
1384 /* r11 points to arg list in callers stackframe; was passed in r2 */
1385 fprintf (f, "\tLR\tr11,r2\n");
1387 /* store callee stack pointer at 8(sp) */
1388 /* fprintf (f, "\tST\tsp,8(,r3)\n "); wasted cycles, no one uses this ... */
1390 /* backchain -- store caller sp at 4(callee_sp) */
1391 fprintf (f, "\tST\tr3,4(,sp)\n ");
1393 fprintf (f, "\t.drop\tr15\n");
1394 /* Place contents of the PSW into r3
1395 that is, place the address of "." into r3 */
1396 fprintf (f, "\tBASR\tr%d,0\n", BASE_REGISTER);
1397 fprintf (f, "\t.using\t.,r%d\n", BASE_REGISTER);
1398 function_first = 1;
1399 function_label_index ++;
1401 fprintf (f, ".LPG%d:\n", mvs_page_num );
1402 fprintf (f, "\tL\tr%d,=A(.LPGT%d)\n", PAGE_REGISTER, mvs_page_num);
1403 fprintf (f, "# Function code\n");
1405 mvs_free_label_list ();
1406 mvs_page_code = 6;
1407 mvs_page_lit = 4;
1408 mvs_check_page (f, 0, 0);
1409 function_base_page = mvs_page_num;
1411 /* find all labels in this routine */
1412 i370_label_scan ();
1414 #endif /* TARGET_ELF_ABI */
1416 /* This function generates the assembly code for function exit.
1417 Args are as for output_function_prologue ().
1419 The function epilogue should not depend on the current stack
1420 pointer! It should use the frame pointer only. This is mandatory
1421 because of alloca; we also take advantage of it to omit stack
1422 adjustments before returning. */
1424 static void
1425 i370_output_function_epilogue (file, l)
1426 FILE *file;
1427 HOST_WIDE_INT l ATTRIBUTE_UNUSED;
1429 int i;
1431 check_label_emit ();
1432 mvs_check_page (file, 14, 0);
1433 fprintf (file, "* Function %s epilogue\n", mvs_function_name);
1434 mvs_page_num++;
1436 #if MACROEPILOGUE == 1
1437 fprintf (file, "\tEDCEPIL\n");
1438 #else /* MACROEPILOGUE != 1 */
1439 fprintf (file, "\tL\t13,4(,13)\n");
1440 fprintf (file, "\tL\t14,12(,13)\n");
1441 fprintf (file, "\tLM\t2,12,28(13)\n");
1442 fprintf (file, "\tBALR\t1,14\n");
1443 fprintf (file, "\tDC\tA(");
1444 assemble_name (file, mvs_function_name);
1445 fprintf (file, ")\n" );
1446 #endif /* MACROEPILOGUE */
1448 fprintf (file, "* Function %s literal pool\n", mvs_function_name);
1449 fprintf (file, "\tDS\t0F\n" );
1450 fprintf (file, "\tLTORG\n");
1451 fprintf (file, "* Function %s page table\n", mvs_function_name);
1452 fprintf (file, "\tDS\t0F\n");
1453 fprintf (file, "PGT%d\tEQU\t*\n", function_base_page);
1455 mvs_free_label_list();
1456 for (i = function_base_page; i < mvs_page_num; i++)
1457 fprintf (file, "\tDC\tA(PG%d)\n", i);
1460 static void
1461 i370_file_start ()
1463 fputs ("\tRMODE\tANY\n\tCSECT\n", asm_out_file);
1466 static void
1467 i370_file_end ()
1469 fputs ("\tEND\n", asm_out_file);
1472 static void
1473 i370_internal_label (stream, prefix, labelno)
1474 FILE *stream;
1475 const char *prefix;
1476 unsigned long labelno;
1478 if (!strcmp (prefix, "L"))
1479 mvs_add_label(labelno);
1481 default_internal_label (stream, prefix, labelno);
1484 static bool
1485 i370_rtx_costs (x, code, outer_code, total)
1486 rtx x;
1487 int code;
1488 int outer_code ATTRIBUTE_UNUSED;
1489 int *total;
1491 switch (code)
1493 case CONST_INT:
1494 if ((unsigned HOST_WIDE_INT) INTVAL (x) < 0xfff)
1496 *total = 1;
1497 return true;
1499 /* FALLTHRU */
1501 case CONST:
1502 case LABEL_REF:
1503 case SYMBOL_REF:
1504 *total = 2;
1505 return true;
1507 case CONST_DOUBLE:
1508 *total = 4;
1509 return true;
1511 default:
1512 return false;