|
|
1.1 root 1: /* Subroutines for insn-output.c for System/370. 1.1.1.2 ! root 2: Copyright (C) 1989, 1993, 1995 Free Software Foundation, Inc. 1.1 root 3: Contributed by Jan Stein ([email protected]). 1.1.1.2 ! root 4: Modified for MVS C/370 by Dave Pitts ([email protected]) 1.1 root 5: 6: This file is part of GNU CC. 7: 8: GNU CC is free software; you can redistribute it and/or modify 9: it under the terms of the GNU General Public License as published by 10: the Free Software Foundation; either version 2, or (at your option) 11: any later version. 12: 13: GNU CC is distributed in the hope that it will be useful, 14: but WITHOUT ANY WARRANTY; without even the implied warranty of 15: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16: GNU General Public License for more details. 17: 18: You should have received a copy of the GNU General Public License 19: along with GNU CC; see the file COPYING. If not, write to 1.1.1.2 ! root 20: the Free Software Foundation, 59 Temple Place - Suite 330, ! 21: Boston, MA 02111-1307, USA. */ 1.1 root 22: 23: #include <stdio.h> 24: #include <string.h> 25: #include <ctype.h> 26: #include "config.h" 27: #include "rtl.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 "flags.h" 37: #include "recog.h" 38: 39: 40: /* Label node, this structure is used to keep track of labels on the 41: current page. */ 42: typedef struct label_node 43: { 44: struct label_node *label_next; 45: int label_id; 46: int label_page; 47: } 48: label_node_t; 49: 50: /* Is 1 when a label has been generated and the base register must be 51: reloaded. */ 1.1.1.2 ! root 52: int mvs_label_emitted = 0; 1.1 root 53: 54: /* Current function starting base page. */ 55: int function_base_page; 56: 57: /* Length of the current page code. */ 58: int mvs_page_code; 59: 60: /* Length of the current page literals. */ 61: int mvs_page_lit; 62: 63: /* Current function name. */ 64: char *mvs_function_name = 0; 65: 66: /* Current function name length. */ 67: int mvs_function_name_length = 0; 68: 69: /* Page number for multi-page functions. */ 70: int mvs_page_num = 0; 71: 72: /* Label node list anchor. */ 73: static label_node_t *label_anchor = 0; 74: 75: /* Label node free list anchor. */ 76: static label_node_t *free_anchor = 0; 77: 1.1.1.2 ! root 78: /* Assembler source file descriptor. */ 1.1 root 79: static FILE *assembler_source = 0; 80: 81: /* Define the length of the internal MVS function table. */ 82: #define MVS_FUNCTION_TABLE_LENGTH 32 83: 84: /* C/370 internal function table. These functions use non-standard linkage 85: and must handled in a special manner. */ 86: static char *mvs_function_table[MVS_FUNCTION_TABLE_LENGTH] = 87: { 88: "ceil", "edc_acos", "edc_asin", "edc_ata2", "edc_atan", "edc_cos", 89: "edc_cosh", "edc_erf", "edc_erfc", "edc_exp", "edc_gamm", "edc_lg10", 90: "edc_log", "edc_sin", "edc_sinh", "edc_sqrt", "edc_tan", "edc_tanh", 91: "fabs", "floor", "fmod", "frexp", "hypot", "j0", 92: "j1", "jn", "ldexp", "modf", "pow", "y0", 93: "y1", "yn" 94: }; 95: 96: /* ASCII to EBCDIC conversion table. */ 97: #if defined(TARGET_EBCDIC) && !defined(HOST_EBCDIC) 98: static unsigned char ascebc[256] = 99: { 100: /*00 NL SH SX EX ET NQ AK BL */ 101: 0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F, 102: /*08 BS HT LF VT FF CR SO SI */ 103: 0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 104: /*10 DL D1 D2 D3 D4 NK SN EB */ 105: 0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26, 106: /*18 CN EM SB EC FS GS RS US */ 107: 0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D, 0x1E, 0x1F, 108: /*20 SP ! " # $ % & ' */ 109: 0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D, 110: /*28 ( ) * + , - . / */ 111: 0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61, 112: /*30 0 1 2 3 4 5 6 7 */ 113: 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 114: /*38 8 9 : ; < = > ? */ 115: 0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F, 116: /*40 @ A B C D E F G */ 117: 0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 118: /*48 H I J K L M N O */ 119: 0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 120: /*50 P Q R S T U V W */ 121: 0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 122: /*58 X Y Z [ \ ] ^ _ */ 123: 0xE7, 0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D, 124: /*60 ` a b c d e f g */ 125: 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 126: /*68 h i j k l m n o */ 127: 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 128: /*70 p q r s t u v w */ 129: 0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 130: /*78 x y z { | } ~ DL */ 131: 0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07, 132: 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 133: 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 134: 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 135: 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 136: 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 137: 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 138: 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 139: 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 140: 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 141: 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 142: 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 143: 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 144: 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 145: 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 146: 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 147: 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0xFF 148: }; 149: #endif 150: 151: /* EBCDIC to ASCII conversion table. */ 152: #if defined(HOST_EBCDIC) && !defined(TARGET_EBCDIC) 153: unsigned char ebcasc[256] = 154: { 155: /*00 NU SH SX EX PF HT LC DL */ 156: 0x00, 0x01, 0x02, 0x03, 0x00, 0x09, 0x00, 0x7F, 157: /*08 SM VT FF CR SO SI */ 158: 0x00, 0x00, 0x00, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 159: /*10 DE D1 D2 TM RS NL BS IL */ 160: 0x10, 0x11, 0x12, 0x13, 0x14, 0x0A, 0x08, 0x00, 161: /*18 CN EM CC C1 FS GS RS US */ 162: 0x18, 0x19, 0x00, 0x00, 0x1C, 0x1D, 0x1E, 0x1F, 163: /*20 DS SS FS BP LF EB EC */ 164: 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x17, 0x1B, 165: /*28 SM C2 EQ AK BL */ 166: 0x00, 0x00, 0x00, 0x00, 0x05, 0x06, 0x07, 0x00, 167: /*30 SY PN RS UC ET */ 168: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 169: /*38 C3 D4 NK SU */ 170: 0x00, 0x00, 0x00, 0x00, 0x14, 0x15, 0x00, 0x1A, 171: /*40 SP */ 172: 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 173: /*48 . < ( + | */ 174: 0x00, 0x00, 0x00, 0x2E, 0x3C, 0x28, 0x2B, 0x7C, 175: /*50 & */ 176: 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 177: /*58 ! $ * ) ; ^ */ 178: 0x00, 0x00, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0x5E, 179: /*60 - / */ 180: 0x2D, 0x2F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 181: /*68 , % _ > ? */ 182: 0x00, 0x00, 0x00, 0x2C, 0x25, 0x5F, 0x3E, 0x3F, 183: /*70 */ 184: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 185: /*78 ` : # @ ' = " */ 186: 0x00, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22, 187: /*80 a b c d e f g */ 188: 0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 189: /*88 h i { */ 190: 0x68, 0x69, 0x00, 0x7B, 0x00, 0x00, 0x00, 0x00, 191: /*90 j k l m n o p */ 192: 0x00, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 193: /*98 q r } */ 194: 0x71, 0x72, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x00, 195: /*A0 ~ s t u v w x */ 196: 0x00, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 197: /*A8 y z [ */ 198: 0x79, 0x7A, 0x00, 0x00, 0x00, 0x5B, 0x00, 0x00, 199: /*B0 */ 200: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 201: /*B8 ] */ 202: 0x00, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x00, 0x00, 203: /*C0 { A B C D E F G */ 204: 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 205: /*C8 H I */ 206: 0x48, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 207: /*D0 } J K L M N O P */ 208: 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 209: /*D8 Q R */ 210: 0x51, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 211: /*E0 \ S T U V W X */ 212: 0x5C, 0x00, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 213: /*E8 Y Z */ 214: 0x59, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 215: /*F0 0 1 2 3 4 5 6 7 */ 216: 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 217: /*F8 8 9 */ 218: 0x38, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF 219: }; 220: #endif 221: 222: /* Map characters from one character set to another. 223: C is the character to be translated. */ 224: 225: char 226: mvs_map_char (c) 227: char c; 228: { 229: #if defined(TARGET_EBCDIC) && !defined(HOST_EBCDIC) 230: return ascebc[c]; 231: #else 232: #if defined(HOST_EBCDIC) && !defined(TARGET_EBCDIC) 233: return ebcasc[c]; 234: #else 235: return c; 236: #endif 237: #endif 238: } 239: 240: /* Emit reload of base register if indicated. This is to eliminate multiple 241: reloads when several labels are generated pointing to the same place 242: in the code. */ 243: 244: int 245: check_label_emit (void) 246: { 1.1.1.2 ! root 247: if (mvs_label_emitted) 1.1 root 248: { 1.1.1.2 ! root 249: mvs_label_emitted = 0; 1.1 root 250: mvs_page_code += 4; 251: fprintf (assembler_source, "\tL\t%d,%d(,%d)\n", 252: BASE_REGISTER, (mvs_page_num - function_base_page) * 4, 253: PAGE_REGISTER); 254: } 255: } 256: 257: /* Add the label to the current page label list. If a free element is available 258: it will be used for the new label. Otherwise, a label element will be 259: allocated from memory. 260: ID is the label number of the label being added to the list. */ 261: 262: int 263: mvs_add_label (id) 264: int id; 265: { 266: label_node_t *lp; 267: 268: if (free_anchor) 269: { 270: lp = free_anchor; 271: free_anchor = lp->label_next; 272: } 273: else 274: { 275: lp = (label_node_t *) malloc (sizeof (label_node_t)); 276: if (lp == 0) 277: { 278: fatal ("virtual memory exhausted\n"); 279: abort (); 280: } 281: } 282: lp->label_id = id; 283: lp->label_page = mvs_page_num; 284: lp->label_next = label_anchor; 285: label_anchor = lp; 286: } 287: 288: /* Check to see if the label is in the list. If 1 is returned then a load 289: and branch on register must be generated. 290: ID is the label number of the label being checked. */ 291: 292: int 293: mvs_check_label (id) 294: int id; 295: { 296: label_node_t *lp; 297: 298: for (lp = label_anchor; lp; lp = lp->label_next) 299: { 300: if (lp->label_id == id) 301: return 1; 302: } 303: return 0; 304: } 305: 306: /* The label list for the current page freed by linking the list onto the free 307: label element chain. */ 308: 309: int 310: mvs_free_label (void) 311: { 312: if (label_anchor) 313: { 314: if (free_anchor) 315: label_anchor->label_next = free_anchor; 316: free_anchor = label_anchor; 317: } 318: label_anchor = 0; 319: } 320: 321: /* If the page size limit is reached a new code page is started, and the base 322: register is set to it. This page break point is counted conservatively, 323: most literals that have the same value are collapsed by the assembler. 324: True is returned when a new page is started. 325: FILE is the assembler output file descriptor. 326: CODE is the length, in bytes, of the instruction to be emitted. 327: LIT is the length of the literal to be emitted. */ 328: 329: int 330: mvs_check_page (file, code, lit) 331: FILE *file; 332: int code, lit; 333: { 334: if (file) 335: assembler_source = file; 336: 337: if (mvs_page_code + code + mvs_page_lit + lit > MAX_MVS_PAGE_LENGTH) 338: { 339: fprintf (assembler_source, "\tB\tPGE%d\n", mvs_page_num); 340: fprintf (assembler_source, "\tDS\t0F\n"); 341: fprintf (assembler_source, "\tLTORG\n"); 342: fprintf (assembler_source, "\tDS\t0F\n"); 343: fprintf (assembler_source, "PGE%d\tEQU\t*\n", mvs_page_num); 344: fprintf (assembler_source, "\tDROP\t%d\n", BASE_REGISTER); 345: mvs_page_num++; 346: fprintf (assembler_source, "\tBALR\t%d,0\n", BASE_REGISTER); 347: fprintf (assembler_source, "PG%d\tEQU\t*\n", mvs_page_num); 348: fprintf (assembler_source, "\tUSING\t*,%d\n", BASE_REGISTER); 349: mvs_free_label (); 350: mvs_page_code = code; 351: mvs_page_lit = lit; 352: return 1; 353: } 354: mvs_page_code += code; 355: mvs_page_lit += lit; 356: return 0; 357: } 358: 359: /* Check for C/370 runtime function, they don't use standard calling 360: conventions. True is returned if the function is in the table. 361: NAME is the name of the current function. */ 362: 363: int 364: mvs_function_check (name) 365: char *name; 366: { 367: int lower, middle, upper; 368: int i; 369: 370: lower = 0; 371: upper = MVS_FUNCTION_TABLE_LENGTH - 1; 372: while (lower <= upper) 373: { 374: middle = (lower + upper) / 2; 375: i = strcmp (name, mvs_function_table[middle]); 376: if (i == 0) 377: return 1; 378: if (i < 0) 379: upper = middle - 1; 380: else 381: lower = middle + 1; 382: } 383: return 0; 384: } 385: 386: 387: /* Return 1 if OP is a valid S operand for an RS, SI or SS type instruction. 388: OP is the current operation. 389: MODE is the current operation mode. */ 390: 391: int 392: s_operand (op, mode) 393: register rtx op; 394: enum machine_mode mode; 395: { 396: extern int volatile_ok; 397: register enum rtx_code code = GET_CODE (op); 398: 399: if (CONSTANT_ADDRESS_P (op)) 400: return 1; 401: if (mode == VOIDmode || GET_MODE (op) != mode) 402: return 0; 403: if (code == MEM) 404: { 405: register rtx x = XEXP (op, 0); 406: 407: if (!volatile_ok && op->volatil) 408: return 0; 409: if (REG_P (x) && REG_OK_FOR_BASE_P (x)) 410: return 1; 411: if (GET_CODE (x) == PLUS 412: && REG_P (XEXP (x, 0)) && REG_OK_FOR_BASE_P (XEXP (x, 0)) 413: && GET_CODE (XEXP (x, 1)) == CONST_INT 414: && (unsigned) INTVAL (XEXP (x, 1)) < 4096) 415: return 1; 416: } 417: return 0; 418: } 419: 420: 421: /* Return 1 if OP is a valid R or S operand for an RS, SI or SS type 422: instruction. 423: OP is the current operation. 424: MODE is the current operation mode. */ 425: 426: int 427: r_or_s_operand (op, mode) 428: register rtx op; 429: enum machine_mode mode; 430: { 431: extern int volatile_ok; 432: register enum rtx_code code = GET_CODE (op); 433: 434: if (CONSTANT_ADDRESS_P (op)) 435: return 1; 436: if (mode == VOIDmode || GET_MODE (op) != mode) 437: return 0; 438: if (code == REG) 439: return 1; 440: else if (code == MEM) 441: { 442: register rtx x = XEXP (op, 0); 443: 444: if (!volatile_ok && op->volatil) 445: return 0; 446: if (REG_P (x) && REG_OK_FOR_BASE_P (x)) 447: return 1; 448: if (GET_CODE (x) == PLUS 449: && REG_P (XEXP (x, 0)) && REG_OK_FOR_BASE_P (XEXP (x, 0)) 450: && GET_CODE (XEXP (x, 1)) == CONST_INT 451: && (unsigned) INTVAL (XEXP (x, 1)) < 4096) 452: return 1; 453: } 454: return 0; 455: } 456: 457: 458: /* Return 1 if the next instruction is an unsigned jump instruction. 459: INSN is the current instruction. */ 460: 461: unsigned_jump_follows_p (insn) 462: register rtx insn; 463: { 464: insn = NEXT_INSN (insn); 465: if (GET_CODE (insn) != JUMP_INSN) 466: return 0; 467: 468: insn = XEXP (insn, 3); 469: if (GET_CODE (insn) != SET) 470: return 0; 471: 472: if (GET_CODE (XEXP (insn, 0)) != PC) 473: return 0; 474: 475: insn = XEXP (insn, 1); 476: if (GET_CODE (insn) != IF_THEN_ELSE) 477: return 0; 478: 479: insn = XEXP (insn, 0); 480: return GET_CODE (insn) != GE && GET_CODE (insn) != GT 481: && GET_CODE (insn) != LE && GET_CODE (insn) != LT; 482: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.