00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "config.h"
00026 #include "system.h"
00027 #include "rtl.h"
00028 #include "tree.h"
00029 #include "regs.h"
00030 #include "hard-reg-set.h"
00031 #include "real.h"
00032 #include "insn-config.h"
00033 #include "conditions.h"
00034 #include "output.h"
00035 #include "insn-attr.h"
00036 #include "function.h"
00037 #include "expr.h"
00038 #include "flags.h"
00039 #include "recog.h"
00040 #include "toplev.h"
00041 #include "cpplib.h"
00042 #include "tm_p.h"
00043 #include "target.h"
00044 #include "target-def.h"
00045
00046 extern FILE *asm_out_file;
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 typedef struct label_node
00058 {
00059 struct label_node *label_next;
00060 int label_id;
00061 int label_page;
00062 int first_ref_page;
00063
00064 int label_addr;
00065 int label_first_ref;
00066 int label_last_ref;
00067 }
00068 label_node_t;
00069
00070
00071 int mvs_need_base_reload = 0;
00072
00073
00074 int function_base_page;
00075
00076
00077 int mvs_page_code;
00078
00079
00080 int mvs_page_lit;
00081
00082
00083 char *mvs_function_name = 0;
00084
00085
00086 int mvs_function_name_length = 0;
00087
00088
00089 int mvs_page_num = 0;
00090
00091
00092 static label_node_t *label_anchor = 0;
00093
00094
00095 static label_node_t *free_anchor = 0;
00096
00097
00098 static FILE *assembler_source = 0;
00099
00100 static label_node_t * mvs_get_label PARAMS ((int));
00101 static void i370_label_scan PARAMS ((void));
00102 #ifdef TARGET_HLASM
00103 static bool i370_hlasm_assemble_integer PARAMS ((rtx, unsigned int, int));
00104 #endif
00105 static void i370_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
00106 static void i370_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
00107 #ifdef LONGEXTERNAL
00108 static int mvs_hash_alias PARAMS ((const char *));
00109 #endif
00110
00111
00112
00113 #ifdef TARGET_HLASM
00114
00115 #define MVS_HASH_PRIME 999983
00116 #if defined(HOST_EBCDIC)
00117 #define MVS_SET_SIZE 256
00118 #else
00119 #define MVS_SET_SIZE 128
00120 #endif
00121
00122 #ifndef MAX_MVS_LABEL_SIZE
00123 #define MAX_MVS_LABEL_SIZE 8
00124 #endif
00125
00126 #define MAX_LONG_LABEL_SIZE 255
00127
00128
00129
00130
00131
00132 typedef struct alias_node
00133 {
00134 struct alias_node *alias_next;
00135 int alias_emitted;
00136 char alias_name [MAX_MVS_LABEL_SIZE + 1];
00137 char real_name [MAX_LONG_LABEL_SIZE + 1];
00138 }
00139 alias_node_t;
00140
00141
00142 static alias_node_t *alias_anchor = 0;
00143
00144
00145 #define MVS_FUNCTION_TABLE_LENGTH 32
00146
00147
00148
00149 static const char *const mvs_function_table[MVS_FUNCTION_TABLE_LENGTH] =
00150 {
00151 #if defined(HOST_EBCDIC)
00152 "ceil", "edc_acos", "edc_asin", "edc_atan", "edc_ata2", "edc_cos",
00153 "edc_cosh", "edc_erf", "edc_erfc", "edc_exp", "edc_gamm", "edc_lg10",
00154 "edc_log", "edc_sin", "edc_sinh", "edc_sqrt", "edc_tan", "edc_tanh",
00155 "fabs", "floor", "fmod", "frexp", "hypot", "jn",
00156 "j0", "j1", "ldexp", "modf", "pow", "yn",
00157 "y0", "y1"
00158 #else
00159 "ceil", "edc_acos", "edc_asin", "edc_ata2", "edc_atan", "edc_cos",
00160 "edc_cosh", "edc_erf", "edc_erfc", "edc_exp", "edc_gamm", "edc_lg10",
00161 "edc_log", "edc_sin", "edc_sinh", "edc_sqrt", "edc_tan", "edc_tanh",
00162 "fabs", "floor", "fmod", "frexp", "hypot", "j0",
00163 "j1", "jn", "ldexp", "modf", "pow", "y0",
00164 "y1", "yn"
00165 #endif
00166 };
00167
00168 #endif
00169
00170
00171
00172 static const unsigned char ascebc[256] =
00173 {
00174
00175 0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F,
00176
00177 0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
00178
00179 0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26,
00180
00181 0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D, 0x1E, 0x1F,
00182
00183 0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D,
00184
00185 0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,
00186
00187 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
00188
00189 0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,
00190
00191 0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
00192
00193 0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
00194
00195 0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,
00196
00197 0xE7, 0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D,
00198
00199 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
00200
00201 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
00202
00203 0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
00204
00205 0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07,
00206 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
00207 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
00208 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
00209 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
00210 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
00211 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
00212 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
00213 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
00214 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
00215 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
00216 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
00217 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
00218 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
00219 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
00220 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
00221 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0xFF
00222 };
00223
00224
00225 static const unsigned char ebcasc[256] =
00226 {
00227
00228 0x00, 0x01, 0x02, 0x03, 0x00, 0x09, 0x00, 0x7F,
00229
00230 0x00, 0x00, 0x00, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
00231
00232 0x10, 0x11, 0x12, 0x13, 0x14, 0x0A, 0x08, 0x00,
00233
00234 0x18, 0x19, 0x00, 0x00, 0x1C, 0x1D, 0x1E, 0x1F,
00235
00236 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x17, 0x1B,
00237
00238 0x00, 0x00, 0x00, 0x00, 0x05, 0x06, 0x07, 0x00,
00239
00240 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
00241
00242 0x00, 0x00, 0x00, 0x00, 0x14, 0x15, 0x00, 0x1A,
00243
00244 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00245
00246 0x00, 0x00, 0x00, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,
00247
00248 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00249
00250 0x00, 0x00, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0x5E,
00251
00252 0x2D, 0x2F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00253
00254 0x00, 0x00, 0x00, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
00255
00256 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00257
00258 0x00, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
00259
00260 0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
00261
00262 0x68, 0x69, 0x00, 0x7B, 0x00, 0x00, 0x00, 0x00,
00263
00264 0x00, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
00265
00266 0x71, 0x72, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x00,
00267
00268 0x00, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
00269
00270 0x79, 0x7A, 0x00, 0x00, 0x00, 0x5B, 0x00, 0x00,
00271
00272 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00273
00274 0x00, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x00, 0x00,
00275
00276 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
00277
00278 0x48, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00279
00280 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
00281
00282 0x51, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00283
00284 0x5C, 0x00, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
00285
00286 0x59, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00287
00288 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
00289
00290 0x38, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF
00291 };
00292
00293
00294 #ifdef TARGET_HLASM
00295 #undef TARGET_ASM_BYTE_OP
00296 #define TARGET_ASM_BYTE_OP NULL
00297 #undef TARGET_ASM_ALIGNED_HI_OP
00298 #define TARGET_ASM_ALIGNED_HI_OP NULL
00299 #undef TARGET_ASM_ALIGNED_SI_OP
00300 #define TARGET_ASM_ALIGNED_SI_OP NULL
00301 #undef TARGET_ASM_INTEGER
00302 #define TARGET_ASM_INTEGER i370_hlasm_assemble_integer
00303 #endif
00304
00305 #undef TARGET_ASM_FUNCTION_PROLOGUE
00306 #define TARGET_ASM_FUNCTION_PROLOGUE i370_output_function_prologue
00307 #undef TARGET_ASM_FUNCTION_EPILOGUE
00308 #define TARGET_ASM_FUNCTION_EPILOGUE i370_output_function_epilogue
00309
00310 struct gcc_target targetm = TARGET_INITIALIZER;
00311
00312
00313
00314
00315 char
00316 mvs_map_char (c)
00317 int c;
00318 {
00319 #if defined(TARGET_EBCDIC) && !defined(HOST_EBCDIC)
00320 fprintf (stderr, "mvs_map_char: TE & !HE: c = %02x\n", c);
00321 return ascebc[c];
00322 #else
00323 #if defined(HOST_EBCDIC) && !defined(TARGET_EBCDIC)
00324 fprintf (stderr, "mvs_map_char: !TE & HE: c = %02x\n", c);
00325 return ebcasc[c];
00326 #else
00327 fprintf (stderr, "mvs_map_char: !TE & !HE: c = %02x\n", c);
00328 return c;
00329 #endif
00330 #endif
00331 }
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345 int
00346 i370_branch_dest (branch)
00347 rtx branch;
00348 {
00349 rtx dest = SET_SRC (PATTERN (branch));
00350 int dest_uid;
00351 int dest_addr;
00352
00353
00354 if (GET_CODE (dest) == IF_THEN_ELSE)
00355 dest = XEXP (dest, 1);
00356 dest = XEXP (dest, 0);
00357 dest_uid = INSN_UID (dest);
00358 dest_addr = INSN_ADDRESSES (dest_uid);
00359
00360
00361 {
00362 label_node_t *lp;
00363 rtx label = JUMP_LABEL (branch);
00364 int labelno = CODE_LABEL_NUMBER (label);
00365
00366 if (!label || CODE_LABEL != GET_CODE (label)) abort ();
00367
00368 lp = mvs_get_label (labelno);
00369 if (-1 == lp -> first_ref_page) lp->first_ref_page = mvs_page_num;
00370 }
00371 return dest_addr;
00372 }
00373
00374 int
00375 i370_branch_length (insn)
00376 rtx insn;
00377 {
00378 int here, there;
00379 here = INSN_ADDRESSES (INSN_UID (insn));
00380 there = i370_branch_dest (insn);
00381 return (there - here);
00382 }
00383
00384
00385 int
00386 i370_short_branch (insn)
00387 rtx insn;
00388 {
00389 int base_offset;
00390
00391 base_offset = i370_branch_length(insn);
00392 if (0 > base_offset)
00393 {
00394 base_offset += mvs_page_code;
00395 }
00396 else
00397 {
00398
00399 base_offset *= 2;
00400 base_offset += mvs_page_code + mvs_page_lit;
00401 }
00402
00403
00404 if ((4060 >base_offset) && ( 0 < base_offset)) return 1;
00405 return 0;
00406 }
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420 #define I370_RECORD_LABEL_REF(label,addr) { \
00421 label_node_t *lp; \
00422 int labelno = CODE_LABEL_NUMBER (label); \
00423 lp = mvs_get_label (labelno); \
00424 if (addr < lp -> label_first_ref) lp->label_first_ref = addr; \
00425 if (addr > lp -> label_last_ref) lp->label_last_ref = addr; \
00426 }
00427
00428 static void
00429 i370_label_scan ()
00430 {
00431 rtx insn;
00432 label_node_t *lp;
00433 int tablejump_offset = 0;
00434
00435 for (insn = get_insns(); insn; insn = NEXT_INSN(insn))
00436 {
00437 int here = INSN_ADDRESSES (INSN_UID (insn));
00438 enum rtx_code code = GET_CODE(insn);
00439
00440
00441
00442 here += tablejump_offset;
00443 INSN_ADDRESSES (INSN_UID (insn)) = here;
00444
00445
00446 if (CODE_LABEL == code)
00447 {
00448 int labelno = CODE_LABEL_NUMBER (insn);
00449
00450 lp = mvs_get_label (labelno);
00451 lp -> label_addr = here;
00452 #if 0
00453
00454
00455
00456 rtx labelref = LABEL_REFS (insn);
00457 rtx ref = labelref;
00458 do
00459 {
00460 rtx linsn = CONTAINING_INSN(ref);
00461 ref = LABEL_NEXTREF(ref);
00462 } while (ref && (ref != labelref));
00463 #endif
00464 }
00465 else
00466 if (JUMP_INSN == code)
00467 {
00468 rtx label = JUMP_LABEL (insn);
00469
00470
00471
00472
00473 if (!label)
00474 {
00475 int j;
00476 rtx body = PATTERN (insn);
00477 if (ADDR_VEC == GET_CODE(body))
00478 {
00479 for (j=0; j < XVECLEN (body, 0); j++)
00480 {
00481 rtx lref = XVECEXP (body, 0, j);
00482 if (LABEL_REF != GET_CODE (lref)) abort ();
00483 label = XEXP (lref,0);
00484 if (CODE_LABEL != GET_CODE (label)) abort ();
00485 tablejump_offset += 4;
00486 here += 4;
00487 I370_RECORD_LABEL_REF(label,here);
00488 }
00489
00490 continue;
00491 }
00492 else
00493 if (ADDR_DIFF_VEC == GET_CODE(body))
00494 {
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511 debug_rtx (insn);
00512 for (j=0; j < XVECLEN (body, 0); j++)
00513 {
00514 }
00515
00516 continue;
00517 }
00518 else
00519 {
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532 debug_rtx (insn);
00533
00534 continue;
00535 }
00536 }
00537 else
00538 {
00539
00540
00541 if (CODE_LABEL != GET_CODE (label)) abort ();
00542 I370_RECORD_LABEL_REF(label,here);
00543 }
00544 }
00545
00546
00547
00548 else
00549 if (INSN == code)
00550 {
00551 if ('i' == GET_RTX_CLASS (code))
00552 {
00553 rtx note;
00554 for (note = REG_NOTES (insn); note; note = XEXP(note,1))
00555 {
00556 if (REG_LABEL == REG_NOTE_KIND(note))
00557 {
00558 rtx label = XEXP (note,0);
00559 if (!label || CODE_LABEL != GET_CODE (label)) abort ();
00560
00561 I370_RECORD_LABEL_REF(label,here);
00562 }
00563 }
00564 }
00565 }
00566 }
00567 }
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588 void
00589 check_label_emit ()
00590 {
00591 if (mvs_need_base_reload)
00592 {
00593 mvs_need_base_reload = 0;
00594
00595 mvs_page_code += 4;
00596 fprintf (assembler_source, "\tL\t%d,%d(,%d)\n",
00597 BASE_REGISTER, (mvs_page_num - function_base_page) * 4,
00598 PAGE_REGISTER);
00599 }
00600 }
00601
00602
00603
00604
00605
00606
00607 static label_node_t *
00608 mvs_get_label (id)
00609 int id;
00610 {
00611 label_node_t *lp;
00612
00613
00614 for (lp = label_anchor; lp; lp = lp->label_next)
00615 {
00616 if (lp->label_id == id) return lp;
00617 }
00618
00619
00620 if (free_anchor)
00621 {
00622 lp = free_anchor;
00623 free_anchor = lp->label_next;
00624 }
00625 else
00626 {
00627 lp = (label_node_t *) xmalloc (sizeof (label_node_t));
00628 }
00629
00630
00631 lp->label_id = id;
00632 lp->label_page = -1;
00633 lp->label_next = label_anchor;
00634 lp->label_first_ref = 2000123123;
00635 lp->label_last_ref = -1;
00636 lp->label_addr = -1;
00637 lp->first_ref_page = -1;
00638 label_anchor = lp;
00639
00640 return lp;
00641 }
00642
00643 void
00644 mvs_add_label (id)
00645 int id;
00646 {
00647 label_node_t *lp;
00648 int fwd_distance;
00649
00650 lp = mvs_get_label (id);
00651 lp->label_page = mvs_page_num;
00652
00653
00654
00655 if ((-1 != lp->first_ref_page) &&
00656 (lp->first_ref_page != mvs_page_num))
00657 {
00658
00659 mvs_need_base_reload ++;
00660 return;
00661 }
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676 if (lp->label_last_ref < lp->label_addr) return;
00677
00678 fwd_distance = lp->label_last_ref - lp->label_addr;
00679
00680 if (mvs_page_code + 2 * fwd_distance + mvs_page_lit < 4060) return;
00681
00682 mvs_need_base_reload ++;
00683 }
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693 int
00694 mvs_check_label (id)
00695 int id;
00696 {
00697 label_node_t *lp;
00698
00699 for (lp = label_anchor; lp; lp = lp->label_next)
00700 {
00701 if (lp->label_id == id)
00702 {
00703 if (lp->label_page == mvs_page_num)
00704 {
00705 return 1;
00706 }
00707 else
00708 {
00709 return 0;
00710 }
00711 }
00712 }
00713 return 0;
00714 }
00715
00716
00717
00718
00719 #if 0
00720 int
00721 mvs_get_label_page(int id)
00722 {
00723 label_node_t *lp;
00724
00725 for (lp = label_anchor; lp; lp = lp->label_next)
00726 {
00727 if (lp->label_id == id)
00728 return lp->label_page;
00729 }
00730 return -1;
00731 }
00732 #endif
00733
00734
00735
00736
00737 void
00738 mvs_free_label_list ()
00739 {
00740
00741 if (label_anchor)
00742 {
00743 label_node_t *last_lp = label_anchor;
00744 while (last_lp->label_next) last_lp = last_lp->label_next;
00745 last_lp->label_next = free_anchor;
00746 free_anchor = label_anchor;
00747 }
00748 label_anchor = 0;
00749 }
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760 #ifdef TARGET_HLASM
00761 int
00762 mvs_check_page (file, code, lit)
00763 FILE *file;
00764 int code, lit;
00765 {
00766 if (file)
00767 assembler_source = file;
00768
00769 if (mvs_page_code + code + mvs_page_lit + lit > MAX_MVS_PAGE_LENGTH)
00770 {
00771 fprintf (assembler_source, "\tB\tPGE%d\n", mvs_page_num);
00772 fprintf (assembler_source, "\tDS\t0F\n");
00773 fprintf (assembler_source, "\tLTORG\n");
00774 fprintf (assembler_source, "\tDS\t0F\n");
00775 fprintf (assembler_source, "PGE%d\tEQU\t*\n", mvs_page_num);
00776 fprintf (assembler_source, "\tDROP\t%d\n", BASE_REGISTER);
00777 mvs_page_num++;
00778
00779
00780 fprintf (assembler_source, "\tBASR\t%d,0\n", BASE_REGISTER);
00781 fprintf (assembler_source, "PG%d\tEQU\t*\n", mvs_page_num);
00782 fprintf (assembler_source, "\tUSING\t*,%d\n", BASE_REGISTER);
00783 mvs_page_code = code;
00784 mvs_page_lit = lit;
00785 return 1;
00786 }
00787 mvs_page_code += code;
00788 mvs_page_lit += lit;
00789 return 0;
00790 }
00791 #endif
00792
00793
00794 #ifdef TARGET_ELF_ABI
00795 int
00796 mvs_check_page (file, code, lit)
00797 FILE *file;
00798 int code, lit;
00799 {
00800 if (file)
00801 assembler_source = file;
00802
00803 if (mvs_page_code + code + mvs_page_lit + lit > MAX_MVS_PAGE_LENGTH)
00804 {
00805
00806 fprintf (assembler_source, "\tB\t.LPGE%d\n", mvs_page_num);
00807
00808
00809
00810
00811 fprintf (assembler_source, "\t.balign\t4\n");
00812 fprintf (assembler_source, "\t.LTORG\n");
00813 fprintf (assembler_source, "\t.balign\t4\n");
00814
00815
00816 fprintf (assembler_source, ".LPGE%d:\n", mvs_page_num);
00817 fprintf (assembler_source, "\t.DROP\t%d\n", BASE_REGISTER);
00818 mvs_page_num++;
00819
00820
00821
00822 fprintf (assembler_source, "\tBASR\tr%d,0\n", BASE_REGISTER);
00823 fprintf (assembler_source, ".LPG%d:\n", mvs_page_num);
00824 fprintf (assembler_source, "\t.USING\t.,r%d\n", BASE_REGISTER);
00825 mvs_page_code = code;
00826 mvs_page_lit = lit;
00827 return 1;
00828 }
00829 mvs_page_code += code;
00830 mvs_page_lit += lit;
00831 return 0;
00832 }
00833 #endif
00834
00835
00836
00837 #ifdef TARGET_HLASM
00838
00839
00840
00841
00842
00843 int
00844 mvs_function_check (name)
00845 const char *name;
00846 {
00847 int lower, middle, upper;
00848 int i;
00849
00850 lower = 0;
00851 upper = MVS_FUNCTION_TABLE_LENGTH - 1;
00852 while (lower <= upper)
00853 {
00854 middle = (lower + upper) / 2;
00855 i = strcmp (name, mvs_function_table[middle]);
00856 if (i == 0)
00857 return 1;
00858 if (i < 0)
00859 upper = middle - 1;
00860 else
00861 lower = middle + 1;
00862 }
00863 return 0;
00864 }
00865
00866
00867
00868 #ifdef LONGEXTERNAL
00869 static int
00870 mvs_hash_alias (key)
00871 const char *key;
00872 {
00873 int h;
00874 int i;
00875 int l = strlen (key);
00876
00877 h = key[0];
00878 for (i = 1; i < l; i++)
00879 h = ((h * MVS_SET_SIZE) + key[i]) % MVS_HASH_PRIME;
00880 return (h);
00881 }
00882 #endif
00883
00884
00885
00886 void
00887 mvs_add_alias (realname, aliasname, emitted)
00888 const char *realname;
00889 const char *aliasname;
00890 int emitted;
00891 {
00892 alias_node_t *ap;
00893
00894 ap = (alias_node_t *) xmalloc (sizeof (alias_node_t));
00895 if (strlen (realname) > MAX_LONG_LABEL_SIZE)
00896 {
00897 warning ("real name is too long - alias ignored");
00898 return;
00899 }
00900 if (strlen (aliasname) > MAX_MVS_LABEL_SIZE)
00901 {
00902 warning ("alias name is too long - alias ignored");
00903 return;
00904 }
00905
00906 strcpy (ap->real_name, realname);
00907 strcpy (ap->alias_name, aliasname);
00908 ap->alias_emitted = emitted;
00909 ap->alias_next = alias_anchor;
00910 alias_anchor = ap;
00911 }
00912
00913
00914
00915
00916
00917
00918 int
00919 mvs_need_alias (realname)
00920 const char *realname;
00921 {
00922 int i, j = strlen (realname);
00923
00924 if (mvs_function_check (realname))
00925 return 0;
00926 #if 0
00927 if (!strcmp (realname, "gccmain"))
00928 return 0;
00929 if (!strcmp (realname, "main"))
00930 return 0;
00931 #endif
00932 if (j > MAX_MVS_LABEL_SIZE)
00933 return 1;
00934 if (strchr (realname, '_') != 0)
00935 return 1;
00936 if (ISUPPER (realname[0]))
00937 {
00938 for (i = 1; i < j; i++)
00939 {
00940 if (ISLOWER (realname[i]))
00941 return 1;
00942 }
00943 }
00944 else
00945 {
00946 for (i = 1; i < j; i++)
00947 {
00948 if (ISUPPER (realname[i]))
00949 return 1;
00950 }
00951 }
00952
00953 return 0;
00954 }
00955
00956
00957
00958
00959 int
00960 mvs_get_alias (realname, aliasname)
00961 const char *realname;
00962 char *aliasname;
00963 {
00964 #ifdef LONGEXTERNAL
00965 alias_node_t *ap;
00966
00967 for (ap = alias_anchor; ap; ap = ap->alias_next)
00968 {
00969 if (!strcmp (ap->real_name, realname))
00970 {
00971 strcpy (aliasname, ap->alias_name);
00972 return 1;
00973 }
00974 }
00975 if (mvs_need_alias (realname))
00976 {
00977 char c1, c2;
00978
00979 c1 = realname[0];
00980 c2 = realname[1];
00981 if (ISLOWER (c1)) c1 = TOUPPER (c1);
00982 else if (c1 == '_') c1 = 'A';
00983 if (ISLOWER (c2)) c2 = TOUPPER (c2);
00984 else if (c2 == '_' || c2 == '\0') c2 = '#';
00985
00986 sprintf (aliasname, "%c%c%06d", c1, c2, mvs_hash_alias (realname));
00987 mvs_add_alias (realname, aliasname, 0);
00988 return 1;
00989 }
00990 #else
00991 if (strlen (realname) > MAX_MVS_LABEL_SIZE)
00992 {
00993 strncpy (aliasname, realname, MAX_MVS_LABEL_SIZE);
00994 aliasname[MAX_MVS_LABEL_SIZE] = '\0';
00995 return 1;
00996 }
00997 #endif
00998 return 0;
00999 }
01000
01001
01002
01003
01004 int
01005 mvs_check_alias (realname, aliasname)
01006 const char *realname;
01007 char *aliasname;
01008 {
01009 #ifdef LONGEXTERNAL
01010 alias_node_t *ap;
01011
01012 for (ap = alias_anchor; ap; ap = ap->alias_next)
01013 {
01014 if (!strcmp (ap->real_name, realname))
01015 {
01016 int rc = (ap->alias_emitted == 1) ? 1 : 2;
01017 strcpy (aliasname, ap->alias_name);
01018 ap->alias_emitted = 1;
01019 return rc;
01020 }
01021 }
01022 if (mvs_need_alias (realname))
01023 {
01024 char c1, c2;
01025
01026 c1 = realname[0];
01027 c2 = realname[1];
01028 if (ISLOWER (c1)) c1 = TOUPPER (c1);
01029 else if (c1 == '_') c1 = 'A';
01030 if (ISLOWER (c2)) c2 = TOUPPER (c2);
01031 else if (c2 == '_' || c2 == '\0') c2 = '#';
01032
01033 sprintf (aliasname, "%c%c%06d", c1, c2, mvs_hash_alias (realname));
01034 mvs_add_alias (realname, aliasname, 0);
01035 alias_anchor->alias_emitted = 1;
01036 return 2;
01037 }
01038 #else
01039 if (strlen (realname) > MAX_MVS_LABEL_SIZE)
01040 {
01041 strncpy (aliasname, realname, MAX_MVS_LABEL_SIZE);
01042 aliasname[MAX_MVS_LABEL_SIZE] = '\0';
01043 return 1;
01044 }
01045 #endif
01046 return 0;
01047 }
01048
01049
01050 #endif
01051
01052
01053
01054 #ifdef TARGET_ELF_ABI
01055
01056
01057
01058
01059
01060
01061 int
01062 mvs_function_check (name)
01063 const char *name ATTRIBUTE_UNUSED;
01064 {
01065 return 0;
01066 }
01067
01068 #endif
01069
01070
01071
01072
01073
01074
01075
01076 int
01077 s_operand (op, mode)
01078 register rtx op;
01079 enum machine_mode mode;
01080 {
01081 extern int volatile_ok;
01082 register enum rtx_code code = GET_CODE (op);
01083
01084 if (CONSTANT_ADDRESS_P (op))
01085 return 1;
01086 if (mode == VOIDmode || GET_MODE (op) != mode)
01087 return 0;
01088 if (code == MEM)
01089 {
01090 register rtx x = XEXP (op, 0);
01091
01092 if (!volatile_ok && op->volatil)
01093 return 0;
01094 if (REG_P (x) && REG_OK_FOR_BASE_P (x))
01095 return 1;
01096 if (GET_CODE (x) == PLUS
01097 && REG_P (XEXP (x, 0)) && REG_OK_FOR_BASE_P (XEXP (x, 0))
01098 && GET_CODE (XEXP (x, 1)) == CONST_INT
01099 && (unsigned) INTVAL (XEXP (x, 1)) < 4096)
01100 return 1;
01101 }
01102 return 0;
01103 }
01104
01105
01106
01107
01108
01109
01110
01111 int
01112 r_or_s_operand (op, mode)
01113 register rtx op;
01114 enum machine_mode mode;
01115 {
01116 extern int volatile_ok;
01117 register enum rtx_code code = GET_CODE (op);
01118
01119 if (CONSTANT_ADDRESS_P (op))
01120 return 1;
01121 if (mode == VOIDmode || GET_MODE (op) != mode)
01122 return 0;
01123 if (code == REG)
01124 return 1;
01125 else if (code == MEM)
01126 {
01127 register rtx x = XEXP (op, 0);
01128
01129 if (!volatile_ok && op->volatil)
01130 return 0;
01131 if (REG_P (x) && REG_OK_FOR_BASE_P (x))
01132 return 1;
01133 if (GET_CODE (x) == PLUS
01134 && REG_P (XEXP (x, 0)) && REG_OK_FOR_BASE_P (XEXP (x, 0))
01135 && GET_CODE (XEXP (x, 1)) == CONST_INT
01136 && (unsigned) INTVAL (XEXP (x, 1)) < 4096)
01137 return 1;
01138 }
01139 return 0;
01140 }
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162 int
01163 unsigned_jump_follows_p (insn)
01164 register rtx insn;
01165 {
01166 rtx orig_insn = insn;
01167 while (1)
01168 {
01169 register rtx tmp_insn;
01170 enum rtx_code coda;
01171
01172 insn = NEXT_INSN (insn);
01173 if (!insn) fatal_insn ("internal error--no jump follows compare:", orig_insn);
01174
01175 if (GET_CODE (insn) != JUMP_INSN) continue;
01176
01177 tmp_insn = XEXP (insn, 3);
01178 if (GET_CODE (tmp_insn) != SET) continue;
01179
01180 if (GET_CODE (XEXP (tmp_insn, 0)) != PC) continue;
01181
01182 tmp_insn = XEXP (tmp_insn, 1);
01183 if (GET_CODE (tmp_insn) != IF_THEN_ELSE) continue;
01184
01185
01186 tmp_insn = XEXP (tmp_insn, 0);
01187 coda = GET_CODE (tmp_insn);
01188
01189 return coda != GE && coda != GT && coda != LE && coda != LT;
01190 }
01191 }
01192
01193 #ifdef TARGET_HLASM
01194
01195
01196
01197
01198 static bool
01199 i370_hlasm_assemble_integer (x, size, aligned_p)
01200 rtx x;
01201 unsigned int size;
01202 int aligned_p;
01203 {
01204 const char *int_format = NULL;
01205
01206 if (aligned_p)
01207 switch (size)
01208 {
01209 case 1:
01210 int_format = "\tDC\tX'%02X'\n";
01211 break;
01212
01213 case 2:
01214 int_format = "\tDC\tX'%04X'\n";
01215 break;
01216
01217 case 4:
01218 if (GET_CODE (x) == CONST_INT)
01219 {
01220 fputs ("\tDC\tF'", asm_out_file);
01221 output_addr_const (asm_out_file, x);
01222 fputs ("'\n", asm_out_file);
01223 }
01224 else
01225 {
01226 fputs ("\tDC\tA(", asm_out_file);
01227 output_addr_const (asm_out_file, x);
01228 fputs (")\n", asm_out_file);
01229 }
01230 return true;
01231 }
01232
01233 if (int_format && GET_CODE (x) == CONST_INT)
01234 {
01235 fprintf (asm_out_file, int_format, INTVAL (x));
01236 return true;
01237 }
01238 return default_assemble_integer (x, size, aligned_p);
01239 }
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250 static void
01251 i370_output_function_prologue (f, l)
01252 FILE *f;
01253 HOST_WIDE_INT l;
01254 {
01255 #if MACROPROLOGUE == 1
01256 fprintf (f, "* Function %s prologue\n", mvs_function_name);
01257 fprintf (f, "\tEDCPRLG USRDSAL=%d,BASEREG=%d\n",
01258 STACK_POINTER_OFFSET + l - 120 +
01259 current_function_outgoing_args_size, BASE_REGISTER);
01260 #else
01261 static int function_label_index = 1;
01262 static int function_first = 0;
01263 static int function_year, function_month, function_day;
01264 static int function_hour, function_minute, function_second;
01265 #if defined(LE370)
01266 if (!function_first)
01267 {
01268 struct tm *function_time;
01269 time_t lcltime;
01270 time (&lcltime);
01271 function_time = localtime (&lcltime);
01272 function_year = function_time->tm_year + 1900;
01273 function_month = function_time->tm_mon + 1;
01274 function_day = function_time->tm_mday;
01275 function_hour = function_time->tm_hour;
01276 function_minute = function_time->tm_min;
01277 function_second = function_time->tm_sec;
01278 }
01279 fprintf (f, "* Function %s prologue\n", mvs_function_name);
01280 fprintf (f, "FDSE%03d\tDSECT\n", function_label_index);
01281 fprintf (f, "\tDS\tD\n");
01282 fprintf (f, "\tDS\tCL(%d)\n", STACK_POINTER_OFFSET + l
01283 + current_function_outgoing_args_size);
01284 fprintf (f, "\tORG\tFDSE%03d\n", function_label_index);
01285 fprintf (f, "\tDS\tCL(120+8)\n");
01286 fprintf (f, "\tORG\n");
01287 fprintf (f, "\tDS\t0D\n");
01288 fprintf (f, "FDSL%03d\tEQU\t*-FDSE%03d-8\n", function_label_index,
01289 function_label_index);
01290 fprintf (f, "\tDS\t0H\n");
01291 assemble_name (f, mvs_function_name);
01292 fprintf (f, "\tCSECT\n");
01293 fprintf (f, "\tUSING\t*,15\n");
01294 fprintf (f, "\tB\tFENT%03d\n", function_label_index);
01295 fprintf (f, "\tDC\tAL1(FNAM%03d+4-*)\n", function_label_index);
01296 fprintf (f, "\tDC\tX'CE',X'A0',AL1(16)\n");
01297 fprintf (f, "\tDC\tAL4(FPPA%03d)\n", function_label_index);
01298 fprintf (f, "\tDC\tAL4(0)\n");
01299 fprintf (f, "\tDC\tAL4(FDSL%03d)\n", function_label_index);
01300 fprintf (f, "FNAM%03d\tEQU\t*\n", function_label_index);
01301 fprintf (f, "\tDC\tAL2(%d),C'%s'\n", strlen (mvs_function_name),
01302 mvs_function_name);
01303 fprintf (f, "FPPA%03d\tDS\t0F\n", function_label_index);
01304 fprintf (f, "\tDC\tX'03',X'00',X'33',X'00'\n");
01305 fprintf (f, "\tDC\tV(CEESTART)\n");
01306 fprintf (f, "\tDC\tAL4(0)\n");
01307 fprintf (f, "\tDC\tAL4(FTIM%03d)\n", function_label_index);
01308 fprintf (f, "FTIM%03d\tDS\t0F\n", function_label_index);
01309 fprintf (f, "\tDC\tCL4'%d',CL4'%02d%02d',CL6'%02d%02d00'\n",
01310 function_year, function_month, function_day,
01311 function_hour, function_minute);
01312 fprintf (f, "\tDC\tCL2'01',CL4'0100'\n");
01313 fprintf (f, "FENT%03d\tDS\t0H\n", function_label_index);
01314 fprintf (f, "\tSTM\t14,12,12(13)\n");
01315 fprintf (f, "\tL\t2,76(,13)\n");
01316 fprintf (f, "\tL\t0,16(,15)\n");
01317 fprintf (f, "\tALR\t0,2\n");
01318 fprintf (f, "\tCL\t0,12(,12)\n");
01319 fprintf (f, "\tBNH\t*+10\n");
01320 fprintf (f, "\tL\t15,116(,12)\n");
01321 fprintf (f, "\tBALR\t14,15\n");
01322 fprintf (f, "\tL\t15,72(,13)\n");
01323 fprintf (f, "\tSTM\t15,0,72(2)\n");
01324 fprintf (f, "\tMVI\t0(2),X'10'\n");
01325 fprintf (f, "\tST\t2,8(,13)\n ");
01326 fprintf (f, "\tST\t13,4(,2)\n ");
01327 fprintf (f, "\tLR\t13,2\n");
01328 fprintf (f, "\tDROP\t15\n");
01329 fprintf (f, "\tBALR\t%d,0\n", BASE_REGISTER);
01330 fprintf (f, "\tUSING\t*,%d\n", BASE_REGISTER);
01331 function_first = 1;
01332 function_label_index ++;
01333 #else
01334 if (!function_first)
01335 {
01336 struct tm *function_time;
01337 time_t lcltime;
01338 time (&lcltime);
01339 function_time = localtime (&lcltime);
01340 function_year = function_time->tm_year + 1900;
01341 function_month = function_time->tm_mon + 1;
01342 function_day = function_time->tm_mday;
01343 function_hour = function_time->tm_hour;
01344 function_minute = function_time->tm_min;
01345 function_second = function_time->tm_sec;
01346 fprintf (f, "PPA2\tDS\t0F\n");
01347 fprintf (f, "\tDC\tX'03',X'00',X'33',X'00'\n");
01348 fprintf (f, "\tDC\tV(CEESTART),A(0)\n");
01349 fprintf (f, "\tDC\tA(CEETIMES)\n");
01350 fprintf (f, "CEETIMES\tDS\t0F\n");
01351 fprintf (f, "\tDC\tCL4'%d',CL4'%02d%02d',CL6'%02d%02d00'\n",
01352 function_year, function_month, function_day,
01353 function_hour, function_minute, function_second);
01354 fprintf (f, "\tDC\tCL2'01',CL4'0100'\n");
01355 }
01356 fprintf (f, "* Function %s prologue\n", mvs_function_name);
01357 fprintf (f, "FDSD%03d\tDSECT\n", function_label_index);
01358 fprintf (f, "\tDS\tD\n");
01359 fprintf (f, "\tDS\tCL(%d)\n", STACK_POINTER_OFFSET + l
01360 + current_function_outgoing_args_size);
01361 fprintf (f, "\tORG\tFDSD%03d\n", function_label_index);
01362 fprintf (f, "\tDS\tCL(120+8)\n");
01363 fprintf (f, "\tORG\n");
01364 fprintf (f, "\tDS\t0D\n");
01365 fprintf (f, "FDSL%03d\tEQU\t*-FDSD%03d-8\n", function_label_index,
01366 function_label_index);
01367 fprintf (f, "\tDS\t0H\n");
01368 assemble_name (f, mvs_function_name);
01369 fprintf (f, "\tCSECT\n");
01370 fprintf (f, "\tUSING\t*,15\n");
01371 fprintf (f, "\tB\tFPL%03d\n", function_label_index);
01372 fprintf (f, "\tDC\tAL1(FPL%03d+4-*)\n", function_label_index + 1);
01373 fprintf (f, "\tDC\tX'CE',X'A0',AL1(16)\n");
01374 fprintf (f, "\tDC\tAL4(PPA2)\n");
01375 fprintf (f, "\tDC\tAL4(0)\n");
01376 fprintf (f, "\tDC\tAL4(FDSL%03d)\n", function_label_index);
01377 fprintf (f, "FPL%03d\tEQU\t*\n", function_label_index + 1);
01378 fprintf (f, "\tDC\tAL2(%d),C'%s'\n", strlen (mvs_function_name),
01379 mvs_function_name);
01380 fprintf (f, "FPL%03d\tDS\t0H\n", function_label_index);
01381 fprintf (f, "\tSTM\t14,12,12(13)\n");
01382 fprintf (f, "\tL\t2,76(,13)\n");
01383 fprintf (f, "\tL\t0,16(,15)\n");
01384 fprintf (f, "\tALR\t0,2\n");
01385 fprintf (f, "\tCL\t0,12(,12)\n");
01386 fprintf (f, "\tBNH\t*+10\n");
01387 fprintf (f, "\tL\t15,116(,12)\n");
01388 fprintf (f, "\tBALR\t14,15\n");
01389 fprintf (f, "\tL\t15,72(,13)\n");
01390 fprintf (f, "\tSTM\t15,0,72(2)\n");
01391 fprintf (f, "\tMVI\t0(2),X'10'\n");
01392 fprintf (f, "\tST\t2,8(,13)\n ");
01393 fprintf (f, "\tST\t13,4(,2)\n ");
01394 fprintf (f, "\tLR\t13,2\n");
01395 fprintf (f, "\tDROP\t15\n");
01396 fprintf (f, "\tBALR\t%d,0\n", BASE_REGISTER);
01397 fprintf (f, "\tUSING\t*,%d\n", BASE_REGISTER);
01398 function_first = 1;
01399 function_label_index += 2;
01400 #endif
01401 #endif
01402 fprintf (f, "PG%d\tEQU\t*\n", mvs_page_num );
01403 fprintf (f, "\tLR\t11,1\n");
01404 fprintf (f, "\tL\t%d,=A(PGT%d)\n", PAGE_REGISTER, mvs_page_num);
01405 fprintf (f, "* Function %s code\n", mvs_function_name);
01406
01407 mvs_free_label_list ();
01408 mvs_page_code = 6;
01409 mvs_page_lit = 4;
01410 mvs_check_page (f, 0, 0);
01411 function_base_page = mvs_page_num;
01412
01413
01414 i370_label_scan ();
01415 }
01416 #endif
01417
01418
01419 #ifdef TARGET_ELF_ABI
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440 static void
01441 i370_output_function_prologue (f, frame_size)
01442 FILE *f;
01443 HOST_WIDE_INT frame_size;
01444 {
01445 static int function_label_index = 1;
01446 static int function_first = 0;
01447 int stackframe_size, aligned_size;
01448
01449 fprintf (f, "# Function prologue\n");
01450
01451
01452
01453 stackframe_size =
01454 STACK_POINTER_OFFSET + current_function_outgoing_args_size + frame_size;
01455 aligned_size = (stackframe_size + 7) >> 3;
01456 aligned_size <<= 3;
01457
01458 fprintf (f, "# arg_size=0x%x frame_size=0x%x aligned size=0x%x\n",
01459 current_function_outgoing_args_size, frame_size, aligned_size);
01460
01461 fprintf (f, "\t.using\t.,r15\n");
01462
01463
01464 fprintf (f, "\tB\t.LFENT%03d\n", function_label_index);
01465
01466
01467 fprintf (f, "\t.long\t%d\n", aligned_size);
01468
01469
01470 fprintf (f, "\t.balign 2\n.LFENT%03d:\n",
01471 function_label_index);
01472
01473
01474 fprintf (f, "\tSTM\tr14,r12,12(sp)\n");
01475
01476
01477 fprintf (f, "\tLR\tr3,sp\n");
01478
01479
01480 fprintf (f, "\tSL\tsp,4(,r15)\n");
01481
01482
01483 fprintf (f, "\tLR\tr11,r2\n");
01484
01485
01486
01487
01488
01489 fprintf (f, "\tST\tr3,4(,sp)\n ");
01490
01491 fprintf (f, "\t.drop\tr15\n");
01492
01493
01494 fprintf (f, "\tBASR\tr%d,0\n", BASE_REGISTER);
01495 fprintf (f, "\t.using\t.,r%d\n", BASE_REGISTER);
01496 function_first = 1;
01497 function_label_index ++;
01498
01499 fprintf (f, ".LPG%d:\n", mvs_page_num );
01500 fprintf (f, "\tL\tr%d,=A(.LPGT%d)\n", PAGE_REGISTER, mvs_page_num);
01501 fprintf (f, "# Function code\n");
01502
01503 mvs_free_label_list ();
01504 mvs_page_code = 6;
01505 mvs_page_lit = 4;
01506 mvs_check_page (f, 0, 0);
01507 function_base_page = mvs_page_num;
01508
01509
01510 i370_label_scan ();
01511 }
01512 #endif
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522 static void
01523 i370_output_function_epilogue (file, l)
01524 FILE *file;
01525 HOST_WIDE_INT l ATTRIBUTE_UNUSED;
01526 {
01527 int i;
01528
01529 check_label_emit ();
01530 mvs_check_page (file, 14, 0);
01531 fprintf (file, "* Function %s epilogue\n", mvs_function_name);
01532 mvs_page_num++;
01533
01534 #if MACROEPILOGUE == 1
01535 fprintf (file, "\tEDCEPIL\n");
01536 #else
01537 fprintf (file, "\tL\t13,4(,13)\n");
01538 fprintf (file, "\tL\t14,12(,13)\n");
01539 fprintf (file, "\tLM\t2,12,28(13)\n");
01540 fprintf (file, "\tBALR\t1,14\n");
01541 fprintf (file, "\tDC\tA(");
01542 assemble_name (file, mvs_function_name);
01543 fprintf (file, ")\n" );
01544 #endif
01545
01546 fprintf (file, "* Function %s literal pool\n", mvs_function_name);
01547 fprintf (file, "\tDS\t0F\n" );
01548 fprintf (file, "\tLTORG\n");
01549 fprintf (file, "* Function %s page table\n", mvs_function_name);
01550 fprintf (file, "\tDS\t0F\n");
01551 fprintf (file, "PGT%d\tEQU\t*\n", function_base_page);
01552
01553 mvs_free_label_list();
01554 for (i = function_base_page; i < mvs_page_num; i++)
01555 fprintf (file, "\tDC\tA(PG%d)\n", i);
01556 }