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 / recog.c < prev    next >
C/C++ Source or Header  |  1994-02-06  |  55KB  |  1,960 lines

  1. /* Subroutines used by or related to instruction recognition.
  2.    Copyright (C) 1987, 1988, 1991, 1992 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.  
  21. #include "config.h"
  22. #include "rtl.h"
  23. #include <stdio.h>
  24. #include "insn-config.h"
  25. #include "insn-attr.h"
  26. #include "insn-flags.h"
  27. #include "insn-codes.h"
  28. #include "recog.h"
  29. #include "regs.h"
  30. #include "hard-reg-set.h"
  31. #include "flags.h"
  32. #include "real.h"
  33.  
  34. #ifndef STACK_PUSH_CODE
  35. #ifdef STACK_GROWS_DOWNWARD
  36. #define STACK_PUSH_CODE PRE_DEC
  37. #else
  38. #define STACK_PUSH_CODE PRE_INC
  39. #endif
  40. #endif
  41.  
  42. /* Import from final.c: */
  43. extern rtx alter_subreg ();
  44.  
  45. int strict_memory_address_p ();
  46. int memory_address_p ();
  47.  
  48. /* Nonzero means allow operands to be volatile.
  49.    This should be 0 if you are generating rtl, such as if you are calling
  50.    the functions in optabs.c and expmed.c (most of the time).
  51.    This should be 1 if all valid insns need to be recognized,
  52.    such as in regclass.c and final.c and reload.c.
  53.  
  54.    init_recog and init_recog_no_volatile are responsible for setting this.  */
  55.  
  56. int volatile_ok;
  57.  
  58. /* On return from `constrain_operands', indicate which alternative
  59.    was satisfied.  */
  60.  
  61. int which_alternative;
  62.  
  63. /* Nonzero after end of reload pass.
  64.    Set to 1 or 0 by toplev.c.
  65.    Controls the significance of (SUBREG (MEM)).  */
  66.  
  67. int reload_completed;
  68.  
  69. /* Initialize data used by the function `recog'.
  70.    This must be called once in the compilation of a function
  71.    before any insn recognition may be done in the function.  */
  72.  
  73. void
  74. init_recog_no_volatile ()
  75. {
  76.   volatile_ok = 0;
  77. }
  78.  
  79. void
  80. init_recog ()
  81. {
  82.   volatile_ok = 1;
  83. }
  84.  
  85. /* Try recognizing the instruction INSN,
  86.    and return the code number that results.
  87.    Remeber the code so that repeated calls do not
  88.    need to spend the time for actual rerecognition.
  89.  
  90.    This function is the normal interface to instruction recognition.
  91.    The automatically-generated function `recog' is normally called
  92.    through this one.  (The only exception is in combine.c.)  */
  93.  
  94. int
  95. recog_memoized (insn)
  96.      rtx insn;
  97. {
  98.   if (INSN_CODE (insn) < 0)
  99.     INSN_CODE (insn) = recog (PATTERN (insn), insn, NULL_PTR);
  100.   return INSN_CODE (insn);
  101. }
  102.  
  103. /* Check that X is an insn-body for an `asm' with operands
  104.    and that the operands mentioned in it are legitimate.  */
  105.  
  106. int
  107. check_asm_operands (x)
  108.      rtx x;
  109. {
  110.   int noperands = asm_noperands (x);
  111.   rtx *operands;
  112.   int i;
  113.  
  114.   if (noperands < 0)
  115.     return 0;
  116.   if (noperands == 0)
  117.     return 1;
  118.  
  119.   operands = (rtx *) alloca (noperands * sizeof (rtx));
  120.   decode_asm_operands (x, operands, NULL_PTR, NULL_PTR, NULL_PTR);
  121.  
  122.   for (i = 0; i < noperands; i++)
  123.     if (!general_operand (operands[i], VOIDmode))
  124.       return 0;
  125.  
  126.   return 1;
  127. }
  128.  
  129. /* Static data for the next two routines.
  130.  
  131.    The maximum number of changes supported is defined as the maximum
  132.    number of operands times 5.  This allows for repeated substitutions
  133.    inside complex indexed address, or, alternatively, changes in up
  134.    to 5 insns.  */
  135.  
  136. #define MAX_CHANGE_LOCS    (MAX_RECOG_OPERANDS * 5)
  137.  
  138. static rtx change_objects[MAX_CHANGE_LOCS];
  139. static int change_old_codes[MAX_CHANGE_LOCS];
  140. static rtx *change_locs[MAX_CHANGE_LOCS];
  141. static rtx change_olds[MAX_CHANGE_LOCS];
  142.  
  143. static int num_changes = 0;
  144.  
  145. /* Validate a proposed change to OBJECT.  LOC is the location in the rtl for
  146.    at which NEW will be placed.  If OBJECT is zero, no validation is done,
  147.    the change is simply made.
  148.  
  149.    Two types of objects are supported:  If OBJECT is a MEM, memory_address_p
  150.    will be called with the address and mode as parameters.  If OBJECT is
  151.    an INSN, CALL_INSN, or JUMP_INSN, the insn will be re-recognized with
  152.    the change in place.
  153.  
  154.    IN_GROUP is non-zero if this is part of a group of changes that must be
  155.    performed as a group.  In that case, the changes will be stored.  The
  156.    function `apply_change_group' will validate and apply the changes.
  157.  
  158.    If IN_GROUP is zero, this is a single change.  Try to recognize the insn
  159.    or validate the memory reference with the change applied.  If the result
  160.    is not valid for the machine, suppress the change and return zero.
  161.    Otherwise, perform the change and return 1.  */
  162.  
  163. int
  164. validate_change (object, loc, new, in_group)
  165.     rtx object;
  166.     rtx *loc;
  167.     rtx new;
  168.     int in_group;
  169. {
  170.   rtx old = *loc;
  171.  
  172.   if (old == new || rtx_equal_p (old, new))
  173.     return 1;
  174.  
  175.   if (num_changes >= MAX_CHANGE_LOCS
  176.       || (in_group == 0 && num_changes != 0))
  177.     abort ();
  178.  
  179.   *loc = new;
  180.  
  181.   /* Save the information describing this change.  */
  182.   change_objects[num_changes] = object;
  183.   change_locs[num_changes] = loc;
  184.   change_olds[num_changes] = old;
  185.  
  186.   if (object && GET_CODE (object) != MEM)
  187.     {
  188.       /* Set INSN_CODE to force rerecognition of insn.  Save old code in
  189.      case invalid.  */
  190.       change_old_codes[num_changes] = INSN_CODE (object);
  191.       INSN_CODE (object) = -1;
  192.     }
  193.  
  194.   num_changes++;
  195.  
  196.   /* If we are making a group of changes, return 1.  Otherwise, validate the
  197.      change group we made.  */
  198.  
  199.   if (in_group)
  200.     return 1;
  201.   else
  202.     return apply_change_group ();
  203. }
  204.  
  205. /* Apply a group of changes previously issued with `validate_change'.
  206.    Return 1 if all changes are valid, zero otherwise.  */
  207.  
  208. int
  209. apply_change_group ()
  210. {
  211.   int i;
  212.  
  213.   /* The changes have been applied and all INSN_CODEs have been reset to force
  214.      rerecognition.
  215.  
  216.      The changes are valid if we aren't given an object, or if we are
  217.      given a MEM and it still is a valid address, or if this is in insn
  218.      and it is recognized.  In the latter case, if reload has completed,
  219.      we also require that the operands meet the constraints for
  220.      the insn.  We do not allow modifying an ASM_OPERANDS after reload
  221.      has completed because verifying the constraints is too difficult.  */
  222.  
  223.   for (i = 0; i < num_changes; i++)
  224.     {
  225.       rtx object = change_objects[i];
  226.  
  227.       if (object == 0)
  228.     continue;
  229.  
  230.       if (GET_CODE (object) == MEM)
  231.     {
  232.       if (! memory_address_p (GET_MODE (object), XEXP (object, 0)))
  233.         break;
  234.     }
  235.       else if ((recog_memoized (object) < 0
  236.         && (asm_noperands (PATTERN (object)) < 0
  237.             || ! check_asm_operands (PATTERN (object))
  238.             || reload_completed))
  239.            || (reload_completed
  240.            && (insn_extract (object),
  241.                ! constrain_operands (INSN_CODE (object), 1))))
  242.     {
  243.       rtx pat = PATTERN (object);
  244.  
  245.       /* Perhaps we couldn't recognize the insn because there were
  246.          extra CLOBBERs at the end.  If so, try to re-recognize
  247.          without the last CLOBBER (later iterations will cause each of
  248.          them to be eliminated, in turn).  But don't do this if we
  249.          have an ASM_OPERAND.  */
  250.       if (GET_CODE (pat) == PARALLEL
  251.           && GET_CODE (XVECEXP (pat, 0, XVECLEN (pat, 0) - 1)) == CLOBBER
  252.           && asm_noperands (PATTERN (object)) < 0)
  253.         {
  254.            rtx newpat;
  255.  
  256.            if (XVECLEN (pat, 0) == 2)
  257.          newpat = XVECEXP (pat, 0, 0);
  258.            else
  259.          {
  260.            int j;
  261.  
  262.            newpat = gen_rtx (PARALLEL, VOIDmode, 
  263.                      gen_rtvec (XVECLEN (pat, 0) - 1));
  264.            for (j = 0; j < XVECLEN (newpat, 0); j++)
  265.              XVECEXP (newpat, 0, j) = XVECEXP (pat, 0, j);
  266.          }
  267.  
  268.            /* Add a new change to this group to replace the pattern
  269.           with this new pattern.  Then consider this change
  270.           as having succeeded.  The change we added will
  271.           cause the entire call to fail if things remain invalid.
  272.  
  273.           Note that this can lose if a later change than the one
  274.           we are processing specified &XVECEXP (PATTERN (object), 0, X)
  275.           but this shouldn't occur.  */
  276.  
  277.            validate_change (object, &PATTERN (object), newpat, 1);
  278.          }
  279.       else if (GET_CODE (pat) == USE