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 GNU CC.
10 GNU CC 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)
15 GNU CC 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 GNU CC; see the file COPYING. If not, write to
22 the Free Software Foundation, 59 Temple Place - Suite 330,
23 Boston, MA 02111-1307, USA. */
30 #include "hard-reg-set.h"
32 #include "insn-config.h"
33 #include "conditions.h"
35 #include "insn-attr.h"
44 #include "target-def.h"
46 extern FILE *asm_out_file;
48 /* Label node. This structure is used to keep track of labels
49 on the various pages in the current routine.
50 The label_id is the numeric ID of the label,
51 The label_page is the page on which it actually appears,
52 The first_ref_page is the page on which the true first ref appears.
53 The label_addr is an estimate of its location in the current routine,
54 The label_first & last_ref are estimates of where the earliest and
55 latest references to this label occur. */
57 typedef struct label_node
59 struct label_node *label_next;
70 /* Is 1 when a label has been generated and the base register must be reloaded. */
71 int mvs_need_base_reload = 0;
73 /* Current function starting base page. */
74 int function_base_page;
76 /* Length of the current page code. */
79 /* Length of the current page literals. */
82 /* Current function name. */
83 char *mvs_function_name = 0;
85 /* Current function name length. */
86 int mvs_function_name_length = 0;
88 /* Page number for multi-page functions. */
91 /* Label node list anchor. */
92 static label_node_t *label_anchor = 0;
94 /* Label node free list anchor. */
95 static label_node_t *free_anchor = 0;
97 /* Assembler source file descriptor. */
98 static FILE *assembler_source = 0;
100 static label_node_t * mvs_get_label PARAMS ((int));
101 static void i370_label_scan PARAMS ((void));
103 static bool i370_hlasm_assemble_integer PARAMS ((rtx, unsigned int, int));
104 static void i370_globalize_label PARAMS ((FILE *, const char *));
106 static void i370_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
107 static void i370_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
109 static int mvs_hash_alias PARAMS ((const char *));
111 static void i370_encode_section_info PARAMS ((tree, int));
113 /* ===================================================== */
114 /* defines and functions specific to the HLASM assembler */
117 #define MVS_HASH_PRIME 999983
118 #if defined(HOST_EBCDIC)
119 #define MVS_SET_SIZE 256
121 #define MVS_SET_SIZE 128
124 #ifndef MAX_MVS_LABEL_SIZE
125 #define MAX_MVS_LABEL_SIZE 8
128 #define MAX_LONG_LABEL_SIZE 255
130 /* Alias node, this structure is used to keep track of aliases to external
131 variables. The IBM assembler allows an alias to an external name
132 that is longer that 8 characters; but only once per assembly.
133 Also, this structure stores the #pragma map info. */
134 typedef struct alias_node
136 struct alias_node *alias_next;
138 char alias_name [MAX_MVS_LABEL_SIZE + 1];
139 char real_name [MAX_LONG_LABEL_SIZE + 1];
143 /* Alias node list anchor. */
144 static alias_node_t *alias_anchor = 0;
146 /* Define the length of the internal MVS function table. */
147 #define MVS_FUNCTION_TABLE_LENGTH 32
149 /* C/370 internal function table. These functions use non-standard linkage
150 and must handled in a special manner. */
151 static const char *const mvs_function_table[MVS_FUNCTION_TABLE_LENGTH] =
153 #if defined(HOST_EBCDIC) /* Changed for EBCDIC collating sequence */
154 "ceil", "edc_acos", "edc_asin", "edc_atan", "edc_ata2", "edc_cos",
155 "edc_cosh", "edc_erf", "edc_erfc", "edc_exp", "edc_gamm", "edc_lg10",
156 "edc_log", "edc_sin", "edc_sinh", "edc_sqrt", "edc_tan", "edc_tanh",
157 "fabs", "floor", "fmod", "frexp", "hypot", "jn",
158 "j0", "j1", "ldexp", "modf", "pow", "yn",
161 "ceil", "edc_acos", "edc_asin", "edc_ata2", "edc_atan", "edc_cos",
162 "edc_cosh", "edc_erf", "edc_erfc", "edc_exp", "edc_gamm", "edc_lg10",
163 "edc_log", "edc_sin", "edc_sinh", "edc_sqrt", "edc_tan", "edc_tanh",
164 "fabs", "floor", "fmod", "frexp", "hypot", "j0",
165 "j1", "jn", "ldexp", "modf", "pow", "y0",
170 #endif /* TARGET_HLASM */
171 /* ===================================================== */
173 /* ASCII to EBCDIC conversion table. */
174 static const unsigned char ascebc[256] =
176 /*00 NL SH SX EX ET NQ AK BL */
177 0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F,
178 /*08 BS HT LF VT FF CR SO SI */
179 0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
180 /*10 DL D1 D2 D3 D4 NK SN EB */
181 0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26,
182 /*18 CN EM SB EC FS GS RS US */
183 0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D, 0x1E, 0x1F,
184 /*20 SP ! " # $ % & ' */
185 0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D,
186 /*28 ( ) * + , - . / */
187 0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,
188 /*30 0 1 2 3 4 5 6 7 */
189 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
190 /*38 8 9 : ; < = > ? */
191 0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,
192 /*40 @ A B C D E F G */
193 0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
194 /*48 H I J K L M N O */
195 0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
196 /*50 P Q R S T U V W */
197 0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,
198 /*58 X Y Z [ \ ] ^ _ */
199 0xE7, 0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D,
200 /*60 ` a b c d e f g */
201 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
202 /*68 h i j k l m n o */
203 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
204 /*70 p q r s t u v w */
205 0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
206 /*78 x y z { | } ~ DL */
207 0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07,
208 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
209 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
210 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
211 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
212 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
213 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
214 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
215 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
216 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
217 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
218 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
219 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
220 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
221 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
222 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
223 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0xFF
226 /* EBCDIC to ASCII conversion table. */
227 static const unsigned char ebcasc[256] =
229 /*00 NU SH SX EX PF HT LC DL */
230 0x00, 0x01, 0x02, 0x03, 0x00, 0x09, 0x00, 0x7F,
231 /*08 SM VT FF CR SO SI */
232 0x00, 0x00, 0x00, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
233 /*10 DE D1 D2 TM RS NL BS IL */
234 0x10, 0x11, 0x12, 0x13, 0x14, 0x0A, 0x08, 0x00,
235 /*18 CN EM CC C1 FS GS RS US */
236 0x18, 0x19, 0x00, 0x00, 0x1C, 0x1D, 0x1E, 0x1F,
237 /*20 DS SS FS BP LF EB EC */
238 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x17, 0x1B,
239 /*28 SM C2 EQ AK BL */
240 0x00, 0x00, 0x00, 0x00, 0x05, 0x06, 0x07, 0x00,
241 /*30 SY PN RS UC ET */
242 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
244 0x00, 0x00, 0x00, 0x00, 0x14, 0x15, 0x00, 0x1A,
246 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
248 0x00, 0x00, 0x00, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,
250 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
252 0x00, 0x00, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0x5E,
254 0x2D, 0x2F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
256 0x00, 0x00, 0x00, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
258 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
259 /*78 ` : # @ ' = " */
260 0x00, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
261 /*80 a b c d e f g */
262 0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
264 0x68, 0x69, 0x00, 0x7B, 0x00, 0x00, 0x00, 0x00,
265 /*90 j k l m n o p */
266 0x00, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
268 0x71, 0x72, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x00,
269 /*A0 ~ s t u v w x */
270 0x00, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
272 0x79, 0x7A, 0x00, 0x00, 0x00, 0x5B, 0x00, 0x00,
274 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
276 0x00, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x00, 0x00,
277 /*C0 { A B C D E F G */
278 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
280 0x48, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
281 /*D0 } J K L M N O P */
282 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
284 0x51, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
285 /*E0 \ S T U V W X */
286 0x5C, 0x00, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
288 0x59, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
289 /*F0 0 1 2 3 4 5 6 7 */
290 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
292 0x38, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF
295 /* Initialize the GCC target structure. */
297 #undef TARGET_ASM_BYTE_OP
298 #define TARGET_ASM_BYTE_OP NULL
299 #undef TARGET_ASM_ALIGNED_HI_OP
300 #define TARGET_ASM_ALIGNED_HI_OP NULL
301 #undef TARGET_ASM_ALIGNED_SI_OP
302 #define TARGET_ASM_ALIGNED_SI_OP NULL
303 #undef TARGET_ASM_INTEGER
304 #define TARGET_ASM_INTEGER i370_hlasm_assemble_integer
305 #undef TARGET_ASM_GLOBALIZE_LABEL
306 #define TARGET_ASM_GLOBALIZE_LABEL i370_globalize_label
309 #undef TARGET_ASM_FUNCTION_PROLOGUE
310 #define TARGET_ASM_FUNCTION_PROLOGUE i370_output_function_prologue
311 #undef TARGET_ASM_FUNCTION_EPILOGUE
312 #define TARGET_ASM_FUNCTION_EPILOGUE i370_output_function_epilogue
313 #undef TARGET_ENCODE_SECTION_INFO
314 #define TARGET_ENCODE_SECTION_INFO i370_encode_section_info
316 struct gcc_target targetm = TARGET_INITIALIZER;
318 /* Map characters from one character set to another.
319 C is the character to be translated. */
325 #if defined(TARGET_EBCDIC) && !defined(HOST_EBCDIC)
326 fprintf (stderr, "mvs_map_char: TE & !HE: c = %02x\n", c);
329 #if defined(HOST_EBCDIC) && !defined(TARGET_EBCDIC)
330 fprintf (stderr, "mvs_map_char: !TE & HE: c = %02x\n", c);
333 fprintf (stderr, "mvs_map_char: !TE & !HE: c = %02x\n", c);
339 /* ===================================================== */
340 /* The following three routines are used to determine whther
341 forward branch is on this page, or is a far jump. We use
342 the "length" attr on an insn [(set_atter "length" "4")]
343 to store the largest possible code length that insn
344 could have. This gives us a hint of the address of a
345 branch destination, and from that, we can work out
346 the length of the jump, and whether its on page or not.
349 /* Return the destination address of a branch. */
352 i370_branch_dest (branch)
355 rtx dest = SET_SRC (PATTERN (branch));
359 /* first, compute the estimated address of the branch target */
360 if (GET_CODE (dest) == IF_THEN_ELSE)
361 dest = XEXP (dest, 1);
362 dest = XEXP (dest, 0);
363 dest_uid = INSN_UID (dest);
364 dest_addr = INSN_ADDRESSES (dest_uid);
366 /* next, record the address of this insn as the true addr of first ref */
369 rtx label = JUMP_LABEL (branch);
370 int labelno = CODE_LABEL_NUMBER (label);
372 if (!label || CODE_LABEL != GET_CODE (label)) abort ();
374 lp = mvs_get_label (labelno);
375 if (-1 == lp -> first_ref_page) lp->first_ref_page = mvs_page_num;
381 i370_branch_length (insn)
385 here = INSN_ADDRESSES (INSN_UID (insn));
386 there = i370_branch_dest (insn);
387 return (there - here);
392 i370_short_branch (insn)
397 base_offset = i370_branch_length(insn);
400 base_offset += mvs_page_code;
404 /* avoid bumping into lit pool; use 2x to estimate max possible lits */
406 base_offset += mvs_page_code + mvs_page_lit;
409 /* make a conservative estimate of room left on page */
410 if ((4060 >base_offset) && ( 0 < base_offset)) return 1;
414 /* The i370_label_scan() routine is supposed to loop over
415 all labels and label references in a compilation unit,
416 and determine whether all label refs appear on the same
417 code page as the label. If they do, then we can avoid
418 a reload of the base register for that label.
420 Note that the instruction addresses used here are only
421 approximate, and make the sizes of the jumps appear
422 farther apart then they will actually be. This makes
423 this code far more conservative than it needs to be.
426 #define I370_RECORD_LABEL_REF(label,addr) { \
428 int labelno = CODE_LABEL_NUMBER (label); \
429 lp = mvs_get_label (labelno); \
430 if (addr < lp -> label_first_ref) lp->label_first_ref = addr; \
431 if (addr > lp -> label_last_ref) lp->label_last_ref = addr; \
439 int tablejump_offset = 0;
441 for (insn = get_insns(); insn; insn = NEXT_INSN(insn))
443 int here = INSN_ADDRESSES (INSN_UID (insn));
444 enum rtx_code code = GET_CODE(insn);
446 /* ??? adjust for tables embedded in the .text section that
447 * the compiler didn't take into account */
448 here += tablejump_offset;
449 INSN_ADDRESSES (INSN_UID (insn)) = here;
451 /* check to see if this insn is a label ... */
452 if (CODE_LABEL == code)
454 int labelno = CODE_LABEL_NUMBER (insn);
456 lp = mvs_get_label (labelno);
457 lp -> label_addr = here;
459 /* Supposedly, labels are supposed to have circular
460 lists of label-refs that reference them,
461 setup in flow.c, but this does not appear to be the case. */
462 rtx labelref = LABEL_REFS (insn);
466 rtx linsn = CONTAINING_INSN(ref);
467 ref = LABEL_NEXTREF(ref);
468 } while (ref && (ref != labelref));
472 if (JUMP_INSN == code)
474 rtx label = JUMP_LABEL (insn);
476 /* If there is no label for this jump, then this
477 had better be a ADDR_VEC or an ADDR_DIFF_VEC
478 and there had better be a vector of labels. */
482 rtx body = PATTERN (insn);
483 if (ADDR_VEC == GET_CODE(body))
485 for (j=0; j < XVECLEN (body, 0); j++)
487 rtx lref = XVECEXP (body, 0, j);
488 if (LABEL_REF != GET_CODE (lref)) abort ();
489 label = XEXP (lref,0);
490 if (CODE_LABEL != GET_CODE (label)) abort ();
491 tablejump_offset += 4;
493 I370_RECORD_LABEL_REF(label,here);
495 /* finished with the vector go do next insn */
499 if (ADDR_DIFF_VEC == GET_CODE(body))
502 Right now, we leave this as a no-op, but strictly speaking,
503 this is incorrect. It is possible that a table-jump
504 driven off of a relative address could take us off-page,
505 to a place where we need to reload the base reg. So really,
506 we need to examing both labels, and compare thier values
507 to the current basereg value.
509 More generally, this brings up a troubling issue overall:
510 what happens if a tablejump is split across two pages? I do
511 not beleive that this case is handled correctly at all, and
512 can only lead to horrible results if this were to occur.
514 However, the current situation is not any worse than it was
515 last week, and so we punt for now. */
518 for (j=0; j < XVECLEN (body, 0); j++)
521 /* finished with the vector go do next insn */
527 Compiling the exception handling (L_eh) in libgcc2.a will trip
528 up right here, with something that looks like
529 (set (pc) (mem:SI (plus:SI (reg/v:SI 1 r1) (const_int 4))))
531 I'm not sure of what leads up to this, but it looks like
532 the makings of a long jump which will surely get us into trouble
533 because the base & page registers don't get reloaded. For now
534 I'm not sure of what to do ... again we punt ... we are not worse
535 off than yesterday. */
537 /* print_rtl_single (stdout, insn); */
545 /* At this point, this jump_insn had better be a plain-old
546 ordinary one, grap the label id and go */
547 if (CODE_LABEL != GET_CODE (label)) abort ();
548 I370_RECORD_LABEL_REF(label,here);
552 /* Sometimes, we take addresses of labels and use them
553 as instruction operands ... these show up as REG_NOTES */
557 if ('i' == GET_RTX_CLASS (code))
560 for (note = REG_NOTES (insn); note; note = XEXP(note,1))
562 if (REG_LABEL == REG_NOTE_KIND(note))
564 rtx label = XEXP (note,0);
565 if (!label || CODE_LABEL != GET_CODE (label)) abort ();
567 I370_RECORD_LABEL_REF(label,here);
575 /* ===================================================== */
577 /* Emit reload of base register if indicated. This is to eliminate multiple
578 reloads when several labels are generated pointing to the same place
581 The page table is written at the end of the function.
582 The entries in the page table look like
583 .LPGT0: // PGT0 EQU *
584 .long .LPG0 // DC A(PG0)
585 .long .LPG1 // DC A(PG1)
586 while the prologue generates
589 Note that this paging scheme breaks down if a single subroutine
590 has more than about 10MB of code in it ... as long as humans write
591 code, this shouldn't be a problem ...
597 if (mvs_need_base_reload)
599 mvs_need_base_reload = 0;
602 fprintf (assembler_source, "\tL\t%d,%d(,%d)\n",
603 BASE_REGISTER, (mvs_page_num - function_base_page) * 4,
608 /* Add the label to the current page label list. If a free element is available
609 it will be used for the new label. Otherwise, a label element will be
610 allocated from memory.
611 ID is the label number of the label being added to the list. */
613 static label_node_t *
619 /* first, lets see if we already go one, if so, use that. */
620 for (lp = label_anchor; lp; lp = lp->label_next)
622 if (lp->label_id == id) return lp;
625 /* not found, get a new one */
629 free_anchor = lp->label_next;
633 lp = (label_node_t *) xmalloc (sizeof (label_node_t));
636 /* initialize for new label */
639 lp->label_next = label_anchor;
640 lp->label_first_ref = 2000123123;
641 lp->label_last_ref = -1;
643 lp->first_ref_page = -1;
656 lp = mvs_get_label (id);
657 lp->label_page = mvs_page_num;
659 /* OK, we just saw the label. Determine if this label
660 * needs a reload of the base register */
661 if ((-1 != lp->first_ref_page) &&
662 (lp->first_ref_page != mvs_page_num))
664 /* Yep; the first label_ref was on a different page. */
665 mvs_need_base_reload ++;
669 /* Hmm. Try to see if the estimated address of the last
670 label_ref is on the current page. If it is, then we
671 don't need a base reg reload. Note that this estimate
672 is very conservatively handled; we'll tend to have
673 a good bit more reloads than actually needed. Someday,
674 we should tighten the estimates (which are driven by
675 the (set_att "length") insn attibute.
677 Currently, we estimate that number of page literals
678 same as number of insns, which is a vast overestimate,
679 esp that the estimate of each insn size is its max size. */
681 /* if latest ref comes before label, we are clear */
682 if (lp->label_last_ref < lp->label_addr) return;
684 fwd_distance = lp->label_last_ref - lp->label_addr;
686 if (mvs_page_code + 2 * fwd_distance + mvs_page_lit < 4060) return;
688 mvs_need_base_reload ++;
691 /* Check to see if the label is in the list and in the current
692 page. If not found, we have to make worst case assumption
693 that label will be on a different page, and thus will have to
694 generate a load and branch on register. This is rather
695 ugly for forward-jumps, but what can we do? For backward
696 jumps on the same page we can branch directly to address.
697 ID is the label number of the label being checked. */
705 for (lp = label_anchor; lp; lp = lp->label_next)
707 if (lp->label_id == id)
709 if (lp->label_page == mvs_page_num)
722 /* Get the page on which the label sits. This will be used to
723 determine is a register reload is really needed. */
727 mvs_get_label_page(int id)
731 for (lp = label_anchor; lp; lp = lp->label_next)
733 if (lp->label_id == id)
734 return lp->label_page;
740 /* The label list for the current page freed by linking the list onto the free
741 label element chain. */
744 mvs_free_label_list ()
749 label_node_t *last_lp = label_anchor;
750 while (last_lp->label_next) last_lp = last_lp->label_next;
751 last_lp->label_next = free_anchor;
752 free_anchor = label_anchor;
757 /* ====================================================================== */
758 /* If the page size limit is reached a new code page is started, and the base
759 register is set to it. This page break point is counted conservatively,
760 most literals that have the same value are collapsed by the assembler.
761 True is returned when a new page is started.
762 FILE is the assembler output file descriptor.
763 CODE is the length, in bytes, of the instruction to be emitted.
764 LIT is the length of the literal to be emitted. */
768 mvs_check_page (file, code, lit)
773 assembler_source = file;
775 if (mvs_page_code + code + mvs_page_lit + lit > MAX_MVS_PAGE_LENGTH)
777 fprintf (assembler_source, "\tB\tPGE%d\n", mvs_page_num);
778 fprintf (assembler_source, "\tDS\t0F\n");
779 fprintf (assembler_source, "\tLTORG\n");
780 fprintf (assembler_source, "\tDS\t0F\n");
781 fprintf (assembler_source, "PGE%d\tEQU\t*\n", mvs_page_num);
782 fprintf (assembler_source, "\tDROP\t%d\n", BASE_REGISTER);
784 /* Safe to use BASR not BALR, since we are
785 * not switching addressing mode here ... */
786 fprintf (assembler_source, "\tBASR\t%d,0\n", BASE_REGISTER);
787 fprintf (assembler_source, "PG%d\tEQU\t*\n", mvs_page_num);
788 fprintf (assembler_source, "\tUSING\t*,%d\n", BASE_REGISTER);
789 mvs_page_code = code;
793 mvs_page_code += code;
797 #endif /* TARGET_HLASM */
800 #ifdef TARGET_ELF_ABI
802 mvs_check_page (file, code, lit)
807 assembler_source = file;
809 if (mvs_page_code + code + mvs_page_lit + lit > MAX_MVS_PAGE_LENGTH)
811 /* hop past the literal pool */
812 fprintf (assembler_source, "\tB\t.LPGE%d\n", mvs_page_num);
814 /* dump the literal pool. The .baligns are optional, since
815 * ltorg will align to the size of the largest literal
816 * (which is possibly 8 bytes) */
817 fprintf (assembler_source, "\t.balign\t4\n");
818 fprintf (assembler_source, "\t.LTORG\n");
819 fprintf (assembler_source, "\t.balign\t4\n");
821 /* we continue execution here ... */
822 fprintf (assembler_source, ".LPGE%d:\n", mvs_page_num);
823 fprintf (assembler_source, "\t.DROP\t%d\n", BASE_REGISTER);
826 /* BASR puts the contents of the PSW into r3
827 * that is, r3 will be loaded with the address of "." */
828 fprintf (assembler_source, "\tBASR\tr%d,0\n", BASE_REGISTER);
829 fprintf (assembler_source, ".LPG%d:\n", mvs_page_num);
830 fprintf (assembler_source, "\t.USING\t.,r%d\n", BASE_REGISTER);
831 mvs_page_code = code;
835 mvs_page_code += code;
839 #endif /* TARGET_ELF_ABI */
841 /* ===================================================== */
842 /* defines and functions specific to the HLASM assembler */
845 /* Check for C/370 runtime function, they don't use standard calling
846 conventions. True is returned if the function is in the table.
847 NAME is the name of the current function. */
850 mvs_function_check (name)
853 int lower, middle, upper;
857 upper = MVS_FUNCTION_TABLE_LENGTH - 1;
858 while (lower <= upper)
860 middle = (lower + upper) / 2;
861 i = strcmp (name, mvs_function_table[middle]);
872 /* Generate a hash for a given key. */
881 int l = strlen (key);
884 for (i = 1; i < l; i++)
885 h = ((h * MVS_SET_SIZE) + key[i]) % MVS_HASH_PRIME;
890 /* Add the alias to the current alias list. */
893 mvs_add_alias (realname, aliasname, emitted)
894 const char *realname;
895 const char *aliasname;
900 ap = (alias_node_t *) xmalloc (sizeof (alias_node_t));
901 if (strlen (realname) > MAX_LONG_LABEL_SIZE)
903 warning ("real name is too long - alias ignored");
906 if (strlen (aliasname) > MAX_MVS_LABEL_SIZE)
908 warning ("alias name is too long - alias ignored");
912 strcpy (ap->real_name, realname);
913 strcpy (ap->alias_name, aliasname);
914 ap->alias_emitted = emitted;
915 ap->alias_next = alias_anchor;
919 /* Check to see if the name needs aliasing. ie. the name is either:
920 1. Longer than 8 characters
921 2. Contains an underscore
925 mvs_need_alias (realname)
926 const char *realname;
928 int i, j = strlen (realname);
930 if (mvs_function_check (realname))
933 if (!strcmp (realname, "gccmain"))
935 if (!strcmp (realname, "main"))
938 if (j > MAX_MVS_LABEL_SIZE)
940 if (strchr (realname, '_') != 0)
942 if (ISUPPER (realname[0]))
944 for (i = 1; i < j; i++)
946 if (ISLOWER (realname[i]))
952 for (i = 1; i < j; i++)
954 if (ISUPPER (realname[i]))
962 /* Get the alias from the list.
963 If 1 is returned then it's in the alias list, 0 if it was not */
966 mvs_get_alias (realname, aliasname)
967 const char *realname;
973 for (ap = alias_anchor; ap; ap = ap->alias_next)
975 if (!strcmp (ap->real_name, realname))
977 strcpy (aliasname, ap->alias_name);
981 if (mvs_need_alias (realname))
987 if (ISLOWER (c1)) c1 = TOUPPER (c1);
988 else if (c1 == '_') c1 = 'A';
989 if (ISLOWER (c2)) c2 = TOUPPER (c2);
990 else if (c2 == '_' || c2 == '\0') c2 = '#';
992 sprintf (aliasname, "%c%c%06d", c1, c2, mvs_hash_alias (realname));
993 mvs_add_alias (realname, aliasname, 0);
997 if (strlen (realname) > MAX_MVS_LABEL_SIZE)
999 strncpy (aliasname, realname, MAX_MVS_LABEL_SIZE);
1000 aliasname[MAX_MVS_LABEL_SIZE] = '\0';
1007 /* Check to see if the alias is in the list.
1008 If 1 is returned then it's in the alias list, 2 it was emitted */
1011 mvs_check_alias (realname, aliasname)
1012 const char *realname;
1018 for (ap = alias_anchor; ap; ap = ap->alias_next)
1020 if (!strcmp (ap->real_name, realname))
1022 int rc = (ap->alias_emitted == 1) ? 1 : 2;
1023 strcpy (aliasname, ap->alias_name);
1024 ap->alias_emitted = 1;
1028 if (mvs_need_alias (realname))
1034 if (ISLOWER (c1)) c1 = TOUPPER (c1);
1035 else if (c1 == '_') c1 = 'A';
1036 if (ISLOWER (c2)) c2 = TOUPPER (c2);
1037 else if (c2 == '_' || c2 == '\0') c2 = '#';
1039 sprintf (aliasname, "%c%c%06d", c1, c2, mvs_hash_alias (realname));
1040 mvs_add_alias (realname, aliasname, 0);
1041 alias_anchor->alias_emitted = 1;
1045 if (strlen (realname) > MAX_MVS_LABEL_SIZE)
1047 strncpy (aliasname, realname, MAX_MVS_LABEL_SIZE);
1048 aliasname[MAX_MVS_LABEL_SIZE] = '\0';
1055 /* defines and functions specific to the HLASM assembler */
1056 #endif /* TARGET_HLASM */
1057 /* ===================================================== */
1058 /* ===================================================== */
1059 /* defines and functions specific to the gas assembler */
1060 #ifdef TARGET_ELF_ABI
1062 /* Check for C/370 runtime function, they don't use standard calling
1063 conventions. True is returned if the function is in the table.
1064 NAME is the name of the current function. */
1065 /* no special calling conventions (yet ??) */
1068 mvs_function_check (name)
1069 const char *name ATTRIBUTE_UNUSED;
1074 #endif /* TARGET_ELF_ABI */
1075 /* ===================================================== */
1078 /* Return 1 if OP is a valid S operand for an RS, SI or SS type instruction.
1079 OP is the current operation.
1080 MODE is the current operation mode. */
1083 s_operand (op, mode)
1085 enum machine_mode mode;
1087 extern int volatile_ok;
1088 register enum rtx_code code = GET_CODE (op);
1090 if (CONSTANT_ADDRESS_P (op))
1092 if (mode == VOIDmode || GET_MODE (op) != mode)
1096 register rtx x = XEXP (op, 0);
1098 if (!volatile_ok && op->volatil)
1100 if (REG_P (x) && REG_OK_FOR_BASE_P (x))
1102 if (GET_CODE (x) == PLUS
1103 && REG_P (XEXP (x, 0)) && REG_OK_FOR_BASE_P (XEXP (x, 0))
1104 && GET_CODE (XEXP (x, 1)) == CONST_INT
1105 && (unsigned) INTVAL (XEXP (x, 1)) < 4096)
1112 /* Return 1 if OP is a valid R or S operand for an RS, SI or SS type
1114 OP is the current operation.
1115 MODE is the current operation mode. */
1118 r_or_s_operand (op, mode)
1120 enum machine_mode mode;
1122 extern int volatile_ok;
1123 register enum rtx_code code = GET_CODE (op);
1125 if (CONSTANT_ADDRESS_P (op))
1127 if (mode == VOIDmode || GET_MODE (op) != mode)
1131 else if (code == MEM)
1133 register rtx x = XEXP (op, 0);
1135 if (!volatile_ok && op->volatil)
1137 if (REG_P (x) && REG_OK_FOR_BASE_P (x))
1139 if (GET_CODE (x) == PLUS
1140 && REG_P (XEXP (x, 0)) && REG_OK_FOR_BASE_P (XEXP (x, 0))
1141 && GET_CODE (XEXP (x, 1)) == CONST_INT
1142 && (unsigned) INTVAL (XEXP (x, 1)) < 4096)
1149 /* Some remarks about unsigned_jump_follows_p():
1150 gcc is built around the assumption that branches are signed
1151 or unsigned, whereas the 370 doesn't care; its the compares that
1152 are signed or unsigned. Thus, we need to somehow know if we
1153 need to do a signed or an unsigned compare, and we do this by
1154 looking ahead in the instruction sequence until we find a jump.
1155 We then note whether this jump is signed or unsigned, and do the
1156 compare appropriately. Note that we have to scan ahead indefinitley,
1157 as the gcc optimizer may insert any number of instructions between
1158 the compare and the jump.
1160 Note that using conditional branch expanders seems to be be a more
1161 elegant/correct way of doing this. See, for instance, the Alpha
1162 cmpdi and bgt patterns. Note also that for the i370, various
1163 arithmetic insn's set the condition code as well.
1165 The unsigned_jump_follows_p() routine returns a 1 if the next jump
1166 is unsigned. INSN is the current instruction. */
1169 unsigned_jump_follows_p (insn)
1172 rtx orig_insn = insn;
1175 register rtx tmp_insn;
1178 insn = NEXT_INSN (insn);
1179 if (!insn) fatal_insn ("internal error--no jump follows compare:", orig_insn);
1181 if (GET_CODE (insn) != JUMP_INSN) continue;
1183 tmp_insn = XEXP (insn, 3);
1184 if (GET_CODE (tmp_insn) != SET) continue;
1186 if (GET_CODE (XEXP (tmp_insn, 0)) != PC) continue;
1188 tmp_insn = XEXP (tmp_insn, 1);
1189 if (GET_CODE (tmp_insn) != IF_THEN_ELSE) continue;
1191 /* if we got to here, this instruction is a jump. Is it signed? */
1192 tmp_insn = XEXP (tmp_insn, 0);
1193 coda = GET_CODE (tmp_insn);
1195 return coda != GE && coda != GT && coda != LE && coda != LT;
1201 /* Target hook for assembling integer objects. This version handles all
1202 objects when TARGET_HLASM is defined. */
1205 i370_hlasm_assemble_integer (x, size, aligned_p)
1210 const char *int_format = NULL;
1216 int_format = "\tDC\tX'%02X'\n";
1220 int_format = "\tDC\tX'%04X'\n";
1224 if (GET_CODE (x) == CONST_INT)
1226 fputs ("\tDC\tF'", asm_out_file);
1227 output_addr_const (asm_out_file, x);
1228 fputs ("'\n", asm_out_file);
1232 fputs ("\tDC\tA(", asm_out_file);
1233 output_addr_const (asm_out_file, x);
1234 fputs (")\n", asm_out_file);
1239 if (int_format && GET_CODE (x) == CONST_INT)
1241 fprintf (asm_out_file, int_format, INTVAL (x));
1244 return default_assemble_integer (x, size, aligned_p);
1247 /* Generate the assembly code for function entry. FILE is a stdio
1248 stream to output the code to. SIZE is an int: how many units of
1249 temporary storage to allocate.
1251 Refer to the array `regs_ever_live' to determine which registers to
1252 save; `regs_ever_live[I]' is nonzero if register number I is ever
1253 used in the function. This function is responsible for knowing
1254 which registers should not be saved even if used. */
1257 i370_output_function_prologue (f, l)
1261 #if MACROPROLOGUE == 1
1262 fprintf (f, "* Function %s prologue\n", mvs_function_name);
1263 fprintf (f, "\tEDCPRLG USRDSAL=%d,BASEREG=%d\n",
1264 STACK_POINTER_OFFSET + l - 120 +
1265 current_function_outgoing_args_size, BASE_REGISTER);
1266 #else /* MACROPROLOGUE != 1 */
1267 static int function_label_index = 1;
1268 static int function_first = 0;
1269 static int function_year, function_month, function_day;
1270 static int function_hour, function_minute, function_second;
1272 if (!function_first)
1274 struct tm *function_time;
1277 function_time = localtime (&lcltime);
1278 function_year = function_time->tm_year + 1900;
1279 function_month = function_time->tm_mon + 1;
1280 function_day = function_time->tm_mday;
1281 function_hour = function_time->tm_hour;
1282 function_minute = function_time->tm_min;
1283 function_second = function_time->tm_sec;
1285 fprintf (f, "* Function %s prologue\n", mvs_function_name);
1286 fprintf (f, "FDSE%03d\tDSECT\n", function_label_index);
1287 fprintf (f, "\tDS\tD\n");
1288 fprintf (f, "\tDS\tCL(%d)\n", STACK_POINTER_OFFSET + l
1289 + current_function_outgoing_args_size);
1290 fprintf (f, "\tORG\tFDSE%03d\n", function_label_index);
1291 fprintf (f, "\tDS\tCL(120+8)\n");
1292 fprintf (f, "\tORG\n");
1293 fprintf (f, "\tDS\t0D\n");
1294 fprintf (f, "FDSL%03d\tEQU\t*-FDSE%03d-8\n", function_label_index,
1295 function_label_index);
1296 fprintf (f, "\tDS\t0H\n");
1297 assemble_name (f, mvs_function_name);
1298 fprintf (f, "\tCSECT\n");
1299 fprintf (f, "\tUSING\t*,15\n");
1300 fprintf (f, "\tB\tFENT%03d\n", function_label_index);
1301 fprintf (f, "\tDC\tAL1(FNAM%03d+4-*)\n", function_label_index);
1302 fprintf (f, "\tDC\tX'CE',X'A0',AL1(16)\n");
1303 fprintf (f, "\tDC\tAL4(FPPA%03d)\n", function_label_index);
1304 fprintf (f, "\tDC\tAL4(0)\n");
1305 fprintf (f, "\tDC\tAL4(FDSL%03d)\n", function_label_index);
1306 fprintf (f, "FNAM%03d\tEQU\t*\n", function_label_index);
1307 fprintf (f, "\tDC\tAL2(%d),C'%s'\n", strlen (mvs_function_name),
1309 fprintf (f, "FPPA%03d\tDS\t0F\n", function_label_index);
1310 fprintf (f, "\tDC\tX'03',X'00',X'33',X'00'\n");
1311 fprintf (f, "\tDC\tV(CEESTART)\n");
1312 fprintf (f, "\tDC\tAL4(0)\n");
1313 fprintf (f, "\tDC\tAL4(FTIM%03d)\n", function_label_index);
1314 fprintf (f, "FTIM%03d\tDS\t0F\n", function_label_index);
1315 fprintf (f, "\tDC\tCL4'%d',CL4'%02d%02d',CL6'%02d%02d00'\n",
1316 function_year, function_month, function_day,
1317 function_hour, function_minute);
1318 fprintf (f, "\tDC\tCL2'01',CL4'0100'\n");
1319 fprintf (f, "FENT%03d\tDS\t0H\n", function_label_index);
1320 fprintf (f, "\tSTM\t14,12,12(13)\n");
1321 fprintf (f, "\tL\t2,76(,13)\n");
1322 fprintf (f, "\tL\t0,16(,15)\n");
1323 fprintf (f, "\tALR\t0,2\n");
1324 fprintf (f, "\tCL\t0,12(,12)\n");
1325 fprintf (f, "\tBNH\t*+10\n");
1326 fprintf (f, "\tL\t15,116(,12)\n");
1327 fprintf (f, "\tBALR\t14,15\n");
1328 fprintf (f, "\tL\t15,72(,13)\n");
1329 fprintf (f, "\tSTM\t15,0,72(2)\n");
1330 fprintf (f, "\tMVI\t0(2),X'10'\n");
1331 fprintf (f, "\tST\t2,8(,13)\n ");
1332 fprintf (f, "\tST\t13,4(,2)\n ");
1333 fprintf (f, "\tLR\t13,2\n");
1334 fprintf (f, "\tDROP\t15\n");
1335 fprintf (f, "\tBALR\t%d,0\n", BASE_REGISTER);
1336 fprintf (f, "\tUSING\t*,%d\n", BASE_REGISTER);
1338 function_label_index ++;
1340 if (!function_first)
1342 struct tm *function_time;
1345 function_time = localtime (&lcltime);
1346 function_year = function_time->tm_year + 1900;
1347 function_month = function_time->tm_mon + 1;
1348 function_day = function_time->tm_mday;
1349 function_hour = function_time->tm_hour;
1350 function_minute = function_time->tm_min;
1351 function_second = function_time->tm_sec;
1352 fprintf (f, "PPA2\tDS\t0F\n");
1353 fprintf (f, "\tDC\tX'03',X'00',X'33',X'00'\n");
1354 fprintf (f, "\tDC\tV(CEESTART),A(0)\n");
1355 fprintf (f, "\tDC\tA(CEETIMES)\n");
1356 fprintf (f, "CEETIMES\tDS\t0F\n");
1357 fprintf (f, "\tDC\tCL4'%d',CL4'%02d%02d',CL6'%02d%02d00'\n",
1358 function_year, function_month, function_day,
1359 function_hour, function_minute, function_second);
1360 fprintf (f, "\tDC\tCL2'01',CL4'0100'\n");
1362 fprintf (f, "* Function %s prologue\n", mvs_function_name);
1363 fprintf (f, "FDSD%03d\tDSECT\n", function_label_index);
1364 fprintf (f, "\tDS\tD\n");
1365 fprintf (f, "\tDS\tCL(%d)\n", STACK_POINTER_OFFSET + l
1366 + current_function_outgoing_args_size);
1367 fprintf (f, "\tORG\tFDSD%03d\n", function_label_index);
1368 fprintf (f, "\tDS\tCL(120+8)\n");
1369 fprintf (f, "\tORG\n");
1370 fprintf (f, "\tDS\t0D\n");
1371 fprintf (f, "FDSL%03d\tEQU\t*-FDSD%03d-8\n", function_label_index,
1372 function_label_index);
1373 fprintf (f, "\tDS\t0H\n");
1374 assemble_name (f, mvs_function_name);
1375 fprintf (f, "\tCSECT\n");
1376 fprintf (f, "\tUSING\t*,15\n");
1377 fprintf (f, "\tB\tFPL%03d\n", function_label_index);
1378 fprintf (f, "\tDC\tAL1(FPL%03d+4-*)\n", function_label_index + 1);
1379 fprintf (f, "\tDC\tX'CE',X'A0',AL1(16)\n");
1380 fprintf (f, "\tDC\tAL4(PPA2)\n");
1381 fprintf (f, "\tDC\tAL4(0)\n");
1382 fprintf (f, "\tDC\tAL4(FDSL%03d)\n", function_label_index);
1383 fprintf (f, "FPL%03d\tEQU\t*\n", function_label_index + 1);
1384 fprintf (f, "\tDC\tAL2(%d),C'%s'\n", strlen (mvs_function_name),
1386 fprintf (f, "FPL%03d\tDS\t0H\n", function_label_index);
1387 fprintf (f, "\tSTM\t14,12,12(13)\n");
1388 fprintf (f, "\tL\t2,76(,13)\n");
1389 fprintf (f, "\tL\t0,16(,15)\n");
1390 fprintf (f, "\tALR\t0,2\n");
1391 fprintf (f, "\tCL\t0,12(,12)\n");
1392 fprintf (f, "\tBNH\t*+10\n");
1393 fprintf (f, "\tL\t15,116(,12)\n");
1394 fprintf (f, "\tBALR\t14,15\n");
1395 fprintf (f, "\tL\t15,72(,13)\n");
1396 fprintf (f, "\tSTM\t15,0,72(2)\n");
1397 fprintf (f, "\tMVI\t0(2),X'10'\n");
1398 fprintf (f, "\tST\t2,8(,13)\n ");
1399 fprintf (f, "\tST\t13,4(,2)\n ");
1400 fprintf (f, "\tLR\t13,2\n");
1401 fprintf (f, "\tDROP\t15\n");
1402 fprintf (f, "\tBALR\t%d,0\n", BASE_REGISTER);
1403 fprintf (f, "\tUSING\t*,%d\n", BASE_REGISTER);
1405 function_label_index += 2;
1407 #endif /* MACROPROLOGUE */
1408 fprintf (f, "PG%d\tEQU\t*\n", mvs_page_num );
1409 fprintf (f, "\tLR\t11,1\n");
1410 fprintf (f, "\tL\t%d,=A(PGT%d)\n", PAGE_REGISTER, mvs_page_num);
1411 fprintf (f, "* Function %s code\n", mvs_function_name);
1413 mvs_free_label_list ();
1416 mvs_check_page (f, 0, 0);
1417 function_base_page = mvs_page_num;
1419 /* find all labels in this routine */
1424 i370_globalize_label (stream, name)
1428 char temp[MAX_MVS_LABEL_SIZE + 1];
1429 if (mvs_check_alias (name, temp) == 2)
1430 fprintf (stream, "%s\tALIAS\tC'%s'\n", temp, name);
1431 fputs ("\tENTRY\t", stream);
1432 assemble_name (stream, name);
1433 putc ('\n', stream);
1435 #endif /* TARGET_HLASM */
1438 #ifdef TARGET_ELF_ABI
1440 The 370_function_prolog() routine generates the current ELF ABI ES/390 prolog.
1441 It implements a stack that grows downward.
1442 It performs the following steps:
1443 -- saves the callers non-volatile registers on the callers stack.
1444 -- subtracts stackframe size from the stack pointer.
1445 -- stores backpointer to old caller stack.
1447 XXX hack alert -- if the global var int leaf_function is nonzero,
1448 then this is a leaf, and it might be possible to optimize the prologue
1449 into doing even less, e.g. not grabbing a new stackframe or maybe just a
1450 partial stack frame.
1452 XXX hack alert -- the current stack frame is bloated into twice the
1453 needed size by unused entries. These entries make it marginally
1454 compatible with MVS/OE/USS C environment, but really they're not used
1455 and could probably chopped out. Modifications to i370.md would be needed
1456 also, to quite using addresses 136, 140, etc.
1460 i370_output_function_prologue (f, frame_size)
1462 HOST_WIDE_INT frame_size;
1464 static int function_label_index = 1;
1465 static int function_first = 0;
1466 int stackframe_size, aligned_size;
1468 fprintf (f, "# Function prologue\n");
1469 /* define the stack, put it into its own data segment
1470 FDSE == Function Stack Entry
1471 FDSL == Function Stack Length */
1473 STACK_POINTER_OFFSET + current_function_outgoing_args_size + frame_size;
1474 aligned_size = (stackframe_size + 7) >> 3;
1477 fprintf (f, "# arg_size=0x%x frame_size=0x%x aligned size=0x%x\n",
1478 current_function_outgoing_args_size, frame_size, aligned_size);
1480 fprintf (f, "\t.using\t.,r15\n");
1482 /* Branch to exectuable part of prologue. */
1483 fprintf (f, "\tB\t.LFENT%03d\n", function_label_index);
1485 /* write the length of the stackframe */
1486 fprintf (f, "\t.long\t%d\n", aligned_size);
1488 /* FENT == function prologue entry */
1489 fprintf (f, "\t.balign 2\n.LFENT%03d:\n",
1490 function_label_index);
1492 /* store multiple registers 14,15,0,...12 at 12 bytes from sp */
1493 fprintf (f, "\tSTM\tr14,r12,12(sp)\n");
1495 /* r3 == saved callee stack pointer */
1496 fprintf (f, "\tLR\tr3,sp\n");
1498 /* 4(r15) == stackframe size */
1499 fprintf (f, "\tSL\tsp,4(,r15)\n");
1501 /* r11 points to arg list in callers stackframe; was passed in r2 */
1502 fprintf (f, "\tLR\tr11,r2\n");
1504 /* store callee stack pointer at 8(sp) */
1505 /* fprintf (f, "\tST\tsp,8(,r3)\n "); wasted cycles, no one uses this ... */
1507 /* backchain -- store caller sp at 4(callee_sp) */
1508 fprintf (f, "\tST\tr3,4(,sp)\n ");
1510 fprintf (f, "\t.drop\tr15\n");
1511 /* Place contents of the PSW into r3
1512 that is, place the address of "." into r3 */
1513 fprintf (f, "\tBASR\tr%d,0\n", BASE_REGISTER);
1514 fprintf (f, "\t.using\t.,r%d\n", BASE_REGISTER);
1516 function_label_index ++;
1518 fprintf (f, ".LPG%d:\n", mvs_page_num );
1519 fprintf (f, "\tL\tr%d,=A(.LPGT%d)\n", PAGE_REGISTER, mvs_page_num);
1520 fprintf (f, "# Function code\n");
1522 mvs_free_label_list ();
1525 mvs_check_page (f, 0, 0);
1526 function_base_page = mvs_page_num;
1528 /* find all labels in this routine */
1531 #endif /* TARGET_ELF_ABI */
1533 /* This function generates the assembly code for function exit.
1534 Args are as for output_function_prologue ().
1536 The function epilogue should not depend on the current stack
1537 pointer! It should use the frame pointer only. This is mandatory
1538 because of alloca; we also take advantage of it to omit stack
1539 adjustments before returning. */
1542 i370_output_function_epilogue (file, l)
1544 HOST_WIDE_INT l ATTRIBUTE_UNUSED;
1548 check_label_emit ();
1549 mvs_check_page (file, 14, 0);
1550 fprintf (file, "* Function %s epilogue\n", mvs_function_name);
1553 #if MACROEPILOGUE == 1
1554 fprintf (file, "\tEDCEPIL\n");
1555 #else /* MACROEPILOGUE != 1 */
1556 fprintf (file, "\tL\t13,4(,13)\n");
1557 fprintf (file, "\tL\t14,12(,13)\n");
1558 fprintf (file, "\tLM\t2,12,28(13)\n");
1559 fprintf (file, "\tBALR\t1,14\n");
1560 fprintf (file, "\tDC\tA(");
1561 assemble_name (file, mvs_function_name);
1562 fprintf (file, ")\n" );
1563 #endif /* MACROEPILOGUE */
1565 fprintf (file, "* Function %s literal pool\n", mvs_function_name);
1566 fprintf (file, "\tDS\t0F\n" );
1567 fprintf (file, "\tLTORG\n");
1568 fprintf (file, "* Function %s page table\n", mvs_function_name);
1569 fprintf (file, "\tDS\t0F\n");
1570 fprintf (file, "PGT%d\tEQU\t*\n", function_base_page);
1572 mvs_free_label_list();
1573 for (i = function_base_page; i < mvs_page_num; i++)
1574 fprintf (file, "\tDC\tA(PG%d)\n", i);
1577 /* Mark external references. */
1580 i370_encode_section_info (decl, first)
1582 int first ATTRIBUTE_UNUSED;
1584 if (DECL_EXTERNAL (decl) && TREE_PUBLIC (decl))
1585 SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1;