9d4eb3d4e17544005159388a4549c6bd69716afa
[gcc.git] / gcc / config / i370 / i370.c
1 /* Subroutines for insn-output.c for System/370.
2 Copyright (C) 1989, 93, 95, 97-99, 2000 Free Software Foundation, Inc.
3 Contributed by Jan Stein (jan@cd.chalmers.se).
4 Modified for OS/390 LanguageEnvironment C by Dave Pitts (dpitts@cozx.com)
5 Hacked for Linux-ELF/390 by Linas Vepstas (linas@linas.org)
6
7 This file is part of GNU CC.
8
9 GNU CC is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
12 any later version.
13
14 GNU CC is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with GNU CC; see the file COPYING. If not, write to
21 the Free Software Foundation, 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA. */
23
24 #include "config.h"
25 #include "system.h"
26 #include "rtl.h"
27 #include "tree.h"
28 #include "regs.h"
29 #include "hard-reg-set.h"
30 #include "real.h"
31 #include "insn-config.h"
32 #include "conditions.h"
33 #include "insn-flags.h"
34 #include "output.h"
35 #include "insn-attr.h"
36 #include "function.h"
37 #include "flags.h"
38 #include "recog.h"
39 #include "toplev.h"
40 #include "tm_p.h"
41
42 extern FILE *asm_out_file;
43
44 /* Label node. This structure is used to keep track of labels
45 on the various pages in the current routine.
46 The label_id is the numeric ID of the label,
47 The label_page is the page on which it actually appears,
48 The first_ref_page is the page on which the true first ref appears.
49 The label_addr is an estimate of its location in the current routine,
50 The label_first & last_ref are estimates of where the earliest and
51 latest references to this label occur. */
52
53 typedef struct label_node
54 {
55 struct label_node *label_next;
56 int label_id;
57 int label_page;
58 int first_ref_page;
59
60 int label_addr;
61 int label_first_ref;
62 int label_last_ref;
63 }
64 label_node_t;
65
66 /* Is 1 when a label has been generated and the base register must be reloaded. */
67 int mvs_need_base_reload = 0;
68
69 /* Current function starting base page. */
70 int function_base_page;
71
72 /* Length of the current page code. */
73 int mvs_page_code;
74
75 /* Length of the current page literals. */
76 int mvs_page_lit;
77
78 /* Current function name. */
79 char *mvs_function_name = 0;
80
81 /* Current function name length. */
82 int mvs_function_name_length = 0;
83
84 /* Page number for multi-page functions. */
85 int mvs_page_num = 0;
86
87 /* Label node list anchor. */
88 static label_node_t *label_anchor = 0;
89
90 /* Label node free list anchor. */
91 static label_node_t *free_anchor = 0;
92
93 /* Assembler source file descriptor. */
94 static FILE *assembler_source = 0;
95
96 static label_node_t * mvs_get_label PARAMS ((int));
97 static void i370_label_scan PARAMS ((void));
98
99 /* ===================================================== */
100 /* defines and functions specific to the HLASM assembler */
101 #ifdef TARGET_HLASM
102
103 #ifndef MAX_MVS_LABEL_SIZE
104 #define MAX_MVS_LABEL_SIZE 8
105 #endif
106
107 #define MAX_LONG_LABEL_SIZE 255
108
109 /* Alias node, this structure is used to keep track of aliases to external
110 variables. The IBM assembler allows an alias to an external name
111 that is longer that 8 characters; but only once per assembly.
112 Also, this structure stores the #pragma map info. */
113 typedef struct alias_node
114 {
115 struct alias_node *alias_next;
116 int alias_emitted;
117 char alias_name [MAX_MVS_LABEL_SIZE + 1];
118 char real_name [MAX_LONG_LABEL_SIZE + 1];
119 }
120 alias_node_t;
121
122 /* Alias node list anchor. */
123 static alias_node_t *alias_anchor = 0;
124
125 /* Alias number */
126 #ifdef LONGEXTERNAL
127 static int alias_number = 0;
128 #endif
129
130 /* Define the length of the internal MVS function table. */
131 #define MVS_FUNCTION_TABLE_LENGTH 32
132
133 /* C/370 internal function table. These functions use non-standard linkage
134 and must handled in a special manner. */
135 static const char *const mvs_function_table[MVS_FUNCTION_TABLE_LENGTH] =
136 {
137 #if defined(HOST_EBCDIC) /* Changed for EBCDIC collating sequence */
138 "ceil", "edc_acos", "edc_asin", "edc_atan", "edc_ata2", "edc_cos",
139 "edc_cosh", "edc_erf", "edc_erfc", "edc_exp", "edc_gamm", "edc_lg10",
140 "edc_log", "edc_sin", "edc_sinh", "edc_sqrt", "edc_tan", "edc_tanh",
141 "fabs", "floor", "fmod", "frexp", "hypot", "jn",
142 "j0", "j1", "ldexp", "modf", "pow", "yn",
143 "y0", "y1"
144 #else
145 "ceil", "edc_acos", "edc_asin", "edc_ata2", "edc_atan", "edc_cos",
146 "edc_cosh", "edc_erf", "edc_erfc", "edc_exp", "edc_gamm", "edc_lg10",
147 "edc_log", "edc_sin", "edc_sinh", "edc_sqrt", "edc_tan", "edc_tanh",
148 "fabs", "floor", "fmod", "frexp", "hypot", "j0",
149 "j1", "jn", "ldexp", "modf", "pow", "y0",
150 "y1", "yn"
151 #endif
152 };
153
154 #endif /* TARGET_HLASM */
155 /* ===================================================== */
156
157 /* ASCII to EBCDIC conversion table. */
158 static const unsigned char ascebc[256] =
159 {
160 /*00 NL SH SX EX ET NQ AK BL */
161 0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F,
162 /*08 BS HT LF VT FF CR SO SI */
163 0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
164 /*10 DL D1 D2 D3 D4 NK SN EB */
165 0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26,
166 /*18 CN EM SB EC FS GS RS US */
167 0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D, 0x1E, 0x1F,
168 /*20 SP ! " # $ % & ' */
169 0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D,
170 /*28 ( ) * + , - . / */
171 0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,
172 /*30 0 1 2 3 4 5 6 7 */
173 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
174 /*38 8 9 : ; < = > ? */
175 0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,
176 /*40 @ A B C D E F G */
177 0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
178 /*48 H I J K L M N O */
179 0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
180 /*50 P Q R S T U V W */
181 0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,
182 /*58 X Y Z [ \ ] ^ _ */
183 0xE7, 0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D,
184 /*60 ` a b c d e f g */
185 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
186 /*68 h i j k l m n o */
187 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
188 /*70 p q r s t u v w */
189 0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
190 /*78 x y z { | } ~ DL */
191 0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07,
192 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
193 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
194 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
195 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
196 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
197 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
198 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
199 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
200 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
201 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
202 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
203 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
204 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
205 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
206 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
207 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0xFF
208 };
209
210 /* EBCDIC to ASCII conversion table. */
211 static const unsigned char ebcasc[256] =
212 {
213 /*00 NU SH SX EX PF HT LC DL */
214 0x00, 0x01, 0x02, 0x03, 0x00, 0x09, 0x00, 0x7F,
215 /*08 SM VT FF CR SO SI */
216 0x00, 0x00, 0x00, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
217 /*10 DE D1 D2 TM RS NL BS IL */
218 0x10, 0x11, 0x12, 0x13, 0x14, 0x0A, 0x08, 0x00,
219 /*18 CN EM CC C1 FS GS RS US */
220 0x18, 0x19, 0x00, 0x00, 0x1C, 0x1D, 0x1E, 0x1F,
221 /*20 DS SS FS BP LF EB EC */
222 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x17, 0x1B,
223 /*28 SM C2 EQ AK BL */
224 0x00, 0x00, 0x00, 0x00, 0x05, 0x06, 0x07, 0x00,
225 /*30 SY PN RS UC ET */
226 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
227 /*38 C3 D4 NK SU */
228 0x00, 0x00, 0x00, 0x00, 0x14, 0x15, 0x00, 0x1A,
229 /*40 SP */
230 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
231 /*48 . < ( + | */
232 0x00, 0x00, 0x00, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,
233 /*50 & */
234 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
235 /*58 ! $ * ) ; ^ */
236 0x00, 0x00, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0x5E,
237 /*60 - / */
238 0x2D, 0x2F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
239 /*68 , % _ > ? */
240 0x00, 0x00, 0x00, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
241 /*70 */
242 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
243 /*78 ` : # @ ' = " */
244 0x00, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
245 /*80 a b c d e f g */
246 0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
247 /*88 h i { */
248 0x68, 0x69, 0x00, 0x7B, 0x00, 0x00, 0x00, 0x00,
249 /*90 j k l m n o p */
250 0x00, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
251 /*98 q r } */
252 0x71, 0x72, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x00,
253 /*A0 ~ s t u v w x */
254 0x00, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
255 /*A8 y z [ */
256 0x79, 0x7A, 0x00, 0x00, 0x00, 0x5B, 0x00, 0x00,
257 /*B0 */
258 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
259 /*B8 ] */
260 0x00, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x00, 0x00,
261 /*C0 { A B C D E F G */
262 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
263 /*C8 H I */
264 0x48, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
265 /*D0 } J K L M N O P */
266 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
267 /*D8 Q R */
268 0x51, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
269 /*E0 \ S T U V W X */
270 0x5C, 0x00, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
271 /*E8 Y Z */
272 0x59, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
273 /*F0 0 1 2 3 4 5 6 7 */
274 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
275 /*F8 8 9 */
276 0x38, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF
277 };
278
279 /* Map characters from one character set to another.
280 C is the character to be translated. */
281
282 char
283 mvs_map_char (c)
284 int c;
285 {
286 #if defined(TARGET_EBCDIC) && !defined(HOST_EBCDIC)
287 fprintf (stderr, "mvs_map_char: TE & !HE: c = %02x\n", c);
288 return ascebc[c];
289 #else
290 #if defined(HOST_EBCDIC) && !defined(TARGET_EBCDIC)
291 fprintf (stderr, "mvs_map_char: !TE & HE: c = %02x\n", c);
292 return ebcasc[c];
293 #else
294 fprintf (stderr, "mvs_map_char: !TE & !HE: c = %02x\n", c);
295 return c;
296 #endif
297 #endif
298 }
299
300 /* ===================================================== */
301 /* The following three routines are used to determine whther
302 forward branch is on this page, or is a far jump. We use
303 the "length" attr on an insn [(set_atter "length" "4")]
304 to store the largest possible code length that insn
305 could have. This gives us a hint of the address of a
306 branch destination, and from that, we can work out
307 the length of the jump, and whether its on page or not.
308 */
309
310 /* Return the destination address of a branch. */
311
312 int
313 i370_branch_dest (branch)
314 rtx branch;
315 {
316 rtx dest = SET_SRC (PATTERN (branch));
317 int dest_uid;
318 int dest_addr;
319
320 /* first, compute the estimated address of the branch target */
321 if (GET_CODE (dest) == IF_THEN_ELSE)
322 dest = XEXP (dest, 1);
323 dest = XEXP (dest, 0);
324 dest_uid = INSN_UID (dest);
325 dest_addr = insn_addresses[dest_uid];
326
327 /* next, record the address of this insn as the true addr of first ref */
328 {
329 label_node_t *lp;
330 rtx label = JUMP_LABEL (branch);
331 int labelno = CODE_LABEL_NUMBER (label);
332
333 if (!label || CODE_LABEL != GET_CODE (label)) abort ();
334
335 lp = mvs_get_label (labelno);
336 if (-1 == lp -> first_ref_page) lp->first_ref_page = mvs_page_num;
337 }
338 return dest_addr;
339 }
340
341 int
342 i370_branch_length (insn)
343 rtx insn;
344 {
345 int here, there;
346 here = insn_addresses[INSN_UID (insn)];
347 there = i370_branch_dest (insn);
348 return (there - here);
349 }
350
351
352 int
353 i370_short_branch (insn)
354 rtx insn;
355 {
356 int base_offset;
357
358 base_offset = i370_branch_length(insn);
359 if (0 > base_offset)
360 {
361 base_offset += mvs_page_code;
362 }
363 else
364 {
365 /* avoid bumping into lit pool; use 2x to estimate max possible lits */
366 base_offset *= 2;
367 base_offset += mvs_page_code + mvs_page_lit;
368 }
369
370 /* make a conservative estimate of room left on page */
371 if ((4060 >base_offset) && ( 0 < base_offset)) return 1;
372 return 0;
373 }
374
375 /* The i370_label_scan() routine is supposed to loop over
376 all labels and label references in a compilation unit,
377 and determine whether all label refs appear on the same
378 code page as the label. If they do, then we can avoid
379 a reload of the base register for that label.
380
381 Note that the instruction addresses used here are only
382 approximate, and make the sizes of the jumps appear
383 farther apart then they will actually be. This makes
384 this code far more conservative than it needs to be.
385 */
386
387 #define I370_RECORD_LABEL_REF(label,addr) { \
388 label_node_t *lp; \
389 int labelno = CODE_LABEL_NUMBER (label); \
390 lp = mvs_get_label (labelno); \
391 if (addr < lp -> label_first_ref) lp->label_first_ref = addr; \
392 if (addr > lp -> label_last_ref) lp->label_last_ref = addr; \
393 }
394
395 void
396 i370_label_scan ()
397 {
398 rtx insn;
399 label_node_t *lp;
400 int tablejump_offset = 0;
401
402 for (insn = get_insns(); insn; insn = NEXT_INSN(insn))
403 {
404 int here = insn_addresses[INSN_UID (insn)];
405 enum rtx_code code = GET_CODE(insn);
406
407 /* ??? adjust for tables embedded in the .text section that
408 * the compiler didn't take into account */
409 here += tablejump_offset;
410 insn_addresses[INSN_UID (insn)] = here;
411
412 /* check to see if this insn is a label ... */
413 if (CODE_LABEL == code)
414 {
415 int labelno = CODE_LABEL_NUMBER (insn);
416
417 lp = mvs_get_label (labelno);
418 lp -> label_addr = here;
419 #if 0
420 /* Supposedly, labels are supposed to have circular
421 lists of label-refs that reference them,
422 setup in flow.c, but this does not appear to be the case. */
423 rtx labelref = LABEL_REFS (insn);
424 rtx ref = labelref;
425 do
426 {
427 rtx linsn = CONTAINING_INSN(ref);
428 ref = LABEL_NEXTREF(ref);
429 } while (ref && (ref != labelref));
430 #endif
431 }
432 else
433 if (JUMP_INSN == code)
434 {
435 rtx label = JUMP_LABEL (insn);
436
437 /* If there is no label for this jump, then this
438 had better be a ADDR_VEC or an ADDR_DIFF_VEC
439 and there had better be a vector of labels. */
440 if (!label)
441 {
442 int j;
443 rtx body = PATTERN (insn);
444 if (ADDR_VEC == GET_CODE(body))
445 {
446 for (j=0; j < XVECLEN (body, 0); j++)
447 {
448 rtx lref = XVECEXP (body, 0, j);
449 if (LABEL_REF != GET_CODE (lref)) abort ();
450 label = XEXP (lref,0);
451 if (CODE_LABEL != GET_CODE (label)) abort ();
452 tablejump_offset += 4;
453 here += 4;
454 I370_RECORD_LABEL_REF(label,here);
455 }
456 /* finished with the vector go do next insn */
457 continue;
458 }
459 else
460 if (ADDR_DIFF_VEC == GET_CODE(body))
461 {
462 /* XXX hack alert.
463 Right now, we leave this as a no-op, but strictly speaking,
464 this is incorrect. It is possible that a table-jump
465 driven off of a relative address could take us off-page,
466 to a place where we need to reload the base reg. So really,
467 we need to examing both labels, and compare thier values
468 to the current basereg value.
469
470 More generally, this brings up a troubling issue overall:
471 what happens if a tablejump is split across two pages? I do
472 not beleive that this case is handled correctly at all, and
473 can only lead to horrible results if this were to occur.
474
475 However, the current situation is not any worse than it was
476 last week, and so we punt for now. */
477
478 debug_rtx (insn);
479 for (j=0; j < XVECLEN (body, 0); j++)
480 {
481 }
482 /* finished with the vector go do next insn */
483 continue;
484 }
485 else
486 {
487 /* XXX hack alert.
488 Compiling the execption handling (L_eh) in libgcc2.a will trip
489 up right here, with something that looks like
490 (set (pc) (mem:SI (plus:SI (reg/v:SI 1 r1) (const_int 4))))
491 {indirect_jump}
492 I'm not sure of what leads up to this, but it looks like
493 the makings of a long jump which will surely get us into trouble
494 because the base & page registers don't get reloaded. For now
495 I'm not sure of what to do ... again we punt ... we are not worse
496 off than yesterday. */
497
498 /* print_rtl_single (stdout, insn); */
499 debug_rtx (insn);
500 /* abort(); */
501 continue;
502 }
503 }
504 else
505 {
506 /* At this point, this jump_insn had better be a plain-old
507 ordinary one, grap the label id and go */
508 if (CODE_LABEL != GET_CODE (label)) abort ();
509 I370_RECORD_LABEL_REF(label,here);
510 }
511 }
512
513 /* Sometimes, we take addresses of labels and use them
514 as instruction operands ... these show up as REG_NOTES */
515 else
516 if (INSN == code)
517 {
518 if ('i' == GET_RTX_CLASS (code))
519 {
520 rtx note;
521 for (note = REG_NOTES (insn); note; note = XEXP(note,1))
522 {
523 if (REG_LABEL == REG_NOTE_KIND(note))
524 {
525 rtx label = XEXP (note,0);
526 if (!label || CODE_LABEL != GET_CODE (label)) abort ();
527
528 I370_RECORD_LABEL_REF(label,here);
529 }
530 }
531 }
532 }
533 }
534 }
535
536 /* ===================================================== */
537
538 /* Emit reload of base register if indicated. This is to eliminate multiple
539 reloads when several labels are generated pointing to the same place
540 in the code.
541
542 The page table is written at the end of the function.
543 The entries in the page table look like
544 .LPGT0: // PGT0 EQU *
545 .long .LPG0 // DC A(PG0)
546 .long .LPG1 // DC A(PG1)
547 while the prologue generates
548 L r4,=A(.LPGT0)
549
550 Note that this paging scheme breaks down if a single subroutine
551 has more than about 10MB of code in it ... as long as humans write
552 code, this shouldn't be a problem ...
553 */
554
555 void
556 check_label_emit ()
557 {
558 if (mvs_need_base_reload)
559 {
560 mvs_need_base_reload = 0;
561
562 mvs_page_code += 4;
563 fprintf (assembler_source, "\tL\t%d,%d(,%d)\n",
564 BASE_REGISTER, (mvs_page_num - function_base_page) * 4,
565 PAGE_REGISTER);
566 }
567 }
568
569 /* Add the label to the current page label list. If a free element is available
570 it will be used for the new label. Otherwise, a label element will be
571 allocated from memory.
572 ID is the label number of the label being added to the list. */
573
574 label_node_t *
575 mvs_get_label (id)
576 int id;
577 {
578 label_node_t *lp;
579
580 /* first, lets see if we already go one, if so, use that. */
581 for (lp = label_anchor; lp; lp = lp->label_next)
582 {
583 if (lp->label_id == id) return lp;
584 }
585
586 /* not found, get a new one */
587 if (free_anchor)
588 {
589 lp = free_anchor;
590 free_anchor = lp->label_next;
591 }
592 else
593 {
594 lp = (label_node_t *) xmalloc (sizeof (label_node_t));
595 }
596
597 /* initialize for new label */
598 lp->label_id = id;
599 lp->label_page = -1;
600 lp->label_next = label_anchor;
601 lp->label_first_ref = 2000123123;
602 lp->label_last_ref = -1;
603 lp->label_addr = -1;
604 lp->first_ref_page = -1;
605 label_anchor = lp;
606
607 return lp;
608 }
609
610 void
611 mvs_add_label (id)
612 int id;
613 {
614 label_node_t *lp;
615 int fwd_distance;
616
617 lp = mvs_get_label (id);
618 lp->label_page = mvs_page_num;
619
620 /* OK, we just saw the label. Determine if this label
621 * needs a reload of the base register */
622 if ((-1 != lp->first_ref_page) &&
623 (lp->first_ref_page != mvs_page_num))
624 {
625 /* Yep; the first label_ref was on a different page. */
626 mvs_need_base_reload ++;
627 return;
628 }
629
630 /* Hmm. Try to see if the estimated address of the last
631 label_ref is on the current page. If it is, then we
632 don't need a base reg reload. Note that this estimate
633 is very conservatively handled; we'll tend to have
634 a good bit more reloads than actually needed. Someday,
635 we should tighten the estimates (which are driven by
636 the (set_att "length") insn attibute.
637
638 Currently, we estimate that number of page literals
639 same as number of insns, which is a vast overestimate,
640 esp that the estimate of each insn size is its max size. */
641
642 /* if latest ref comes before label, we are clear */
643 if (lp->label_last_ref < lp->label_addr) return;
644
645 fwd_distance = lp->label_last_ref - lp->label_addr;
646
647 if (mvs_page_code + 2*fwd_distance + mvs_page_lit < 4060) return;
648
649 mvs_need_base_reload ++;
650 }
651
652 /* Check to see if the label is in the list and in the current
653 page. If not found, we have to make worst case assumption
654 that label will be on a different page, and thus will have to
655 generate a load and branch on register. This is rather
656 ugly for forward-jumps, but what can we do? For backward
657 jumps on the same page we can branch directly to address.
658 ID is the label number of the label being checked. */
659
660 int
661 mvs_check_label (id)
662 int id;
663 {
664 label_node_t *lp;
665
666 for (lp = label_anchor; lp; lp = lp->label_next)
667 {
668 if (lp->label_id == id)
669 {
670 if (lp->label_page == mvs_page_num)
671 {
672 return 1;
673 }
674 else
675 {
676 return 0;
677 }
678 }
679 }
680 return 0;
681 }
682
683 /* Get the page on which the label sits. This will be used to
684 determine is a register reload is really needed. */
685
686 int
687 mvs_get_label_page(int id)
688 {
689 label_node_t *lp;
690
691 for (lp = label_anchor; lp; lp = lp->label_next)
692 {
693 if (lp->label_id == id)
694 return lp->label_page;
695 }
696 return -1;
697 }
698
699 /* The label list for the current page freed by linking the list onto the free
700 label element chain. */
701
702 void
703 mvs_free_label_list ()
704 {
705
706 if (label_anchor)
707 {
708 label_node_t *last_lp = label_anchor;
709 while (last_lp->label_next) last_lp = last_lp->label_next;
710 last_lp->label_next = free_anchor;
711 free_anchor = label_anchor;
712 }
713 label_anchor = 0;
714 }
715
716 /* ====================================================================== */
717 /* If the page size limit is reached a new code page is started, and the base
718 register is set to it. This page break point is counted conservatively,
719 most literals that have the same value are collapsed by the assembler.
720 True is returned when a new page is started.
721 FILE is the assembler output file descriptor.
722 CODE is the length, in bytes, of the instruction to be emitted.
723 LIT is the length of the literal to be emitted. */
724
725 #ifdef TARGET_HLASM
726 int
727 mvs_check_page (file, code, lit)
728 FILE *file;
729 int code, lit;
730 {
731 if (file)
732 assembler_source = file;
733
734 if (mvs_page_code + code + mvs_page_lit + lit > MAX_MVS_PAGE_LENGTH)
735 {
736 fprintf (assembler_source, "\tB\tPGE%d\n", mvs_page_num);
737 fprintf (assembler_source, "\tDS\t0F\n");
738 fprintf (assembler_source, "\tLTORG\n");
739 fprintf (assembler_source, "\tDS\t0F\n");
740 fprintf (assembler_source, "PGE%d\tEQU\t*\n", mvs_page_num);
741 fprintf (assembler_source, "\tDROP\t%d\n", BASE_REGISTER);
742 mvs_page_num++;
743 /* Safe to use BASR not BALR, since we are
744 * not switching addressing mode here ... */
745 fprintf (assembler_source, "\tBASR\t%d,0\n", BASE_REGISTER);
746 fprintf (assembler_source, "PG%d\tEQU\t*\n", mvs_page_num);
747 fprintf (assembler_source, "\tUSING\t*,%d\n", BASE_REGISTER);
748 mvs_page_code = code;
749 mvs_page_lit = lit;
750 return 1;
751 }
752 mvs_page_code += code;
753 mvs_page_lit += lit;
754 return 0;
755 }
756 #endif /* TARGET_HLASM */
757
758
759 #ifdef TARGET_ELF_ABI
760 int
761 mvs_check_page (file, code, lit)
762 FILE *file;
763 int code, lit;
764 {
765 if (file)
766 assembler_source = file;
767
768 if (mvs_page_code + code + mvs_page_lit + lit > MAX_MVS_PAGE_LENGTH)
769 {
770 /* hop past the literal pool */
771 fprintf (assembler_source, "\tB\t.LPGE%d\n", mvs_page_num);
772
773 /* dump the literal pool. The .baligns are optional, since
774 * ltorg will align to the size of the largest literal
775 * (which is possibly 8 bytes) */
776 fprintf (assembler_source, "\t.balign\t4\n");
777 fprintf (assembler_source, "\t.LTORG\n");
778 fprintf (assembler_source, "\t.balign\t4\n");
779
780 /* we continue execution here ... */
781 fprintf (assembler_source, ".LPGE%d:\n", mvs_page_num);
782 fprintf (assembler_source, "\t.DROP\t%d\n", BASE_REGISTER);
783 mvs_page_num++;
784
785 /* BASR puts the contents of the PSW into r3
786 * that is, r3 will be loaded with the address of "." */
787 fprintf (assembler_source, "\tBASR\tr%d,0\n", BASE_REGISTER);
788 fprintf (assembler_source, ".LPG%d:\n", mvs_page_num);
789 fprintf (assembler_source, "\t.USING\t.,r%d\n", BASE_REGISTER);
790 mvs_page_code = code;
791 mvs_page_lit = lit;
792 return 1;
793 }
794 mvs_page_code += code;
795 mvs_page_lit += lit;
796 return 0;
797 }
798 #endif /* TARGET_ELF_ABI */
799
800 /* ===================================================== */
801 /* defines and functions specific to the HLASM assembler */
802 #ifdef TARGET_HLASM
803
804 /* Check for C/370 runtime function, they don't use standard calling
805 conventions. True is returned if the function is in the table.
806 NAME is the name of the current function. */
807
808 int
809 mvs_function_check (name)
810 const char *name;
811 {
812 int lower, middle, upper;
813 int i;
814
815 lower = 0;
816 upper = MVS_FUNCTION_TABLE_LENGTH - 1;
817 while (lower <= upper)
818 {
819 middle = (lower + upper) / 2;
820 i = strcmp (name, mvs_function_table[middle]);
821 if (i == 0)
822 return 1;
823 if (i < 0)
824 upper = middle - 1;
825 else
826 lower = middle + 1;
827 }
828 return 0;
829 }
830
831
832 /* Add the alias to the current alias list. */
833
834 void
835 mvs_add_alias (realname, aliasname, emitted)
836 const char *realname;
837 const char *aliasname;
838 int emitted;
839 {
840 alias_node_t *ap;
841
842 ap = (alias_node_t *) xmalloc (sizeof (alias_node_t));
843 strcpy (ap->real_name, realname);
844 strcpy (ap->alias_name, aliasname);
845 ap->alias_emitted = emitted;
846 ap->alias_next = alias_anchor;
847 alias_anchor = ap;
848 }
849
850 /* Check to see if the name needs aliasing */
851
852 int
853 mvs_need_alias (realname)
854 const char *realname;
855 {
856 if (mvs_function_check (realname))
857 return 0;
858 if (strlen (realname) > MAX_MVS_LABEL_SIZE)
859 return 1;
860 if (strchr (realname, '_') != 0)
861 return 1;
862 return 0;
863 }
864
865 /* Get the alias from the list.
866 If 1 is returned then it's in the alias list, 0 if it was not */
867
868 int
869 mvs_get_alias (realname, aliasname)
870 const char *realname;
871 char *aliasname;
872 {
873 #ifdef LONGEXTERNAL
874 alias_node_t *ap;
875
876 for (ap = alias_anchor; ap; ap = ap->alias_next)
877 {
878 if (!strcmp (ap->real_name, realname))
879 {
880 strcpy (aliasname, ap->alias_name);
881 return 1;
882 }
883 }
884 if (mvs_need_alias (realname))
885 {
886 sprintf (aliasname, "ALS%05d", alias_number++);
887 mvs_add_alias (realname, aliasname, 0);
888 return 1;
889 }
890 #else
891 if (strlen (realname) > MAX_MVS_LABEL_SIZE)
892 {
893 strncpy (aliasname, realname, MAX_MVS_LABEL_SIZE);
894 aliasname[MAX_MVS_LABEL_SIZE] = '\0';
895 return 1;
896 }
897 #endif
898 return 0;
899 }
900
901 /* Check to see if the alias is in the list.
902 If 1 is returned then it's in the alias list, 2 it was emitted */
903
904 int
905 mvs_check_alias (realname, aliasname)
906 const char *realname;
907 char *aliasname;
908 {
909 #ifdef LONGEXTERNAL
910 alias_node_t *ap;
911
912 for (ap = alias_anchor; ap; ap = ap->alias_next)
913 {
914 if (!strcmp (ap->real_name, realname))
915 {
916 int rc = (ap->alias_emitted == 1) ? 1 : 2;
917 strcpy (aliasname, ap->alias_name);
918 ap->alias_emitted = 1;
919 return rc;
920 }
921 }
922 if (mvs_need_alias (realname))
923 {
924 sprintf (aliasname, "ALS%05d", alias_number++);
925 mvs_add_alias (realname, aliasname, 0);
926 alias_anchor->alias_emitted = 1;
927 return 2;
928 }
929 #else
930 if (strlen (realname) > MAX_MVS_LABEL_SIZE)
931 {
932 strncpy (aliasname, realname, MAX_MVS_LABEL_SIZE);
933 aliasname[MAX_MVS_LABEL_SIZE] = '\0';
934 return 1;
935 }
936 #endif
937 return 0;
938 }
939
940 /* Called from check_newline via the macro HANDLE_PRAGMA.
941 FINPUT is the source file input stream.
942 NODE is the tree node for the token after the "pragma".
943 The result is 1 if the pragma was handled. */
944
945 int
946 handle_pragma (p_getc, p_ungetc, pname)
947 int (* p_getc) PARAMS ((void));
948 void (* p_ungetc) PARAMS ((int));
949 const char *pname;
950 {
951 int retval = 0;
952 register int c;
953
954 if (strcmp (pname, "map") == 0)
955 {
956 char realname[MAX_LONG_LABEL_SIZE + 1];
957 char aliasname[MAX_MVS_LABEL_SIZE + 1];
958 char *s;
959
960 do {
961 c = p_getc ();
962 } while (c == ' ' || c == '\t');
963
964 if (c == '(')
965 {
966 s = realname;
967 do {
968 c = p_getc ();
969 } while (c == ' ' || c == '\t');
970 if (c == '\n')
971 goto PRAGMA_WARNING;
972 do {
973 *s++ = c;
974 c = p_getc ();
975 } while (ISALNUM(c) || c == '_');
976 if (c == '\n')
977 goto PRAGMA_WARNING;
978 *s = 0;
979
980 if (c == ' ' || c == '\t')
981 do {
982 c = p_getc ();
983 } while (c == ' ' || c == '\t');
984
985 if (c == ',')
986 {
987 do {
988 c = p_getc ();
989 } while (c == ' ' || c == '\t');
990 if (c == '"')
991 {
992 s = aliasname;
993 c = p_getc ();
994 do {
995 if (c == '\\')
996 {
997 int d = 0;
998 do {
999 c = p_getc ();
1000 if (c >= '0' && c <= '7')
1001 d = (d << 3) | (c - '0');
1002 } while (c >= '0' && c <= '7');
1003 p_ungetc (c);
1004 c = d;
1005 if (d < 1 || d > 255)
1006 warning ("Escape value out of range");
1007 #ifndef HOST_EBCDIC
1008 c = ebcasc[c];
1009 #endif
1010 }
1011 *s++ = c;
1012 c = p_getc ();
1013 if (ISSPACE(c) || c == ')')
1014 goto PRAGMA_WARNING;
1015 } while (c != '"');
1016 *s = 0;
1017 if (strlen (aliasname) > MAX_MVS_LABEL_SIZE)
1018 {
1019 warning ("#pragma map alias is too long, truncated");
1020 aliasname[MAX_MVS_LABEL_SIZE] = '\0';
1021 }
1022 do {
1023 c = p_getc ();
1024 } while (c == ' ' || c == '\t');
1025 if (c == ')')
1026 {
1027 mvs_add_alias (realname, aliasname, 1);
1028 retval = 1;
1029 }
1030 else
1031 goto PRAGMA_WARNING;
1032 }
1033 else
1034 goto PRAGMA_WARNING;
1035 }
1036 else
1037 goto PRAGMA_WARNING;
1038
1039 }
1040 else
1041 {
1042 PRAGMA_WARNING:
1043 warning ("#pragma map options are missing or incorrect");
1044 }
1045
1046 }
1047
1048 return retval;
1049 }
1050
1051 /* defines and functions specific to the HLASM assembler */
1052 #endif /* TARGET_HLASM */
1053 /* ===================================================== */
1054 /* ===================================================== */
1055 /* defines and functions specific to the gas assembler */
1056 #ifdef TARGET_ELF_ABI
1057
1058 /* Check for C/370 runtime function, they don't use standard calling
1059 conventions. True is returned if the function is in the table.
1060 NAME is the name of the current function. */
1061 /* no special calling conventions (yet ??) */
1062
1063 int
1064 mvs_function_check (name)
1065 const char *name ATTRIBUTE_UNUSED;
1066 {
1067 return 0;
1068 }
1069
1070 #endif /* TARGET_ELF_ABI */
1071 /* ===================================================== */
1072
1073
1074 /* Return 1 if OP is a valid S operand for an RS, SI or SS type instruction.
1075 OP is the current operation.
1076 MODE is the current operation mode. */
1077
1078 int
1079 s_operand (op, mode)
1080 register rtx op;
1081 enum machine_mode mode;
1082 {
1083 extern int volatile_ok;
1084 register enum rtx_code code = GET_CODE (op);
1085
1086 if (CONSTANT_ADDRESS_P (op))
1087 return 1;
1088 if (mode == VOIDmode || GET_MODE (op) != mode)
1089 return 0;
1090 if (code == MEM)
1091 {
1092 register rtx x = XEXP (op, 0);
1093
1094 if (!volatile_ok && op->volatil)
1095 return 0;
1096 if (REG_P (x) && REG_OK_FOR_BASE_P (x))
1097 return 1;
1098 if (GET_CODE (x) == PLUS
1099 && REG_P (XEXP (x, 0)) && REG_OK_FOR_BASE_P (XEXP (x, 0))
1100 && GET_CODE (XEXP (x, 1)) == CONST_INT
1101 && (unsigned) INTVAL (XEXP (x, 1)) < 4096)
1102 return 1;
1103 }
1104 return 0;
1105 }
1106
1107
1108 /* Return 1 if OP is a valid R or S operand for an RS, SI or SS type
1109 instruction.
1110 OP is the current operation.
1111 MODE is the current operation mode. */
1112
1113 int
1114 r_or_s_operand (op, mode)
1115 register rtx op;
1116 enum machine_mode mode;
1117 {
1118 extern int volatile_ok;
1119 register enum rtx_code code = GET_CODE (op);
1120
1121 if (CONSTANT_ADDRESS_P (op))
1122 return 1;
1123 if (mode == VOIDmode || GET_MODE (op) != mode)
1124 return 0;
1125 if (code == REG)
1126 return 1;
1127 else if (code == MEM)
1128 {
1129 register rtx x = XEXP (op, 0);
1130
1131 if (!volatile_ok && op->volatil)
1132 return 0;
1133 if (REG_P (x) && REG_OK_FOR_BASE_P (x))
1134 return 1;
1135 if (GET_CODE (x) == PLUS
1136 && REG_P (XEXP (x, 0)) && REG_OK_FOR_BASE_P (XEXP (x, 0))
1137 && GET_CODE (XEXP (x, 1)) == CONST_INT
1138 && (unsigned) INTVAL (XEXP (x, 1)) < 4096)
1139 return 1;
1140 }
1141 return 0;
1142 }
1143
1144
1145 /* Some remarks about unsigned_jump_follows_p():
1146 gcc is built around the assumption that branches are signed
1147 or unsigned, whereas the 370 doesn't care; its the compares that
1148 are signed or unsigned. Thus, we need to somehow know if we
1149 need to do a signed or an unsigned compare, and we do this by
1150 looking ahead in the instruction sequence until we find a jump.
1151 We then note whether this jump is signed or unsigned, and do the
1152 compare appropriately. Note that we have to scan ahead indefinitley,
1153 as the gcc optimizer may insert any number of instructions between
1154 the compare and the jump.
1155
1156 Note that using conditional branch expanders seems to be be a more
1157 elegant/correct way of doing this. See, for instance, the Alpha
1158 cmpdi and bgt patterns. Note also that for the i370, various
1159 arithmetic insn's set the condition code as well.
1160
1161 The unsigned_jump_follows_p() routine returns a 1 if the next jump
1162 is unsigned. INSN is the current instruction. */
1163
1164 int
1165 unsigned_jump_follows_p (insn)
1166 register rtx insn;
1167 {
1168 rtx orig_insn = insn;
1169 while (1)
1170 {
1171 register rtx tmp_insn;
1172 enum rtx_code coda;
1173
1174 insn = NEXT_INSN (insn);
1175 if (!insn) fatal_insn ("internal error--no jump follows compare:", orig_insn);
1176
1177 if (GET_CODE (insn) != JUMP_INSN) continue;
1178
1179 tmp_insn = XEXP (insn, 3);
1180 if (GET_CODE (tmp_insn) != SET) continue;
1181
1182 if (GET_CODE (XEXP (tmp_insn, 0)) != PC) continue;
1183
1184 tmp_insn = XEXP (tmp_insn, 1);
1185 if (GET_CODE (tmp_insn) != IF_THEN_ELSE) continue;
1186
1187 /* if we got to here, this instruction is a jump. Is it signed? */
1188 tmp_insn = XEXP (tmp_insn, 0);
1189 coda = GET_CODE (tmp_insn);
1190
1191 return coda != GE && coda != GT && coda != LE && coda != LT;
1192 }
1193 }
1194
1195
1196 #ifdef TARGET_HLASM
1197
1198 void
1199 i370_function_prolog (f, l)
1200 FILE *f;
1201 int l;
1202 {
1203 #if MACROPROLOGUE == 1
1204 fprintf (f, "* Function %s prologue\n", mvs_function_name);
1205 fprintf (f, "\tEDCPRLG USRDSAL=%d,BASEREG=%d\n",
1206 STACK_POINTER_OFFSET + l - 120 +
1207 current_function_outgoing_args_size, BASE_REGISTER);
1208 #else /* MACROPROLOGUE != 1 */
1209 static int function_label_index = 1;
1210 static int function_first = 0;
1211 static int function_year, function_month, function_day;
1212 static int function_hour, function_minute, function_second;
1213 #if defined(LE370)
1214 if (!function_first)
1215 {
1216 struct tm *function_time;
1217 time_t lcltime;
1218 time (&lcltime);
1219 function_time = localtime (&lcltime);
1220 function_year = function_time->tm_year + 1900;
1221 function_month = function_time->tm_mon + 1;
1222 function_day = function_time->tm_mday;
1223 function_hour = function_time->tm_hour;
1224 function_minute = function_time->tm_min;
1225 function_second = function_time->tm_sec;
1226 }
1227 fprintf (f, "* Function %s prologue\n", mvs_function_name);
1228 fprintf (f, "FDSE%03d\tDSECT\n", function_label_index);
1229 fprintf (f, "\tDS\tD\n");
1230 fprintf (f, "\tDS\tCL(%d)\n", STACK_POINTER_OFFSET + l
1231 + current_function_outgoing_args_size);
1232 fprintf (f, "\tORG\tFDSE%03d\n", function_label_index);
1233 fprintf (f, "\tDS\tCL(120+8)\n");
1234 fprintf (f, "\tORG\n");
1235 fprintf (f, "\tDS\t0D\n");
1236 fprintf (f, "FDSL%03d\tEQU\t*-FDSE%03d-8\n", function_label_index,
1237 function_label_index);
1238 fprintf (f, "\tDS\t0H\n");
1239 assemble_name (f, mvs_function_name);
1240 fprintf (f, "\tCSECT\n");
1241 fprintf (f, "\tUSING\t*,15\n");
1242 fprintf (f, "\tB\tFENT%03d\n", function_label_index);
1243 fprintf (f, "\tDC\tAL1(FNAM%03d+4-*)\n", function_label_index);
1244 fprintf (f, "\tDC\tX'CE',X'A0',AL1(16)\n");
1245 fprintf (f, "\tDC\tAL4(FPPA%03d)\n", function_label_index);
1246 fprintf (f, "\tDC\tAL4(0)\n");
1247 fprintf (f, "\tDC\tAL4(FDSL%03d)\n", function_label_index);
1248 fprintf (f, "FNAM%03d\tEQU\t*\n", function_label_index);
1249 fprintf (f, "\tDC\tAL2(%d),C'%s'\n", strlen (mvs_function_name),
1250 mvs_function_name);
1251 fprintf (f, "FPPA%03d\tDS\t0F\n", function_label_index);
1252 fprintf (f, "\tDC\tX'03',X'00',X'33',X'00'\n");
1253 fprintf (f, "\tDC\tV(CEESTART)\n");
1254 fprintf (f, "\tDC\tAL4(0)\n");
1255 fprintf (f, "\tDC\tAL4(FTIM%03d)\n", function_label_index);
1256 fprintf (f, "FTIM%03d\tDS\t0F\n", function_label_index);
1257 fprintf (f, "\tDC\tCL4'%d',CL4'%02d%02d',CL6'%02d%02d00'\n",
1258 function_year, function_month, function_day,
1259 function_hour, function_minute);
1260 fprintf (f, "\tDC\tCL2'01',CL4'0100'\n");
1261 fprintf (f, "FENT%03d\tDS\t0H\n", function_label_index);
1262 fprintf (f, "\tSTM\t14,12,12(13)\n");
1263 fprintf (f, "\tL\t2,76(,13)\n");
1264 fprintf (f, "\tL\t0,16(,15)\n");
1265 fprintf (f, "\tALR\t0,2\n");
1266 fprintf (f, "\tCL\t0,12(,12)\n");
1267 fprintf (f, "\tBNH\t*+10\n");
1268 fprintf (f, "\tL\t15,116(,12)\n");
1269 fprintf (f, "\tBALR\t14,15\n");
1270 fprintf (f, "\tL\t15,72(,13)\n");
1271 fprintf (f, "\tSTM\t15,0,72(2)\n");
1272 fprintf (f, "\tMVI\t0(2),X'10'\n");
1273 fprintf (f, "\tST\t2,8(,13)\n ");
1274 fprintf (f, "\tST\t13,4(,2)\n ");
1275 fprintf (f, "\tLR\t13,2\n");
1276 fprintf (f, "\tDROP\t15\n");
1277 fprintf (f, "\tBALR\t%d,0\n", BASE_REGISTER);
1278 fprintf (f, "\tUSING\t*,%d\n", BASE_REGISTER);
1279 function_first = 1;
1280 function_label_index ++;
1281 #else /* !LE370 */
1282 if (!function_first)
1283 {
1284 struct tm *function_time;
1285 time_t lcltime;
1286 time (&lcltime);
1287 function_time = localtime (&lcltime);
1288 function_year = function_time->tm_year + 1900;
1289 function_month = function_time->tm_mon + 1;
1290 function_day = function_time->tm_mday;
1291 function_hour = function_time->tm_hour;
1292 function_minute = function_time->tm_min;
1293 function_second = function_time->tm_sec;
1294 fprintf (f, "PPA2\tDS\t0F\n");
1295 fprintf (f, "\tDC\tX'03',X'00',X'33',X'00'\n");
1296 fprintf (f, "\tDC\tV(CEESTART),A(0)\n");
1297 fprintf (f, "\tDC\tA(CEETIMES)\n");
1298 fprintf (f, "CEETIMES\tDS\t0F\n");
1299 fprintf (f, "\tDC\tCL4'%d',CL4'%02d%02d',CL6'%02d%02d00'\n",
1300 function_year, function_month, function_day,
1301 function_hour, function_minute, function_second);
1302 fprintf (f, "\tDC\tCL2'01',CL4'0100'\n");
1303 }
1304 fprintf (f, "* Function %s prologue\n", mvs_function_name);
1305 fprintf (f, "FDSD%03d\tDSECT\n", function_label_index);
1306 fprintf (f, "\tDS\tD\n");
1307 fprintf (f, "\tDS\tCL(%d)\n", STACK_POINTER_OFFSET + l
1308 + current_function_outgoing_args_size);
1309 fprintf (f, "\tORG\tFDSD%03d\n", function_label_index);
1310 fprintf (f, "\tDS\tCL(120+8)\n");
1311 fprintf (f, "\tORG\n");
1312 fprintf (f, "\tDS\t0D\n");
1313 fprintf (f, "FDSL%03d\tEQU\t*-FDSD%03d-8\n", function_label_index,
1314 function_label_index);
1315 fprintf (f, "\tDS\t0H\n");
1316 assemble_name (f, mvs_function_name);
1317 fprintf (f, "\tCSECT\n");
1318 fprintf (f, "\tUSING\t*,15\n");
1319 fprintf (f, "\tB\tFPL%03d\n", function_label_index);
1320 fprintf (f, "\tDC\tAL1(FPL%03d+4-*)\n", function_label_index + 1);
1321 fprintf (f, "\tDC\tX'CE',X'A0',AL1(16)\n");
1322 fprintf (f, "\tDC\tAL4(PPA2)\n");
1323 fprintf (f, "\tDC\tAL4(0)\n");
1324 fprintf (f, "\tDC\tAL4(FDSL%03d)\n", function_label_index);
1325 fprintf (f, "FPL%03d\tEQU\t*\n", function_label_index + 1);
1326 fprintf (f, "\tDC\tAL2(%d),C'%s'\n", strlen (mvs_function_name),
1327 mvs_function_name);
1328 fprintf (f, "FPL%03d\tDS\t0H\n", function_label_index);
1329 fprintf (f, "\tSTM\t14,12,12(13)\n");
1330 fprintf (f, "\tL\t2,76(,13)\n");
1331 fprintf (f, "\tL\t0,16(,15)\n");
1332 fprintf (f, "\tALR\t0,2\n");
1333 fprintf (f, "\tCL\t0,12(,12)\n");
1334 fprintf (f, "\tBNH\t*+10\n");
1335 fprintf (f, "\tL\t15,116(,12)\n");
1336 fprintf (f, "\tBALR\t14,15\n");
1337 fprintf (f, "\tL\t15,72(,13)\n");
1338 fprintf (f, "\tSTM\t15,0,72(2)\n");
1339 fprintf (f, "\tMVI\t0(2),X'10'\n");
1340 fprintf (f, "\tST\t2,8(,13)\n ");
1341 fprintf (f, "\tST\t13,4(,2)\n ");
1342 fprintf (f, "\tLR\t13,2\n");
1343 fprintf (f, "\tDROP\t15\n");
1344 fprintf (f, "\tBALR\t%d,0\n", BASE_REGISTER);
1345 fprintf (f, "\tUSING\t*,%d\n", BASE_REGISTER);
1346 function_first = 1;
1347 function_label_index += 2;
1348 #endif /* !LE370 */
1349 #endif /* MACROPROLOGUE */
1350 fprintf (f, "PG%d\tEQU\t*\n", mvs_page_num );
1351 fprintf (f, "\tLR\t11,1\n");
1352 fprintf (f, "\tL\t%d,=A(PGT%d)\n", PAGE_REGISTER, mvs_page_num);
1353 fprintf (f, "* Function %s code\n", mvs_function_name);
1354
1355 mvs_free_label_list ();
1356 mvs_page_code = 6;
1357 mvs_page_lit = 4;
1358 mvs_check_page (f, 0, 0);
1359 function_base_page = mvs_page_num;
1360
1361 /* find all labels in this routine */
1362 i370_label_scan ();
1363 }
1364 #endif /* TARGET_HLASM */
1365
1366
1367 #ifdef TARGET_ELF_ABI
1368 /*
1369 The 370_function_prolog() routine generates the current ELF ABI ES/390 prolog.
1370 It implements a stack that grows downward.
1371 It performs the following steps:
1372 -- saves the callers non-volatile registers on the callers stack.
1373 -- subtracts stackframe size from the stack pointer.
1374 -- stores backpointer to old caller stack.
1375
1376 XXX hack alert -- if the global var int leaf_function is non-zero,
1377 then this is a leaf, and it might be possible to optimize the prologue
1378 into doing even less, e.g. not grabbing a new stackframe or maybe just a
1379 partial stack frame.
1380
1381 XXX hack alert -- the current stack frame is bloated into twice the
1382 needed size by unused entries. These entries make it marginally
1383 compatible with MVS/OE/USS C environment, but really they're not used
1384 and could probably chopped out. Modifications to i370.md would be needed
1385 also, to quite using addresses 136, 140, etc.
1386 */
1387
1388 void
1389 i370_function_prolog (f, frame_size)
1390 FILE *f;
1391 int frame_size;
1392 {
1393 static int function_label_index = 1;
1394 static int function_first = 0;
1395 int stackframe_size, aligned_size;
1396
1397 fprintf (f, "# Function prologue\n");
1398 /* define the stack, put it into its own data segment
1399 FDSE == Function Stack Entry
1400 FDSL == Function Stack Length */
1401 stackframe_size =
1402 STACK_POINTER_OFFSET + current_function_outgoing_args_size + frame_size;
1403 aligned_size = (stackframe_size + 7) >> 3;
1404 aligned_size <<= 3;
1405
1406 fprintf (f, "# arg_size=0x%x frame_size=0x%x aligned size=0x%x\n",
1407 current_function_outgoing_args_size, frame_size, aligned_size);
1408
1409 fprintf (f, "\t.using\t.,r15\n");
1410
1411 /* Branch to exectuable part of prologue. */
1412 fprintf (f, "\tB\t.LFENT%03d\n", function_label_index);
1413
1414 /* write the length of the stackframe */
1415 fprintf (f, "\t.long\t%d\n", aligned_size);
1416
1417 /* FENT == function prologue entry */
1418 fprintf (f, "\t.balign 2\n.LFENT%03d:\n",
1419 function_label_index);
1420
1421 /* store multiple registers 14,15,0,...12 at 12 bytes from sp */
1422 fprintf (f, "\tSTM\tr14,r12,12(sp)\n");
1423
1424 /* r3 == saved callee stack pointer */
1425 fprintf (f, "\tLR\tr3,sp\n");
1426
1427 /* 4(r15) == stackframe size */
1428 fprintf (f, "\tSL\tsp,4(,r15)\n");
1429
1430 /* r11 points to arg list in callers stackframe; was passed in r2 */
1431 fprintf (f, "\tLR\tr11,r2\n");
1432
1433 /* store callee stack pointer at 8(sp) */
1434 /* fprintf (f, "\tST\tsp,8(,r3)\n "); wasted cycles, no one uses this ... */
1435
1436 /* backchain -- store caller sp at 4(callee_sp) */
1437 fprintf (f, "\tST\tr3,4(,sp)\n ");
1438
1439 fprintf (f, "\t.drop\tr15\n");
1440 /* Place contents of the PSW into r3
1441 that is, place the address of "." into r3 */
1442 fprintf (f, "\tBASR\tr%d,0\n", BASE_REGISTER);
1443 fprintf (f, "\t.using\t.,r%d\n", BASE_REGISTER);
1444 function_first = 1;
1445 function_label_index ++;
1446
1447 fprintf (f, ".LPG%d:\n", mvs_page_num );
1448 fprintf (f, "\tL\tr%d,=A(.LPGT%d)\n", PAGE_REGISTER, mvs_page_num);
1449 fprintf (f, "# Function code\n");
1450
1451 mvs_free_label_list ();
1452 mvs_page_code = 6;
1453 mvs_page_lit = 4;
1454 mvs_check_page (f, 0, 0);
1455 function_base_page = mvs_page_num;
1456
1457 /* find all labels in this routine */
1458 i370_label_scan ();
1459 }
1460 #endif /* TARGET_ELF_ABI */