include:
[official-gcc.git] / gcc / config / i370 / i370.c
blobf7df14fb8538880ea48f7d96fab27be203685447
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)
13 any later version.
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. */
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 PARAMS ((int));
103 static void i370_label_scan PARAMS ((void));
104 #ifdef TARGET_HLASM
105 static bool i370_hlasm_assemble_integer PARAMS ((rtx, unsigned int, int));
106 static void i370_globalize_label PARAMS ((FILE *, const char *));
107 #endif
108 static void i370_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
109 static void i370_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
110 static void i370_file_start PARAMS ((void));
111 static void i370_file_end PARAMS ((void));
113 #ifdef LONGEXTERNAL
114 static int mvs_hash_alias PARAMS ((const char *));
115 #endif
116 static void i370_internal_label PARAMS ((FILE *, const char *, unsigned long));
117 static bool i370_rtx_costs PARAMS ((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 == HC_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 == HC_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 /* ===================================================== */
179 #if defined(TARGET_EBCDIC) && HOST_CHARSET == HC_ASCII
180 /* ASCII to EBCDIC conversion table. */
181 static const unsigned char ascebc[256] =
183 /*00 NL SH SX EX ET NQ AK BL */
184 0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F,
185 /*08 BS HT LF VT FF CR SO SI */
186 0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
187 /*10 DL D1 D2 D3 D4 NK SN EB */
188 0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26,
189 /*18 CN EM SB EC FS GS RS US */
190 0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D, 0x1E, 0x1F,
191 /*20 SP ! " # $ % & ' */
192 0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D,
193 /*28 ( ) * + , - . / */
194 0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,
195 /*30 0 1 2 3 4 5 6 7 */
196 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
197 /*38 8 9 : ; < = > ? */
198 0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,
199 /*40 @ A B C D E F G */
200 0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
201 /*48 H I J K L M N O */
202 0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
203 /*50 P Q R S T U V W */
204 0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,
205 /*58 X Y Z [ \ ] ^ _ */
206 0xE7, 0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D,
207 /*60 ` a b c d e f g */
208 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
209 /*68 h i j k l m n o */
210 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
211 /*70 p q r s t u v w */
212 0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
213 /*78 x y z { | } ~ DL */
214 0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07,
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, 0x3F,
224 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
225 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
226 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
227 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
228 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
229 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
230 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0xFF
232 #endif /* target EBCDIC, host ASCII */
234 #if !defined(TARGET_EBCDIC) && HOST_CHARSET == HC_EBCDIC
235 /* EBCDIC to ASCII conversion table. */
236 static const unsigned char ebcasc[256] =
238 /*00 NU SH SX EX PF HT LC DL */
239 0x00, 0x01, 0x02, 0x03, 0x00, 0x09, 0x00, 0x7F,
240 /*08 SM VT FF CR SO SI */
241 0x00, 0x00, 0x00, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
242 /*10 DE D1 D2 TM RS NL BS IL */
243 0x10, 0x11, 0x12, 0x13, 0x14, 0x0A, 0x08, 0x00,
244 /*18 CN EM CC C1 FS GS RS US */
245 0x18, 0x19, 0x00, 0x00, 0x1C, 0x1D, 0x1E, 0x1F,
246 /*20 DS SS FS BP LF EB EC */
247 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x17, 0x1B,
248 /*28 SM C2 EQ AK BL */
249 0x00, 0x00, 0x00, 0x00, 0x05, 0x06, 0x07, 0x00,
250 /*30 SY PN RS UC ET */
251 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
252 /*38 C3 D4 NK SU */
253 0x00, 0x00, 0x00, 0x00, 0x14, 0x15, 0x00, 0x1A,
254 /*40 SP */
255 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
256 /*48 . < ( + | */
257 0x00, 0x00, 0x00, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,
258 /*50 & */
259 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
260 /*58 ! $ * ) ; ^ */
261 0x00, 0x00, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0x5E,
262 /*60 - / */
263 0x2D, 0x2F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
264 /*68 , % _ > ? */
265 0x00, 0x00, 0x00, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
266 /*70 */
267 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
268 /*78 ` : # @ ' = " */
269 0x00, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
270 /*80 a b c d e f g */
271 0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
272 /*88 h i { */
273 0x68, 0x69, 0x00, 0x7B, 0x00, 0x00, 0x00, 0x00,
274 /*90 j k l m n o p */
275 0x00, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
276 /*98 q r } */
277 0x71, 0x72, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x00,
278 /*A0 ~ s t u v w x */
279 0x00, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
280 /*A8 y z [ */
281 0x79, 0x7A, 0x00, 0x00, 0x00, 0x5B, 0x00, 0x00,
282 /*B0 */
283 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
284 /*B8 ] */
285 0x00, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x00, 0x00,
286 /*C0 { A B C D E F G */
287 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
288 /*C8 H I */
289 0x48, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
290 /*D0 } J K L M N O P */
291 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
292 /*D8 Q R */
293 0x51, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
294 /*E0 \ S T U V W X */
295 0x5C, 0x00, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
296 /*E8 Y Z */
297 0x59, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
298 /*F0 0 1 2 3 4 5 6 7 */
299 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
300 /*F8 8 9 */
301 0x38, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF
303 #endif /* target ASCII, host EBCDIC */
305 /* Initialize the GCC target structure. */
306 #ifdef TARGET_HLASM
307 #undef TARGET_ASM_BYTE_OP
308 #define TARGET_ASM_BYTE_OP NULL
309 #undef TARGET_ASM_ALIGNED_HI_OP
310 #define TARGET_ASM_ALIGNED_HI_OP NULL
311 #undef TARGET_ASM_ALIGNED_SI_OP
312 #define TARGET_ASM_ALIGNED_SI_OP NULL
313 #undef TARGET_ASM_INTEGER
314 #define TARGET_ASM_INTEGER i370_hlasm_assemble_integer
315 #undef TARGET_ASM_GLOBALIZE_LABEL
316 #define TARGET_ASM_GLOBALIZE_LABEL i370_globalize_label
317 #endif
319 #undef TARGET_ASM_FUNCTION_PROLOGUE
320 #define TARGET_ASM_FUNCTION_PROLOGUE i370_output_function_prologue
321 #undef TARGET_ASM_FUNCTION_EPILOGUE
322 #define TARGET_ASM_FUNCTION_EPILOGUE i370_output_function_epilogue
323 #undef TARGET_ASM_FILE_START
324 #define TARGET_ASM_FILE_START i370_file_start
325 #undef TARGET_ASM_FILE_END
326 #define TARGET_ASM_FILE_END i370_file_end
327 #undef TARGET_ASM_INTERNAL_LABEL
328 #define TARGET_ASM_INTERNAL_LABEL i370_internal_label
329 #undef TARGET_RTX_COSTS
330 #define TARGET_RTX_COSTS i370_rtx_costs
332 struct gcc_target targetm = TARGET_INITIALIZER;
334 /* Set global variables as needed for the options enabled. */
336 void
337 override_options ()
339 /* We're 370 floating point, not IEEE floating point. */
340 memset (real_format_for_mode, 0, sizeof real_format_for_mode);
341 real_format_for_mode[SFmode - QFmode] = &i370_single_format;
342 real_format_for_mode[DFmode - QFmode] = &i370_double_format;
346 /* Map characters from one character set to another.
347 C is the character to be translated. */
349 char
350 mvs_map_char (c)
351 int c;
353 #if defined(TARGET_EBCDIC) && HOST_CHARSET == HC_ASCII
354 fprintf (stderr, "mvs_map_char: TE & !HE: c = %02x\n", c);
355 return ascebc[c];
356 #else
357 #if !defined(TARGET_EBCDIC) && HOST_CHARSET == HC_EBCDIC
358 fprintf (stderr, "mvs_map_char: !TE & HE: c = %02x\n", c);
359 return ebcasc[c];
360 #else
361 fprintf (stderr, "mvs_map_char: !TE & !HE: c = %02x\n", c);
362 return c;
363 #endif
364 #endif
367 /* ===================================================== */
368 /* The following three routines are used to determine whther
369 forward branch is on this page, or is a far jump. We use
370 the "length" attr on an insn [(set_atter "length" "4")]
371 to store the largest possible code length that insn
372 could have. This gives us a hint of the address of a
373 branch destination, and from that, we can work out
374 the length of the jump, and whether its on page or not.
377 /* Return the destination address of a branch. */
380 i370_branch_dest (branch)
381 rtx branch;
383 rtx dest = SET_SRC (PATTERN (branch));
384 int dest_uid;
385 int dest_addr;
387 /* first, compute the estimated address of the branch target */
388 if (GET_CODE (dest) == IF_THEN_ELSE)
389 dest = XEXP (dest, 1);
390 dest = XEXP (dest, 0);
391 dest_uid = INSN_UID (dest);
392 dest_addr = INSN_ADDRESSES (dest_uid);
394 /* next, record the address of this insn as the true addr of first ref */
396 label_node_t *lp;
397 rtx label = JUMP_LABEL (branch);
398 int labelno = CODE_LABEL_NUMBER (label);
400 if (!label || CODE_LABEL != GET_CODE (label)) abort ();
402 lp = mvs_get_label (labelno);
403 if (-1 == lp -> first_ref_page) lp->first_ref_page = mvs_page_num;
405 return dest_addr;
409 i370_branch_length (insn)
410 rtx insn;
412 int here, there;
413 here = INSN_ADDRESSES (INSN_UID (insn));
414 there = i370_branch_dest (insn);
415 return (there - here);
420 i370_short_branch (insn)
421 rtx insn;
423 int base_offset;
425 base_offset = i370_branch_length(insn);
426 if (0 > base_offset)
428 base_offset += mvs_page_code;
430 else
432 /* avoid bumping into lit pool; use 2x to estimate max possible lits */
433 base_offset *= 2;
434 base_offset += mvs_page_code + mvs_page_lit;
437 /* make a conservative estimate of room left on page */
438 if ((4060 >base_offset) && ( 0 < base_offset)) return 1;
439 return 0;
442 /* The i370_label_scan() routine is supposed to loop over
443 all labels and label references in a compilation unit,
444 and determine whether all label refs appear on the same
445 code page as the label. If they do, then we can avoid
446 a reload of the base register for that label.
448 Note that the instruction addresses used here are only
449 approximate, and make the sizes of the jumps appear
450 farther apart then they will actually be. This makes
451 this code far more conservative than it needs to be.
454 #define I370_RECORD_LABEL_REF(label,addr) { \
455 label_node_t *lp; \
456 int labelno = CODE_LABEL_NUMBER (label); \
457 lp = mvs_get_label (labelno); \
458 if (addr < lp -> label_first_ref) lp->label_first_ref = addr; \
459 if (addr > lp -> label_last_ref) lp->label_last_ref = addr; \
462 static void
463 i370_label_scan ()
465 rtx insn;
466 label_node_t *lp;
467 int tablejump_offset = 0;
469 for (insn = get_insns(); insn; insn = NEXT_INSN(insn))
471 int here = INSN_ADDRESSES (INSN_UID (insn));
472 enum rtx_code code = GET_CODE(insn);
474 /* ??? adjust for tables embedded in the .text section that
475 * the compiler didn't take into account */
476 here += tablejump_offset;
477 INSN_ADDRESSES (INSN_UID (insn)) = here;
479 /* check to see if this insn is a label ... */
480 if (CODE_LABEL == code)
482 int labelno = CODE_LABEL_NUMBER (insn);
484 lp = mvs_get_label (labelno);
485 lp -> label_addr = here;
486 #if 0
487 /* Supposedly, labels are supposed to have circular
488 lists of label-refs that reference them,
489 setup in flow.c, but this does not appear to be the case. */
490 rtx labelref = LABEL_REFS (insn);
491 rtx ref = labelref;
494 rtx linsn = CONTAINING_INSN(ref);
495 ref = LABEL_NEXTREF(ref);
496 } while (ref && (ref != labelref));
497 #endif
499 else
500 if (JUMP_INSN == code)
502 rtx label = JUMP_LABEL (insn);
504 /* If there is no label for this jump, then this
505 had better be a ADDR_VEC or an ADDR_DIFF_VEC
506 and there had better be a vector of labels. */
507 if (!label)
509 int j;
510 rtx body = PATTERN (insn);
511 if (ADDR_VEC == GET_CODE(body))
513 for (j=0; j < XVECLEN (body, 0); j++)
515 rtx lref = XVECEXP (body, 0, j);
516 if (LABEL_REF != GET_CODE (lref)) abort ();
517 label = XEXP (lref,0);
518 if (CODE_LABEL != GET_CODE (label)) abort ();
519 tablejump_offset += 4;
520 here += 4;
521 I370_RECORD_LABEL_REF(label,here);
523 /* finished with the vector go do next insn */
524 continue;
526 else
527 if (ADDR_DIFF_VEC == GET_CODE(body))
529 /* XXX hack alert.
530 Right now, we leave this as a no-op, but strictly speaking,
531 this is incorrect. It is possible that a table-jump
532 driven off of a relative address could take us off-page,
533 to a place where we need to reload the base reg. So really,
534 we need to examing both labels, and compare thier values
535 to the current basereg value.
537 More generally, this brings up a troubling issue overall:
538 what happens if a tablejump is split across two pages? I do
539 not beleive that this case is handled correctly at all, and
540 can only lead to horrible results if this were to occur.
542 However, the current situation is not any worse than it was
543 last week, and so we punt for now. */
545 debug_rtx (insn);
546 for (j=0; j < XVECLEN (body, 0); j++)
549 /* finished with the vector go do next insn */
550 continue;
552 else
554 /* XXX hack alert.
555 Compiling the exception handling (L_eh) in libgcc2.a will trip
556 up right here, with something that looks like
557 (set (pc) (mem:SI (plus:SI (reg/v:SI 1 r1) (const_int 4))))
558 {indirect_jump}
559 I'm not sure of what leads up to this, but it looks like
560 the makings of a long jump which will surely get us into trouble
561 because the base & page registers don't get reloaded. For now
562 I'm not sure of what to do ... again we punt ... we are not worse
563 off than yesterday. */
565 /* print_rtl_single (stdout, insn); */
566 debug_rtx (insn);
567 /* abort(); */
568 continue;
571 else
573 /* At this point, this jump_insn had better be a plain-old
574 ordinary one, grap the label id and go */
575 if (CODE_LABEL != GET_CODE (label)) abort ();
576 I370_RECORD_LABEL_REF(label,here);
580 /* Sometimes, we take addresses of labels and use them
581 as instruction operands ... these show up as REG_NOTES */
582 else
583 if (INSN == code)
585 if ('i' == GET_RTX_CLASS (code))
587 rtx note;
588 for (note = REG_NOTES (insn); note; note = XEXP(note,1))
590 if (REG_LABEL == REG_NOTE_KIND(note))
592 rtx label = XEXP (note,0);
593 if (!label || CODE_LABEL != GET_CODE (label)) abort ();
595 I370_RECORD_LABEL_REF(label,here);
603 /* ===================================================== */
605 /* Emit reload of base register if indicated. This is to eliminate multiple
606 reloads when several labels are generated pointing to the same place
607 in the code.
609 The page table is written at the end of the function.
610 The entries in the page table look like
611 .LPGT0: // PGT0 EQU *
612 .long .LPG0 // DC A(PG0)
613 .long .LPG1 // DC A(PG1)
614 while the prologue generates
615 L r4,=A(.LPGT0)
617 Note that this paging scheme breaks down if a single subroutine
618 has more than about 10MB of code in it ... as long as humans write
619 code, this shouldn't be a problem ...
622 void
623 check_label_emit ()
625 if (mvs_need_base_reload)
627 mvs_need_base_reload = 0;
629 mvs_page_code += 4;
630 fprintf (assembler_source, "\tL\t%d,%d(,%d)\n",
631 BASE_REGISTER, (mvs_page_num - function_base_page) * 4,
632 PAGE_REGISTER);
636 /* Add the label to the current page label list. If a free element is available
637 it will be used for the new label. Otherwise, a label element will be
638 allocated from memory.
639 ID is the label number of the label being added to the list. */
641 static label_node_t *
642 mvs_get_label (id)
643 int id;
645 label_node_t *lp;
647 /* first, lets see if we already go one, if so, use that. */
648 for (lp = label_anchor; lp; lp = lp->label_next)
650 if (lp->label_id == id) return lp;
653 /* not found, get a new one */
654 if (free_anchor)
656 lp = free_anchor;
657 free_anchor = lp->label_next;
659 else
661 lp = (label_node_t *) xmalloc (sizeof (label_node_t));
664 /* initialize for new label */
665 lp->label_id = id;
666 lp->label_page = -1;
667 lp->label_next = label_anchor;
668 lp->label_first_ref = 2000123123;
669 lp->label_last_ref = -1;
670 lp->label_addr = -1;
671 lp->first_ref_page = -1;
672 label_anchor = lp;
674 return lp;
677 void
678 mvs_add_label (id)
679 int id;
681 label_node_t *lp;
682 int fwd_distance;
684 lp = mvs_get_label (id);
685 lp->label_page = mvs_page_num;
687 /* OK, we just saw the label. Determine if this label
688 * needs a reload of the base register */
689 if ((-1 != lp->first_ref_page) &&
690 (lp->first_ref_page != mvs_page_num))
692 /* Yep; the first label_ref was on a different page. */
693 mvs_need_base_reload ++;
694 return;
697 /* Hmm. Try to see if the estimated address of the last
698 label_ref is on the current page. If it is, then we
699 don't need a base reg reload. Note that this estimate
700 is very conservatively handled; we'll tend to have
701 a good bit more reloads than actually needed. Someday,
702 we should tighten the estimates (which are driven by
703 the (set_att "length") insn attibute.
705 Currently, we estimate that number of page literals
706 same as number of insns, which is a vast overestimate,
707 esp that the estimate of each insn size is its max size. */
709 /* if latest ref comes before label, we are clear */
710 if (lp->label_last_ref < lp->label_addr) return;
712 fwd_distance = lp->label_last_ref - lp->label_addr;
714 if (mvs_page_code + 2 * fwd_distance + mvs_page_lit < 4060) return;
716 mvs_need_base_reload ++;
719 /* Check to see if the label is in the list and in the current
720 page. If not found, we have to make worst case assumption
721 that label will be on a different page, and thus will have to
722 generate a load and branch on register. This is rather
723 ugly for forward-jumps, but what can we do? For backward
724 jumps on the same page we can branch directly to address.
725 ID is the label number of the label being checked. */
728 mvs_check_label (id)
729 int id;
731 label_node_t *lp;
733 for (lp = label_anchor; lp; lp = lp->label_next)
735 if (lp->label_id == id)
737 if (lp->label_page == mvs_page_num)
739 return 1;
741 else
743 return 0;
747 return 0;
750 /* Get the page on which the label sits. This will be used to
751 determine is a register reload is really needed. */
753 #if 0
755 mvs_get_label_page(int id)
757 label_node_t *lp;
759 for (lp = label_anchor; lp; lp = lp->label_next)
761 if (lp->label_id == id)
762 return lp->label_page;
764 return -1;
766 #endif
768 /* The label list for the current page freed by linking the list onto the free
769 label element chain. */
771 void
772 mvs_free_label_list ()
775 if (label_anchor)
777 label_node_t *last_lp = label_anchor;
778 while (last_lp->label_next) last_lp = last_lp->label_next;
779 last_lp->label_next = free_anchor;
780 free_anchor = label_anchor;
782 label_anchor = 0;
785 /* ====================================================================== */
786 /* If the page size limit is reached a new code page is started, and the base
787 register is set to it. This page break point is counted conservatively,
788 most literals that have the same value are collapsed by the assembler.
789 True is returned when a new page is started.
790 FILE is the assembler output file descriptor.
791 CODE is the length, in bytes, of the instruction to be emitted.
792 LIT is the length of the literal to be emitted. */
794 #ifdef TARGET_HLASM
796 mvs_check_page (file, code, lit)
797 FILE *file;
798 int code, lit;
800 if (file)
801 assembler_source = file;
803 if (mvs_page_code + code + mvs_page_lit + lit > MAX_MVS_PAGE_LENGTH)
805 fprintf (assembler_source, "\tB\tPGE%d\n", mvs_page_num);
806 fprintf (assembler_source, "\tDS\t0F\n");
807 fprintf (assembler_source, "\tLTORG\n");
808 fprintf (assembler_source, "\tDS\t0F\n");
809 fprintf (assembler_source, "PGE%d\tEQU\t*\n", mvs_page_num);
810 fprintf (assembler_source, "\tDROP\t%d\n", BASE_REGISTER);
811 mvs_page_num++;
812 /* Safe to use BASR not BALR, since we are
813 * not switching addressing mode here ... */
814 fprintf (assembler_source, "\tBASR\t%d,0\n", BASE_REGISTER);
815 fprintf (assembler_source, "PG%d\tEQU\t*\n", mvs_page_num);
816 fprintf (assembler_source, "\tUSING\t*,%d\n", BASE_REGISTER);
817 mvs_page_code = code;
818 mvs_page_lit = lit;
819 return 1;
821 mvs_page_code += code;
822 mvs_page_lit += lit;
823 return 0;
825 #endif /* TARGET_HLASM */
828 #ifdef TARGET_ELF_ABI
830 mvs_check_page (file, code, lit)
831 FILE *file;
832 int code, lit;
834 if (file)
835 assembler_source = file;
837 if (mvs_page_code + code + mvs_page_lit + lit > MAX_MVS_PAGE_LENGTH)
839 /* hop past the literal pool */
840 fprintf (assembler_source, "\tB\t.LPGE%d\n", mvs_page_num);
842 /* dump the literal pool. The .baligns are optional, since
843 * ltorg will align to the size of the largest literal
844 * (which is possibly 8 bytes) */
845 fprintf (assembler_source, "\t.balign\t4\n");
846 fprintf (assembler_source, "\t.LTORG\n");
847 fprintf (assembler_source, "\t.balign\t4\n");
849 /* we continue execution here ... */
850 fprintf (assembler_source, ".LPGE%d:\n", mvs_page_num);
851 fprintf (assembler_source, "\t.DROP\t%d\n", BASE_REGISTER);
852 mvs_page_num++;
854 /* BASR puts the contents of the PSW into r3
855 * that is, r3 will be loaded with the address of "." */
856 fprintf (assembler_source, "\tBASR\tr%d,0\n", BASE_REGISTER);
857 fprintf (assembler_source, ".LPG%d:\n", mvs_page_num);
858 fprintf (assembler_source, "\t.USING\t.,r%d\n", BASE_REGISTER);
859 mvs_page_code = code;
860 mvs_page_lit = lit;
861 return 1;
863 mvs_page_code += code;
864 mvs_page_lit += lit;
865 return 0;
867 #endif /* TARGET_ELF_ABI */
869 /* ===================================================== */
870 /* defines and functions specific to the HLASM assembler */
871 #ifdef TARGET_HLASM
873 /* Check for C/370 runtime function, they don't use standard calling
874 conventions. True is returned if the function is in the table.
875 NAME is the name of the current function. */
878 mvs_function_check (name)
879 const char *name;
881 int lower, middle, upper;
882 int i;
884 lower = 0;
885 upper = MVS_FUNCTION_TABLE_LENGTH - 1;
886 while (lower <= upper)
888 middle = (lower + upper) / 2;
889 i = strcmp (name, mvs_function_table[middle]);
890 if (i == 0)
891 return 1;
892 if (i < 0)
893 upper = middle - 1;
894 else
895 lower = middle + 1;
897 return 0;
900 /* Generate a hash for a given key. */
902 #ifdef LONGEXTERNAL
903 static int
904 mvs_hash_alias (key)
905 const char *key;
907 int h;
908 int i;
909 int l = strlen (key);
911 h = key[0];
912 for (i = 1; i < l; i++)
913 h = ((h * MVS_SET_SIZE) + key[i]) % MVS_HASH_PRIME;
914 return (h);
916 #endif
918 /* Add the alias to the current alias list. */
920 void
921 mvs_add_alias (realname, aliasname, emitted)
922 const char *realname;
923 const char *aliasname;
924 int emitted;
926 alias_node_t *ap;
928 ap = (alias_node_t *) xmalloc (sizeof (alias_node_t));
929 if (strlen (realname) > MAX_LONG_LABEL_SIZE)
931 warning ("real name is too long - alias ignored");
932 return;
934 if (strlen (aliasname) > MAX_MVS_LABEL_SIZE)
936 warning ("alias name is too long - alias ignored");
937 return;
940 strcpy (ap->real_name, realname);
941 strcpy (ap->alias_name, aliasname);
942 ap->alias_emitted = emitted;
943 ap->alias_next = alias_anchor;
944 alias_anchor = ap;
947 /* Check to see if the name needs aliasing. ie. the name is either:
948 1. Longer than 8 characters
949 2. Contains an underscore
950 3. Is mixed case */
953 mvs_need_alias (realname)
954 const char *realname;
956 int i, j = strlen (realname);
958 if (mvs_function_check (realname))
959 return 0;
960 #if 0
961 if (!strcmp (realname, "gccmain"))
962 return 0;
963 if (!strcmp (realname, "main"))
964 return 0;
965 #endif
966 if (j > MAX_MVS_LABEL_SIZE)
967 return 1;
968 if (strchr (realname, '_') != 0)
969 return 1;
970 if (ISUPPER (realname[0]))
972 for (i = 1; i < j; i++)
974 if (ISLOWER (realname[i]))
975 return 1;
978 else
980 for (i = 1; i < j; i++)
982 if (ISUPPER (realname[i]))
983 return 1;
987 return 0;
990 /* Get the alias from the list.
991 If 1 is returned then it's in the alias list, 0 if it was not */
994 mvs_get_alias (realname, aliasname)
995 const char *realname;
996 char *aliasname;
998 #ifdef LONGEXTERNAL
999 alias_node_t *ap;
1001 for (ap = alias_anchor; ap; ap = ap->alias_next)
1003 if (!strcmp (ap->real_name, realname))
1005 strcpy (aliasname, ap->alias_name);
1006 return 1;
1009 if (mvs_need_alias (realname))
1011 char c1, c2;
1013 c1 = realname[0];
1014 c2 = realname[1];
1015 if (ISLOWER (c1)) c1 = TOUPPER (c1);
1016 else if (c1 == '_') c1 = 'A';
1017 if (ISLOWER (c2)) c2 = TOUPPER (c2);
1018 else if (c2 == '_' || c2 == '\0') c2 = '#';
1020 sprintf (aliasname, "%c%c%06d", c1, c2, mvs_hash_alias (realname));
1021 mvs_add_alias (realname, aliasname, 0);
1022 return 1;
1024 #else
1025 if (strlen (realname) > MAX_MVS_LABEL_SIZE)
1027 strncpy (aliasname, realname, MAX_MVS_LABEL_SIZE);
1028 aliasname[MAX_MVS_LABEL_SIZE] = '\0';
1029 return 1;
1031 #endif
1032 return 0;
1035 /* Check to see if the alias is in the list.
1036 If 1 is returned then it's in the alias list, 2 it was emitted */
1039 mvs_check_alias (realname, aliasname)
1040 const char *realname;
1041 char *aliasname;
1043 #ifdef LONGEXTERNAL
1044 alias_node_t *ap;
1046 for (ap = alias_anchor; ap; ap = ap->alias_next)
1048 if (!strcmp (ap->real_name, realname))
1050 int rc = (ap->alias_emitted == 1) ? 1 : 2;
1051 strcpy (aliasname, ap->alias_name);
1052 ap->alias_emitted = 1;
1053 return rc;
1056 if (mvs_need_alias (realname))
1058 char c1, c2;
1060 c1 = realname[0];
1061 c2 = realname[1];
1062 if (ISLOWER (c1)) c1 = TOUPPER (c1);
1063 else if (c1 == '_') c1 = 'A';
1064 if (ISLOWER (c2)) c2 = TOUPPER (c2);
1065 else if (c2 == '_' || c2 == '\0') c2 = '#';
1067 sprintf (aliasname, "%c%c%06d", c1, c2, mvs_hash_alias (realname));
1068 mvs_add_alias (realname, aliasname, 0);
1069 alias_anchor->alias_emitted = 1;
1070 return 2;
1072 #else
1073 if (strlen (realname) > MAX_MVS_LABEL_SIZE)
1075 strncpy (aliasname, realname, MAX_MVS_LABEL_SIZE);
1076 aliasname[MAX_MVS_LABEL_SIZE] = '\0';
1077 return 1;
1079 #endif
1080 return 0;
1083 /* defines and functions specific to the HLASM assembler */
1084 #endif /* TARGET_HLASM */
1085 /* ===================================================== */
1086 /* ===================================================== */
1087 /* defines and functions specific to the gas assembler */
1088 #ifdef TARGET_ELF_ABI
1090 /* Check for C/370 runtime function, they don't use standard calling
1091 conventions. True is returned if the function is in the table.
1092 NAME is the name of the current function. */
1093 /* no special calling conventions (yet ??) */
1096 mvs_function_check (name)
1097 const char *name ATTRIBUTE_UNUSED;
1099 return 0;
1102 #endif /* TARGET_ELF_ABI */
1103 /* ===================================================== */
1106 /* Return 1 if OP is a valid S operand for an RS, SI or SS type instruction.
1107 OP is the current operation.
1108 MODE is the current operation mode. */
1111 s_operand (op, mode)
1112 register rtx op;
1113 enum machine_mode mode;
1115 extern int volatile_ok;
1116 register enum rtx_code code = GET_CODE (op);
1118 if (CONSTANT_ADDRESS_P (op))
1119 return 1;
1120 if (mode == VOIDmode || GET_MODE (op) != mode)
1121 return 0;
1122 if (code == MEM)
1124 register rtx x = XEXP (op, 0);
1126 if (!volatile_ok && op->volatil)
1127 return 0;
1128 if (REG_P (x) && REG_OK_FOR_BASE_P (x))
1129 return 1;
1130 if (GET_CODE (x) == PLUS
1131 && REG_P (XEXP (x, 0)) && REG_OK_FOR_BASE_P (XEXP (x, 0))
1132 && GET_CODE (XEXP (x, 1)) == CONST_INT
1133 && (unsigned) INTVAL (XEXP (x, 1)) < 4096)
1134 return 1;
1136 return 0;
1140 /* Return 1 if OP is a valid R or S operand for an RS, SI or SS type
1141 instruction.
1142 OP is the current operation.
1143 MODE is the current operation mode. */
1146 r_or_s_operand (op, mode)
1147 register rtx op;
1148 enum machine_mode mode;
1150 extern int volatile_ok;
1151 register enum rtx_code code = GET_CODE (op);
1153 if (CONSTANT_ADDRESS_P (op))
1154 return 1;
1155 if (mode == VOIDmode || GET_MODE (op) != mode)
1156 return 0;
1157 if (code == REG)
1158 return 1;
1159 else if (code == MEM)
1161 register rtx x = XEXP (op, 0);
1163 if (!volatile_ok && op->volatil)
1164 return 0;
1165 if (REG_P (x) && REG_OK_FOR_BASE_P (x))
1166 return 1;
1167 if (GET_CODE (x) == PLUS
1168 && REG_P (XEXP (x, 0)) && REG_OK_FOR_BASE_P (XEXP (x, 0))
1169 && GET_CODE (XEXP (x, 1)) == CONST_INT
1170 && (unsigned) INTVAL (XEXP (x, 1)) < 4096)
1171 return 1;
1173 return 0;
1177 /* Some remarks about unsigned_jump_follows_p():
1178 gcc is built around the assumption that branches are signed
1179 or unsigned, whereas the 370 doesn't care; its the compares that
1180 are signed or unsigned. Thus, we need to somehow know if we
1181 need to do a signed or an unsigned compare, and we do this by
1182 looking ahead in the instruction sequence until we find a jump.
1183 We then note whether this jump is signed or unsigned, and do the
1184 compare appropriately. Note that we have to scan ahead indefinitley,
1185 as the gcc optimizer may insert any number of instructions between
1186 the compare and the jump.
1188 Note that using conditional branch expanders seems to be be a more
1189 elegant/correct way of doing this. See, for instance, the Alpha
1190 cmpdi and bgt patterns. Note also that for the i370, various
1191 arithmetic insn's set the condition code as well.
1193 The unsigned_jump_follows_p() routine returns a 1 if the next jump
1194 is unsigned. INSN is the current instruction. */
1197 unsigned_jump_follows_p (insn)
1198 register rtx insn;
1200 rtx orig_insn = insn;
1201 while (1)
1203 register rtx tmp_insn;
1204 enum rtx_code coda;
1206 insn = NEXT_INSN (insn);
1207 if (!insn) fatal_insn ("internal error--no jump follows compare:", orig_insn);
1209 if (GET_CODE (insn) != JUMP_INSN) continue;
1211 tmp_insn = XEXP (insn, 3);
1212 if (GET_CODE (tmp_insn) != SET) continue;
1214 if (GET_CODE (XEXP (tmp_insn, 0)) != PC) continue;
1216 tmp_insn = XEXP (tmp_insn, 1);
1217 if (GET_CODE (tmp_insn) != IF_THEN_ELSE) continue;
1219 /* if we got to here, this instruction is a jump. Is it signed? */
1220 tmp_insn = XEXP (tmp_insn, 0);
1221 coda = GET_CODE (tmp_insn);
1223 return coda != GE && coda != GT && coda != LE && coda != LT;
1227 #ifdef TARGET_HLASM
1229 /* Target hook for assembling integer objects. This version handles all
1230 objects when TARGET_HLASM is defined. */
1232 static bool
1233 i370_hlasm_assemble_integer (x, size, aligned_p)
1234 rtx x;
1235 unsigned int size;
1236 int aligned_p;
1238 const char *int_format = NULL;
1240 if (aligned_p)
1241 switch (size)
1243 case 1:
1244 int_format = "\tDC\tX'%02X'\n";
1245 break;
1247 case 2:
1248 int_format = "\tDC\tX'%04X'\n";
1249 break;
1251 case 4:
1252 if (GET_CODE (x) == CONST_INT)
1254 fputs ("\tDC\tF'", asm_out_file);
1255 output_addr_const (asm_out_file, x);
1256 fputs ("'\n", asm_out_file);
1258 else
1260 fputs ("\tDC\tA(", asm_out_file);
1261 output_addr_const (asm_out_file, x);
1262 fputs (")\n", asm_out_file);
1264 return true;
1267 if (int_format && GET_CODE (x) == CONST_INT)
1269 fprintf (asm_out_file, int_format, INTVAL (x));
1270 return true;
1272 return default_assemble_integer (x, size, aligned_p);
1275 /* Generate the assembly code for function entry. FILE is a stdio
1276 stream to output the code to. SIZE is an int: how many units of
1277 temporary storage to allocate.
1279 Refer to the array `regs_ever_live' to determine which registers to
1280 save; `regs_ever_live[I]' is nonzero if register number I is ever
1281 used in the function. This function is responsible for knowing
1282 which registers should not be saved even if used. */
1284 static void
1285 i370_output_function_prologue (f, l)
1286 FILE *f;
1287 HOST_WIDE_INT l;
1289 #if MACROPROLOGUE == 1
1290 fprintf (f, "* Function %s prologue\n", mvs_function_name);
1291 fprintf (f, "\tEDCPRLG USRDSAL=%d,BASEREG=%d\n",
1292 STACK_POINTER_OFFSET + l - 120 +
1293 current_function_outgoing_args_size, BASE_REGISTER);
1294 #else /* MACROPROLOGUE != 1 */
1295 static int function_label_index = 1;
1296 static int function_first = 0;
1297 static int function_year, function_month, function_day;
1298 static int function_hour, function_minute, function_second;
1299 #if defined(LE370)
1300 if (!function_first)
1302 struct tm *function_time;
1303 time_t lcltime;
1304 time (&lcltime);
1305 function_time = localtime (&lcltime);
1306 function_year = function_time->tm_year + 1900;
1307 function_month = function_time->tm_mon + 1;
1308 function_day = function_time->tm_mday;
1309 function_hour = function_time->tm_hour;
1310 function_minute = function_time->tm_min;
1311 function_second = function_time->tm_sec;
1313 fprintf (f, "* Function %s prologue\n", mvs_function_name);
1314 fprintf (f, "FDSE%03d\tDSECT\n", function_label_index);
1315 fprintf (f, "\tDS\tD\n");
1316 fprintf (f, "\tDS\tCL(" HOST_WIDE_INT_PRINT_DEC ")\n",
1317 STACK_POINTER_OFFSET + l
1318 + current_function_outgoing_args_size);
1319 fprintf (f, "\tORG\tFDSE%03d\n", function_label_index);
1320 fprintf (f, "\tDS\tCL(120+8)\n");
1321 fprintf (f, "\tORG\n");
1322 fprintf (f, "\tDS\t0D\n");
1323 fprintf (f, "FDSL%03d\tEQU\t*-FDSE%03d-8\n", function_label_index,
1324 function_label_index);
1325 fprintf (f, "\tDS\t0H\n");
1326 assemble_name (f, mvs_function_name);
1327 fprintf (f, "\tCSECT\n");
1328 fprintf (f, "\tUSING\t*,15\n");
1329 fprintf (f, "\tB\tFENT%03d\n", function_label_index);
1330 fprintf (f, "\tDC\tAL1(FNAM%03d+4-*)\n", function_label_index);
1331 fprintf (f, "\tDC\tX'CE',X'A0',AL1(16)\n");
1332 fprintf (f, "\tDC\tAL4(FPPA%03d)\n", function_label_index);
1333 fprintf (f, "\tDC\tAL4(0)\n");
1334 fprintf (f, "\tDC\tAL4(FDSL%03d)\n", function_label_index);
1335 fprintf (f, "FNAM%03d\tEQU\t*\n", function_label_index);
1336 fprintf (f, "\tDC\tAL2(%d),C'%s'\n", strlen (mvs_function_name),
1337 mvs_function_name);
1338 fprintf (f, "FPPA%03d\tDS\t0F\n", function_label_index);
1339 fprintf (f, "\tDC\tX'03',X'00',X'33',X'00'\n");
1340 fprintf (f, "\tDC\tV(CEESTART)\n");
1341 fprintf (f, "\tDC\tAL4(0)\n");
1342 fprintf (f, "\tDC\tAL4(FTIM%03d)\n", function_label_index);
1343 fprintf (f, "FTIM%03d\tDS\t0F\n", function_label_index);
1344 fprintf (f, "\tDC\tCL4'%d',CL4'%02d%02d',CL6'%02d%02d00'\n",
1345 function_year, function_month, function_day,
1346 function_hour, function_minute);
1347 fprintf (f, "\tDC\tCL2'01',CL4'0100'\n");
1348 fprintf (f, "FENT%03d\tDS\t0H\n", function_label_index);
1349 fprintf (f, "\tSTM\t14,12,12(13)\n");
1350 fprintf (f, "\tL\t2,76(,13)\n");
1351 fprintf (f, "\tL\t0,16(,15)\n");
1352 fprintf (f, "\tALR\t0,2\n");
1353 fprintf (f, "\tCL\t0,12(,12)\n");
1354 fprintf (f, "\tBNH\t*+10\n");
1355 fprintf (f, "\tL\t15,116(,12)\n");
1356 fprintf (f, "\tBALR\t14,15\n");
1357 fprintf (f, "\tL\t15,72(,13)\n");
1358 fprintf (f, "\tSTM\t15,0,72(2)\n");
1359 fprintf (f, "\tMVI\t0(2),X'10'\n");
1360 fprintf (f, "\tST\t2,8(,13)\n ");
1361 fprintf (f, "\tST\t13,4(,2)\n ");
1362 fprintf (f, "\tLR\t13,2\n");
1363 fprintf (f, "\tDROP\t15\n");
1364 fprintf (f, "\tBALR\t%d,0\n", BASE_REGISTER);
1365 fprintf (f, "\tUSING\t*,%d\n", BASE_REGISTER);
1366 function_first = 1;
1367 function_label_index ++;
1368 #else /* !LE370 */
1369 if (!function_first)
1371 struct tm *function_time;
1372 time_t lcltime;
1373 time (&lcltime);
1374 function_time = localtime (&lcltime);
1375 function_year = function_time->tm_year + 1900;
1376 function_month = function_time->tm_mon + 1;
1377 function_day = function_time->tm_mday;
1378 function_hour = function_time->tm_hour;
1379 function_minute = function_time->tm_min;
1380 function_second = function_time->tm_sec;
1381 fprintf (f, "PPA2\tDS\t0F\n");
1382 fprintf (f, "\tDC\tX'03',X'00',X'33',X'00'\n");
1383 fprintf (f, "\tDC\tV(CEESTART),A(0)\n");
1384 fprintf (f, "\tDC\tA(CEETIMES)\n");
1385 fprintf (f, "CEETIMES\tDS\t0F\n");
1386 fprintf (f, "\tDC\tCL4'%d',CL4'%02d%02d',CL6'%02d%02d00'\n",
1387 function_year, function_month, function_day,
1388 function_hour, function_minute, function_second);
1389 fprintf (f, "\tDC\tCL2'01',CL4'0100'\n");
1391 fprintf (f, "* Function %s prologue\n", mvs_function_name);
1392 fprintf (f, "FDSD%03d\tDSECT\n", function_label_index);
1393 fprintf (f, "\tDS\tD\n");
1394 fprintf (f, "\tDS\tCL(%d)\n", STACK_POINTER_OFFSET + l
1395 + current_function_outgoing_args_size);
1396 fprintf (f, "\tORG\tFDSD%03d\n", function_label_index);
1397 fprintf (f, "\tDS\tCL(120+8)\n");
1398 fprintf (f, "\tORG\n");
1399 fprintf (f, "\tDS\t0D\n");
1400 fprintf (f, "FDSL%03d\tEQU\t*-FDSD%03d-8\n", function_label_index,
1401 function_label_index);
1402 fprintf (f, "\tDS\t0H\n");
1403 assemble_name (f, mvs_function_name);
1404 fprintf (f, "\tCSECT\n");
1405 fprintf (f, "\tUSING\t*,15\n");
1406 fprintf (f, "\tB\tFPL%03d\n", function_label_index);
1407 fprintf (f, "\tDC\tAL1(FPL%03d+4-*)\n", function_label_index + 1);
1408 fprintf (f, "\tDC\tX'CE',X'A0',AL1(16)\n");
1409 fprintf (f, "\tDC\tAL4(PPA2)\n");
1410 fprintf (f, "\tDC\tAL4(0)\n");
1411 fprintf (f, "\tDC\tAL4(FDSL%03d)\n", function_label_index);
1412 fprintf (f, "FPL%03d\tEQU\t*\n", function_label_index + 1);
1413 fprintf (f, "\tDC\tAL2(%d),C'%s'\n", strlen (mvs_function_name),
1414 mvs_function_name);
1415 fprintf (f, "FPL%03d\tDS\t0H\n", function_label_index);
1416 fprintf (f, "\tSTM\t14,12,12(13)\n");
1417 fprintf (f, "\tL\t2,76(,13)\n");
1418 fprintf (f, "\tL\t0,16(,15)\n");
1419 fprintf (f, "\tALR\t0,2\n");
1420 fprintf (f, "\tCL\t0,12(,12)\n");
1421 fprintf (f, "\tBNH\t*+10\n");
1422 fprintf (f, "\tL\t15,116(,12)\n");
1423 fprintf (f, "\tBALR\t14,15\n");
1424 fprintf (f, "\tL\t15,72(,13)\n");
1425 fprintf (f, "\tSTM\t15,0,72(2)\n");
1426 fprintf (f, "\tMVI\t0(2),X'10'\n");
1427 fprintf (f, "\tST\t2,8(,13)\n ");
1428 fprintf (f, "\tST\t13,4(,2)\n ");
1429 fprintf (f, "\tLR\t13,2\n");
1430 fprintf (f, "\tDROP\t15\n");
1431 fprintf (f, "\tBALR\t%d,0\n", BASE_REGISTER);
1432 fprintf (f, "\tUSING\t*,%d\n", BASE_REGISTER);
1433 function_first = 1;
1434 function_label_index += 2;
1435 #endif /* !LE370 */
1436 #endif /* MACROPROLOGUE */
1437 fprintf (f, "PG%d\tEQU\t*\n", mvs_page_num );
1438 fprintf (f, "\tLR\t11,1\n");
1439 fprintf (f, "\tL\t%d,=A(PGT%d)\n", PAGE_REGISTER, mvs_page_num);
1440 fprintf (f, "* Function %s code\n", mvs_function_name);
1442 mvs_free_label_list ();
1443 mvs_page_code = 6;
1444 mvs_page_lit = 4;
1445 mvs_check_page (f, 0, 0);
1446 function_base_page = mvs_page_num;
1448 /* find all labels in this routine */
1449 i370_label_scan ();
1452 static void
1453 i370_globalize_label (stream, name)
1454 FILE *stream;
1455 const char *name;
1457 char temp[MAX_MVS_LABEL_SIZE + 1];
1458 if (mvs_check_alias (name, temp) == 2)
1459 fprintf (stream, "%s\tALIAS\tC'%s'\n", temp, name);
1460 fputs ("\tENTRY\t", stream);
1461 assemble_name (stream, name);
1462 putc ('\n', stream);
1464 #endif /* TARGET_HLASM */
1467 #ifdef TARGET_ELF_ABI
1469 The 370_function_prolog() routine generates the current ELF ABI ES/390 prolog.
1470 It implements a stack that grows downward.
1471 It performs the following steps:
1472 -- saves the callers non-volatile registers on the callers stack.
1473 -- subtracts stackframe size from the stack pointer.
1474 -- stores backpointer to old caller stack.
1476 XXX hack alert -- if the global var int leaf_function is nonzero,
1477 then this is a leaf, and it might be possible to optimize the prologue
1478 into doing even less, e.g. not grabbing a new stackframe or maybe just a
1479 partial stack frame.
1481 XXX hack alert -- the current stack frame is bloated into twice the
1482 needed size by unused entries. These entries make it marginally
1483 compatible with MVS/OE/USS C environment, but really they're not used
1484 and could probably chopped out. Modifications to i370.md would be needed
1485 also, to quite using addresses 136, 140, etc.
1488 static void
1489 i370_output_function_prologue (f, frame_size)
1490 FILE *f;
1491 HOST_WIDE_INT frame_size;
1493 static int function_label_index = 1;
1494 static int function_first = 0;
1495 int stackframe_size, aligned_size;
1497 fprintf (f, "# Function prologue\n");
1498 /* define the stack, put it into its own data segment
1499 FDSE == Function Stack Entry
1500 FDSL == Function Stack Length */
1501 stackframe_size =
1502 STACK_POINTER_OFFSET + current_function_outgoing_args_size + frame_size;
1503 aligned_size = (stackframe_size + 7) >> 3;
1504 aligned_size <<= 3;
1506 fprintf (f, "# arg_size=0x%x frame_size=" HOST_WIDE_INT_PRINT_HEX
1507 " aligned size=0x%x\n",
1508 current_function_outgoing_args_size, frame_size, aligned_size);
1510 fprintf (f, "\t.using\t.,r15\n");
1512 /* Branch to exectuable part of prologue. */
1513 fprintf (f, "\tB\t.LFENT%03d\n", function_label_index);
1515 /* write the length of the stackframe */
1516 fprintf (f, "\t.long\t%d\n", aligned_size);
1518 /* FENT == function prologue entry */
1519 fprintf (f, "\t.balign 2\n.LFENT%03d:\n",
1520 function_label_index);
1522 /* store multiple registers 14,15,0,...12 at 12 bytes from sp */
1523 fprintf (f, "\tSTM\tr14,r12,12(sp)\n");
1525 /* r3 == saved callee stack pointer */
1526 fprintf (f, "\tLR\tr3,sp\n");
1528 /* 4(r15) == stackframe size */
1529 fprintf (f, "\tSL\tsp,4(,r15)\n");
1531 /* r11 points to arg list in callers stackframe; was passed in r2 */
1532 fprintf (f, "\tLR\tr11,r2\n");
1534 /* store callee stack pointer at 8(sp) */
1535 /* fprintf (f, "\tST\tsp,8(,r3)\n "); wasted cycles, no one uses this ... */
1537 /* backchain -- store caller sp at 4(callee_sp) */
1538 fprintf (f, "\tST\tr3,4(,sp)\n ");
1540 fprintf (f, "\t.drop\tr15\n");
1541 /* Place contents of the PSW into r3
1542 that is, place the address of "." into r3 */
1543 fprintf (f, "\tBASR\tr%d,0\n", BASE_REGISTER);
1544 fprintf (f, "\t.using\t.,r%d\n", BASE_REGISTER);
1545 function_first = 1;
1546 function_label_index ++;
1548 fprintf (f, ".LPG%d:\n", mvs_page_num );
1549 fprintf (f, "\tL\tr%d,=A(.LPGT%d)\n", PAGE_REGISTER, mvs_page_num);
1550 fprintf (f, "# Function code\n");
1552 mvs_free_label_list ();
1553 mvs_page_code = 6;
1554 mvs_page_lit = 4;
1555 mvs_check_page (f, 0, 0);
1556 function_base_page = mvs_page_num;
1558 /* find all labels in this routine */
1559 i370_label_scan ();
1561 #endif /* TARGET_ELF_ABI */
1563 /* This function generates the assembly code for function exit.
1564 Args are as for output_function_prologue ().
1566 The function epilogue should not depend on the current stack
1567 pointer! It should use the frame pointer only. This is mandatory
1568 because of alloca; we also take advantage of it to omit stack
1569 adjustments before returning. */
1571 static void
1572 i370_output_function_epilogue (file, l)
1573 FILE *file;
1574 HOST_WIDE_INT l ATTRIBUTE_UNUSED;
1576 int i;
1578 check_label_emit ();
1579 mvs_check_page (file, 14, 0);
1580 fprintf (file, "* Function %s epilogue\n", mvs_function_name);
1581 mvs_page_num++;
1583 #if MACROEPILOGUE == 1
1584 fprintf (file, "\tEDCEPIL\n");
1585 #else /* MACROEPILOGUE != 1 */
1586 fprintf (file, "\tL\t13,4(,13)\n");
1587 fprintf (file, "\tL\t14,12(,13)\n");
1588 fprintf (file, "\tLM\t2,12,28(13)\n");
1589 fprintf (file, "\tBALR\t1,14\n");
1590 fprintf (file, "\tDC\tA(");
1591 assemble_name (file, mvs_function_name);
1592 fprintf (file, ")\n" );
1593 #endif /* MACROEPILOGUE */
1595 fprintf (file, "* Function %s literal pool\n", mvs_function_name);
1596 fprintf (file, "\tDS\t0F\n" );
1597 fprintf (file, "\tLTORG\n");
1598 fprintf (file, "* Function %s page table\n", mvs_function_name);
1599 fprintf (file, "\tDS\t0F\n");
1600 fprintf (file, "PGT%d\tEQU\t*\n", function_base_page);
1602 mvs_free_label_list();
1603 for (i = function_base_page; i < mvs_page_num; i++)
1604 fprintf (file, "\tDC\tA(PG%d)\n", i);
1607 static void
1608 i370_file_start ()
1610 fputs ("\tRMODE\tANY\n\tCSECT\n", asm_out_file);
1613 static void
1614 i370_file_end ()
1616 fputs ("\tEND\n", asm_out_file);
1619 static void
1620 i370_internal_label (stream, prefix, labelno)
1621 FILE *stream;
1622 const char *prefix;
1623 unsigned long labelno;
1625 if (!strcmp (prefix, "L"))
1626 mvs_add_label(labelno);
1628 default_internal_label (stream, prefix, labelno);
1631 static bool
1632 i370_rtx_costs (x, code, outer_code, total)
1633 rtx x;
1634 int code;
1635 int outer_code ATTRIBUTE_UNUSED;
1636 int *total;
1638 switch (code)
1640 case CONST_INT:
1641 if ((unsigned HOST_WIDE_INT) INTVAL (x) < 0xfff)
1643 *total = 1;
1644 return true;
1646 /* FALLTHRU */
1648 case CONST:
1649 case LABEL_REF:
1650 case SYMBOL_REF:
1651 *total = 2;
1652 return true;
1654 case CONST_DOUBLE:
1655 *total = 4;
1656 return true;
1658 default:
1659 return false;