home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 7 / FreshFishVol7.bin / bbs / gnu / gcc-2.3.3-src.lha / GNU / src / amiga / gcc-2.3.3 / config / vax.c < prev    next >
C/C++ Source or Header  |  1994-02-06  |  16KB  |  669 lines

  1. /* Subroutines for insn-output.c for Vax.
  2.    Copyright (C) 1987 Free Software Foundation, Inc.
  3.  
  4. This file is part of GNU CC.
  5.  
  6. GNU CC is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2, or (at your option)
  9. any later version.
  10.  
  11. GNU CC is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GNU CC; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. #include <stdio.h>
  21. #include "config.h"
  22. #include "rtl.h"
  23. #include "regs.h"
  24. #include "hard-reg-set.h"
  25. #include "real.h"
  26. #include "insn-config.h"
  27. #include "conditions.h"
  28. #include "insn-flags.h"
  29. #include "output.h"
  30. #include "insn-attr.h"
  31.  
  32.  
  33. /* This is like nonimmediate_operand with a restriction on the type of MEM.  */
  34.  
  35. void
  36. split_quadword_operands (operands, low, n)
  37.      rtx *operands, *low;
  38.      int n;
  39. {
  40.   int i;
  41.   /* Split operands.  */
  42.  
  43.   low[0] = low[1] = low[2] = 0;
  44.   for (i = 0; i < 3; i++)
  45.     {
  46.       if (low[i])
  47.     /* it's already been figured out */;
  48.       else if (GET_CODE (operands[i]) == MEM
  49.            && (GET_CODE (XEXP (operands[i], 0)) == POST_INC))
  50.     {
  51.       rtx addr = XEXP (operands[i], 0);
  52.       operands[i] = low[i] = gen_rtx (MEM, SImode, addr);
  53.       if (which_alternative == 0 && i == 0)
  54.         {
  55.           addr = XEXP (operands[i], 0);
  56.           operands[i+1] = low[i+1] = gen_rtx (MEM, SImode, addr);
  57.         }
  58.     }
  59.       else
  60.     {
  61.       low[i] = operand_subword (operands[i], 0, 0, DImode);
  62.       operands[i] = operand_subword (operands[i], 1, 0, DImode);
  63.     }
  64.     }
  65. }
  66.  
  67. print_operand_address (file, addr)
  68.      FILE *file;
  69.      register rtx addr;
  70. {
  71.   register rtx reg1, reg2, breg, ireg;
  72.   rtx offset;
  73.  
  74.  retry:
  75.   switch (GET_CODE (addr))
  76.     {
  77.     case MEM:
  78.       fprintf (file, "*");
  79.       addr = XEXP (addr, 0);
  80.       goto retry;
  81.  
  82.     case REG:
  83.       fprintf (file, "(%s)", reg_names[REGNO (addr)]);
  84.       break;
  85.  
  86.     case PRE_DEC:
  87.       fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
  88.       break;
  89.  
  90.     case POST_INC:
  91.       fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
  92.       break;
  93.  
  94.     case PLUS:
  95.       /* There can be either two or three things added here.  One must be a
  96.      REG.  One can be either a REG or a MULT of a REG and an appropriate
  97.      constant, and the third can only be a constant or a MEM.
  98.  
  99.      We get these two or three things and put the constant or MEM in
  100.      OFFSET, the MULT or REG in IREG, and the REG in BREG.  If we have
  101.      a register and can't tell yet if it is a base or index register,
  102.      put it into REG1.  */
  103.  
  104.       reg1 = 0; ireg = 0; breg = 0; offset = 0;
  105.  
  106.       if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
  107.       || GET_CODE (XEXP (addr, 0)) == MEM)
  108.     {
  109.       offset = XEXP (addr, 0);
  110.       addr = XEXP (addr, 1);
  111.     }
  112.       else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
  113.            || GET_CODE (XEXP (addr, 1)) == MEM)
  114.     {
  115.       offset = XEXP (addr, 1);
  116.       addr = XEXP (addr, 0);
  117.     }
  118.       else if (GET_CODE (XEXP (addr, 1)) == MULT)
  119.     {
  120.       ireg = XEXP (addr, 1);
  121.       addr = XEXP (addr, 0);
  122.     }
  123.       else if (GET_CODE (XEXP (addr, 0)) == MULT)
  124.     {
  125.       ireg = XEXP (addr, 0);
  126.       addr = XEXP (addr, 1);
  127.     }
  128.       else if (GET_CODE (XEXP (addr, 1)) == REG)
  129.     {
  130.       reg1 = XEXP (addr, 1);
  131.       addr = XEXP (addr, 0);
  132.     }
  133.       else if (GET_CODE (XEXP (addr, 0)) == REG)
  134.     {
  135.       reg1 = XEXP (addr, 0);
  136.       addr = XEXP (addr, 1);
  137.     }
  138.       else
  139.     abort ();
  140.  
  141.       if (GET_CODE (addr) == REG)
  142.     {
  143.       if (reg1)
  144.         ireg = addr;
  145.       else
  146.         reg1 = addr;
  147.     }
  148.       else if (GET_CODE (addr) == MULT)
  149.     ireg = addr;
  150.       else if (GET_CODE (addr) == PLUS)
  151.     {
  152.       if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
  153.           || GET_CODE (XEXP (addr, 0)) == MEM)
  154.         {
  155.           if (offset)
  156.         {
  157.           if (GET_CODE (offset) == CONST_INT)
  158.             offset = plus_constant (XEXP (addr, 0), INTVAL (offset));
  159.           else if (GET_CODE (XEXP (addr, 0)) == CONST_INT)
  160.             offset = plus_constant (offset, INTVAL (XEXP (addr, 0)));
  161.           else
  162.             abort ();
  163.         }
  164.           offset = XEXP (addr, 0);
  165.         }
  166.       else if (GET_CODE (XEXP (addr, 0)) == REG)
  167.         {
  168.           if (reg1)
  169.         ireg = reg1, breg = XEXP (addr, 0), reg1 = 0;
  170.           else
  171.         reg1 = XEXP (addr, 0);
  172.         }
  173.       else if (GET_CODE (XEXP (addr, 0)) == MULT)
  174.         {
  175.           if (ireg)
  176.         abort ();
  177.           ireg = XEXP (addr, 0);
  178.         }
  179.       else
  180.         abort ();
  181.  
  182.       if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
  183.           || GET_CODE (XEXP (addr, 1)) == MEM)
  184.         {
  185.           if (offset)
  186.         {
  187.           if (GET_CODE (offset) == CONST_INT)
  188.             offset = plus_constant (XEXP (addr, 1), INTVAL (offset));
  189.           else if (GET_CODE (XEXP (addr, 1)) == CONST_INT)
  190.             offset = plus_constant (offset, INTVAL (XEXP (addr, 1)));
  191.           else
  192.             abort ();
  193.         }
  194.           offset = XEXP (addr, 1);
  195.         }
  196.       else if (GET_CODE (XEXP (addr, 1)) == REG)
  197.         {
  198.           if (reg1)
  199.         ireg = reg1, breg = XEXP (addr, 1), reg1 = 0;
  200.           else
  201.         reg1 = XEXP (addr, 1);
  202.         }
  203.       else if (GET_CODE (XEXP (addr, 1)) == MULT)
  204.         {
  205.           if (ireg)
  206.         abort ();
  207.           ireg = XEXP (addr, 1);
  208.         }
  209.       else
  210.         abort ();
  211.     }
  212.       else
  213.     abort ();
  214.  
  215.       /* If REG1 is non-zero, figure out if it is a base or index register.  */
  216.       if (reg1)
  217.     {
  218.       if (breg != 0 || (offset && GET_CODE (offset) == MEM))
  219.         {
  220.           if (ireg)
  221.         abort ();
  222.           ireg = reg1;
  223.         }
  224.       else
  225.         breg = reg1;
  226.     }
  227.  
  228.       if (offset != 0)
  229.     output_address (offset);
  230.  
  231.       if (breg != 0)
  232.     fprintf (file, "(%s)", reg_names[REGNO (breg)]);
  233.  
  234.       if (ireg != 0)
  235.     {
  236.       if (GET_CODE (ireg) == MULT)
  237.         ireg = XEXP (ireg, 0);
  238.       if (GET_CODE (ireg) != REG)
  239.         abort ();
  240.       fprintf (file, "[%s]", reg_names[REGNO (ireg)]);
  241.     }
  242.       break;
  243.  
  244.     default:
  245.       output_addr_const (file, addr);
  246.     }
  247. }
  248.  
  249. char *
  250. rev_cond_name (op)
  251.      rtx op;
  252. {
  253.   switch (GET_CODE (op))
  254.     {
  255.     case EQ:
  256.       return "neq";
  257.     case NE:
  258.       return "eql";
  259.     case LT:
  260.       return "geq";
  261.     case LE:
  262.       return "gtr";
  263.     case GT:
  264.       return "leq";
  265.     case GE:
  266.       return "lss";
  267.     case LTU:
  268.       return "gequ";
  269.     case LEU:
  270.       return "gtru";
  271.     case GTU:
  272.       return "lequ";
  273.     case GEU:
  274.       return "lssu";
  275.  
  276.     default:
  277.       abort ();
  278.     }
  279. }
  280.  
  281. int
  282. vax_float_literal(c)
  283.     register rtx c;
  284. {
  285.   register enum machine_mode mode;
  286.   int i;
  287.   union {double d; int i[2];} val;
  288.  
  289.   if (GET_CODE (c) != CONST_DOUBLE)
  290.     return 0;
  291.  
  292.   mode = GET_MODE (c);
  293.  
  294.   if (c == const_tiny_rtx[(int) mode][0]
  295.       || c == const_tiny_rtx[(int) mode][1]
  296.       || c == const_tiny_rtx[(int) mode][2])
  297.     return 1;
  298.  
  299. #if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
  300.  
  301.   val.i[0] = CONST_DOUBLE_LOW (c);
  302.   val.i[1] = CONST_DOUBLE_HIGH (c);
  303.  
  304.   for (i = 0; i < 7; i ++)
  305.     if (val.d == 1 << i || val.d == 1 / (1 << i))
  306.       return 1;
  307. #endif
  308.   return 0;
  309. }
  310.  
  311.  
  312. /* Return the cost in cycles of a memory address, relative to register
  313.    indirect.
  314.  
  315.    Each of the following adds the indicated number of cycles:
  316.  
  317.    1 - symbolic address
  318.    1 - pre-decrement
  319.    1 - indexing and/or offset(register)
  320.    2 - indirect */
  321.  
  322.  
  323. int vax_address_cost(addr)
  324.     register rtx addr;
  325. {
  326.   int reg = 0, indexed = 0, indir = 0, offset = 0, predec = 0;
  327.   rtx plus_op0 = 0, plus_op1 = 0;
  328.  restart:
  329.   switch (GET_CODE (addr))
  330.     {
  331.     case PRE_DEC:
  332.       predec = 1;
  333.     case REG:
  334.     case SUBREG:
  335.     case POST_INC:
  336.       reg = 1;
  337.       break;
  338.     case MULT:
  339.       indexed = 1;    /* 2 on VAX 2 */
  340.       break;
  341.     case CONST_INT:
  342.       /* byte offsets cost nothing (on a VAX 2, they cost 1 cycle) */
  343.       if (offset == 0)
  344.     offset = (unsigned)(INTVAL(addr)+128) > 256;
  345.       break;
  346.     case CONST:
  347.     case SYMBOL_REF:
  348.       offset = 1;    /* 2 on VAX 2 */
  349.       break;
  350.     case LABEL_REF:    /* this is probably a byte offset from the pc */
  351.       if (offset == 0)
  352.     offset = 1;
  353.       break;
  354.     case PLUS:
  355.       if (plus_op0)
  356.     plus_op1 = XEXP (addr, 0);
  357.       else
  358.     plus_op0 = XEXP (addr, 0);
  359.       addr = XEXP (addr, 1);
  360.       goto restart;
  361.     case MEM:
  362.       indir = 2;    /* 3 on VAX 2 */
  363.       addr = XEXP (addr, 0);
  364.       goto restart;
  365.     }
  366.  
  367.   /*