home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / gcc-2.7.2.1-src.tgz / tar.out / fsf / gcc / config / i370 / mvs370.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  15KB  |  483 lines

  1. /* Subroutines for insn-output.c for System/370.
  2.    Copyright (C) 1989, 1993, 1995 Free Software Foundation, Inc.
  3.    Contributed by Jan Stein (jan@cd.chalmers.se).
  4.    Modified for MVS C/370 by Dave Pitts (dpitts@nyx.cs.du.edu)
  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
  20. the Free Software Foundation, 59 Temple Place - Suite 330,
  21. Boston, MA 02111-1307, USA.  */
  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.  */
  52. int mvs_label_emitted = 0;
  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.  
  78. /* Assembler source file descriptor.  */
  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. {
  247.   if (mvs_label_emitted)
  248.     {
  249.       mvs_label_emitted = 0;
  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. }
  483.