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