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

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