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