OSDN Git Service

* final.c (alter_subreg): Allow the target to hook by-mode subreg
[pf3gnuchains/gcc-fork.git] / gcc / final.c
index 70a6fbe..6b851f2 100644 (file)
@@ -50,18 +50,7 @@ Boston, MA 02111-1307, USA.  */
 #else
 #include <varargs.h>
 #endif
-#include <stdio.h>
-#include <ctype.h>
-#if HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#else
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#endif
+#include "system.h"
 
 #include "tree.h"
 #include "rtl.h"
@@ -161,7 +150,7 @@ extern int length_unit_log; /* This is defined in insn-attrtab.c.  */
 static rtx this_is_asm_operands;
 
 /* Number of operands of this insn, for an `asm' with operands.  */
-static int insn_noperands;
+static unsigned int insn_noperands;
 
 /* Compare optimization flag.  */
 
@@ -1176,7 +1165,7 @@ shorten_branches (first)
          if (log)
            {
              int align = 1 << log;
-             int new_address = insn_current_address + align - 1 & -align;
+             int new_address = (insn_current_address + align - 1) & -align;
              insn_lengths[uid] = new_address - insn_current_address;
              insn_current_address = new_address;
            }
@@ -1279,7 +1268,7 @@ shorten_branches (first)
              if (log > insn_current_align)
                {
                  int align = 1 << log;
-                 int new_address= insn_current_address + align - 1 & -align;
+                 int new_address= (insn_current_address + align - 1) & -align;
                  insn_lengths[uid] = new_address - insn_current_address;
                  insn_current_align = log;
                  insn_current_address = new_address;
@@ -2366,7 +2355,7 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
        /* Detect `asm' construct with operands.  */
        if (asm_noperands (body) >= 0)
          {
-           int noperands = asm_noperands (body);
+           unsigned int noperands = asm_noperands (body);
            rtx *ops = (rtx *) alloca (noperands * sizeof (rtx));
            char *string;
 
@@ -2902,9 +2891,20 @@ alter_subreg (x)
 
   if (GET_CODE (y) == REG)
     {
-      /* If the containing reg really gets a hard reg, so do we.  */
+      /* If the word size is larger than the size of this register,
+        adjust the register number to compensate.  */
+      /* ??? Note that this just catches stragglers created by/for
+        integrate.  It would be better if we either caught these
+        earlier, or kept _all_ subregs until now and eliminate
+        gen_lowpart and friends.  */
+
       PUT_CODE (x, REG);
+#ifdef ALTER_HARD_SUBREG
+      REGNO (x) = ALTER_HARD_SUBREG(GET_MODE (x), SUBREG_WORD (x),
+                                   GET_MODE (y), REGNO (y));
+#else
       REGNO (x) = REGNO (y) + SUBREG_WORD (x);
+#endif
     }
   else if (GET_CODE (y) == MEM)
     {
@@ -3255,7 +3255,7 @@ output_asm_insn (template, operands)
 
            if (! (*p >= '0' && *p <= '9'))
              output_operand_lossage ("operand number missing after %-letter");
-           else if (this_is_asm_operands && c >= insn_noperands)
+           else if (this_is_asm_operands && (c < 0 || (unsigned int) c >= insn_noperands))
              output_operand_lossage ("operand number out of range");
            else if (letter == 'l')
              output_asm_label (operands[c]);
@@ -3288,7 +3288,7 @@ output_asm_insn (template, operands)
        else if (*p >= '0' && *p <= '9')
          {
            c = atoi (p);
-           if (this_is_asm_operands && c >= insn_noperands)
+           if (this_is_asm_operands && (c < 0 || (unsigned int) c >= insn_noperands))
              output_operand_lossage ("operand number out of range");
            else
              output_operand (operands[c], 0);