PR middle-end/32889
authordanglin <danglin@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 9 Dec 2007 18:02:08 +0000 (18:02 +0000)
committerdanglin <danglin@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 9 Dec 2007 18:02:08 +0000 (18:02 +0000)
PR target/34091
* pa.md: Consolidate HImode and QImode move patterns into one pattern
each, eliminating floating-point alternatives.
* pa-protos.h (pa_cannot_change_mode_class, pa_modes_tieable_p):
Declare functions.
* pa-64.h (SECONDARY_MEMORY_NEEDED): Define here.
* pa.c (pa_secondary_reload): Use an intermediate general register
for copies to/from floating-point register classes.  Simplify code
SHIFT_REGS class.  Provide additional comments.
(pa_cannot_change_mode_class, pa_modes_tieable_p): New functions.
* pa.h (MODES_TIEABLE_P): Use pa_modes_tieable_p.
(SECONDARY_MEMORY_NEEDED): Delete define.
(INT14_OK_STRICT): Define.
(MODE_OK_FOR_SCALED_INDEXING_P): Allow SFmode and DFmode when using
soft float.
(MODE_OK_FOR_UNSCALED_INDEXING_P): Likewise.
(GO_IF_LEGITIMATE_ADDRESS): Use INT14_OK_STRICT in REG+D case for
SFmode and DFmode.
(LEGITIMIZE_RELOAD_ADDRESS): Use INT14_OK_STRICT in mask selection.
Align DImode offsets when generating 64-bit code.
* pa32-regs.h (VALID_FP_MODE_P): Remove QImode and HImode.
(CANNOT_CHANGE_MODE_CLASS): Define.
* pa64-regs.h (VALID_FP_MODE_P): Remove QImode and HImode.
(CANNOT_CHANGE_MODE_CLASS): Define using pa_cannot_change_mode_class.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@130725 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/pa/pa-64.h
gcc/config/pa/pa-protos.h
gcc/config/pa/pa.c
gcc/config/pa/pa.h
gcc/config/pa/pa.md
gcc/config/pa/pa32-regs.h
gcc/config/pa/pa64-regs.h

index 1e480c3..b3bb96e 100644 (file)
@@ -1,3 +1,31 @@
+2007-12-09  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>
+
+       PR middle-end/32889
+       PR target/34091
+       * pa.md: Consolidate HImode and QImode move patterns into one pattern
+       each, eliminating floating-point alternatives.
+       * pa-protos.h (pa_cannot_change_mode_class, pa_modes_tieable_p):
+       Declare functions.
+       * pa-64.h (SECONDARY_MEMORY_NEEDED): Define here.
+       * pa.c (pa_secondary_reload): Use an intermediate general register
+       for copies to/from floating-point register classes.  Simplify code
+       SHIFT_REGS class.  Provide additional comments.
+       (pa_cannot_change_mode_class, pa_modes_tieable_p): New functions.
+       * pa.h (MODES_TIEABLE_P): Use pa_modes_tieable_p.
+       (SECONDARY_MEMORY_NEEDED): Delete define.
+       (INT14_OK_STRICT): Define.
+       (MODE_OK_FOR_SCALED_INDEXING_P): Allow SFmode and DFmode when using
+       soft float.
+       (MODE_OK_FOR_UNSCALED_INDEXING_P): Likewise.
+       (GO_IF_LEGITIMATE_ADDRESS): Use INT14_OK_STRICT in REG+D case for
+       SFmode and DFmode.
+       (LEGITIMIZE_RELOAD_ADDRESS): Use INT14_OK_STRICT in mask selection.
+       Align DImode offsets when generating 64-bit code.
+       * pa32-regs.h (VALID_FP_MODE_P): Remove QImode and HImode.
+       (CANNOT_CHANGE_MODE_CLASS): Define.
+       * pa64-regs.h (VALID_FP_MODE_P): Remove QImode and HImode.
+       (CANNOT_CHANGE_MODE_CLASS): Define using pa_cannot_change_mode_class.
+
 2007-12-09  Jakub Jelinek  <jakub@redhat.com>
 
        PR fortran/22244
index e3adcf3..67c8179 100644 (file)
@@ -84,3 +84,17 @@ along with GCC; see the file COPYING3.  If not see
    want aggregates padded down.  */
 
 #define PAD_VARARGS_DOWN (!AGGREGATE_TYPE_P (type))
+
+/* In the PA architecture, it is not possible to directly move data
+   between GENERAL_REGS and FP_REGS.  On the 32-bit port, we use the
+   location at SP-16 because PA 1.X only supports 5-bit immediates for
+   floating-point loads and stores.  We don't expose this location in
+   the RTL to avoid scheduling related problems.  For example, the
+   store and load could be separated by a call to a pure or const
+   function which has no frame and this function might also use SP-16.
+   We have 14-bit immediates on the 64-bit port, so we use secondary
+   memory for the copies.  */
+#define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \
+  (MAYBE_FP_REG_CLASS_P (CLASS1) != FP_REG_CLASS_P (CLASS2)            \
+   || MAYBE_FP_REG_CLASS_P (CLASS2) != FP_REG_CLASS_P (CLASS1))
+
index ff621a3..7fc9dca 100644 (file)
@@ -172,6 +172,9 @@ extern void pa_asm_output_aligned_local (FILE *, const char *,
                                         unsigned HOST_WIDE_INT,
                                         unsigned int);
 extern void pa_hpux_asm_output_external (FILE *, tree, const char *);
+extern bool pa_cannot_change_mode_class (enum machine_mode, enum machine_mode,
+                                        enum reg_class);
+extern bool pa_modes_tieable_p (enum machine_mode, enum machine_mode);
 
 extern const int magic_milli[];
 extern int shadd_constant_p (int);
index 58122f6..b1f3a00 100644 (file)
@@ -5687,12 +5687,49 @@ pa_secondary_reload (bool in_p, rtx x, enum reg_class class,
   if (regno >= FIRST_PSEUDO_REGISTER || GET_CODE (x) == SUBREG)
     regno = true_regnum (x);
 
-  /* Handle out of range displacement for integer mode loads/stores of
-     FP registers.  */
-  if (((regno >= FIRST_PSEUDO_REGISTER || regno == -1)
-       && GET_MODE_CLASS (mode) == MODE_INT
-       && FP_REG_CLASS_P (class))
-      || (class == SHIFT_REGS && (regno <= 0 || regno >= 32)))
+  /* In order to allow 14-bit displacements in integer loads and stores,
+     we need to prevent reload from generating out of range integer mode
+     loads and stores to the floating point registers.  Previously, we
+     used to call for a secondary reload and have emit_move_sequence()
+     fix the instruction sequence.  However, reload occasionally wouldn't
+     generate the reload and we would end up with an invalid REG+D memory
+     address.  So, now we use an intermediate general register for most
+     memory loads and stores.  */
+  if ((regno >= FIRST_PSEUDO_REGISTER || regno == -1)
+      && GET_MODE_CLASS (mode) == MODE_INT
+      && FP_REG_CLASS_P (class))
+    {
+      /* Reload passes (mem:SI (reg/f:DI 30 %r30) when it wants to check
+        the secondary reload needed for a pseudo.  It never passes a
+        REG+D address.  */
+      if (GET_CODE (x) == MEM)
+       {
+         x = XEXP (x, 0);
+
+         /* We don't need an intermediate for indexed and LO_SUM DLT
+            memory addresses.  When INT14_OK_STRICT is true, it might
+            appear that we could directly allow register indirect
+            memory addresses.  However, this doesn't work because we
+            don't support SUBREGs in floating-point register copies
+            and reload doesn't tell us when it's going to use a SUBREG.  */
+         if (IS_INDEX_ADDR_P (x)
+             || IS_LO_SUM_DLT_ADDR_P (x))
+           return NO_REGS;
+
+         /* Otherwise, we need an intermediate general register.  */
+         return GENERAL_REGS;
+       }
+
+      /* Request a secondary reload with a general scratch register
+        for everthing else.  ??? Could symbolic operands be handled
+        directly when generating non-pic PA 2.0 code?  */
+      sri->icode = in_p ? reload_in_optab[mode] : reload_out_optab[mode];
+      return NO_REGS;
+    }
+
+  /* We need a secondary register (GPR) for copies between the SAR
+     and anything other than a general register.  */
+  if (class == SHIFT_REGS && (regno <= 0 || regno >= 32))
     {
       sri->icode = in_p ? reload_in_optab[mode] : reload_out_optab[mode];
       return NO_REGS;
@@ -5701,16 +5738,15 @@ pa_secondary_reload (bool in_p, rtx x, enum reg_class class,
   /* A SAR<->FP register copy requires a secondary register (GPR) as
      well as secondary memory.  */
   if (regno >= 0 && regno < FIRST_PSEUDO_REGISTER
-      && ((REGNO_REG_CLASS (regno) == SHIFT_REGS && FP_REG_CLASS_P (class))
-         || (class == SHIFT_REGS
-             && FP_REG_CLASS_P (REGNO_REG_CLASS (regno)))))
+      && (REGNO_REG_CLASS (regno) == SHIFT_REGS
+      && FP_REG_CLASS_P (class)))
     {
       sri->icode = in_p ? reload_in_optab[mode] : reload_out_optab[mode];
       return NO_REGS;
     }
 
   /* Secondary reloads of symbolic operands require %r1 as a scratch
-     register when we're generating PIC code and the operand isn't
+     register when we're generating PIC code and when the operand isn't
      readonly.  */
   if (GET_CODE (x) == HIGH)
     x = XEXP (x, 0);
@@ -9570,4 +9606,62 @@ pa_hpux_file_end (void)
 }
 #endif
 
+/* Return true if a change from mode FROM to mode TO for a register
+   in register class CLASS is invalid.  */
+
+bool
+pa_cannot_change_mode_class (enum machine_mode from, enum machine_mode to,
+                            enum reg_class class)
+{
+  if (from == to)
+    return false;
+
+  /* Reject changes to/from complex and vector modes.  */
+  if (COMPLEX_MODE_P (from) || VECTOR_MODE_P (from)
+      || COMPLEX_MODE_P (to) || VECTOR_MODE_P (to))
+    return true;
+      
+  if (GET_MODE_SIZE (from) == GET_MODE_SIZE (to))
+    return false;
+
+  /* There is no way to load QImode or HImode values directly from
+     memory.  SImode loads to the FP registers are not zero extended.
+     On the 64-bit target, this conflicts with the definition of
+     LOAD_EXTEND_OP.  Thus, we can't allow changing between modes
+     with different sizes in the floating-point registers.  */
+  if (MAYBE_FP_REG_CLASS_P (class))
+    return true;
+
+  /* HARD_REGNO_MODE_OK places modes with sizes larger than a word
+     in specific sets of registers.  Thus, we cannot allow changing
+     to a larger mode when it's larger than a word.  */
+  if (GET_MODE_SIZE (to) > UNITS_PER_WORD
+      && GET_MODE_SIZE (to) > GET_MODE_SIZE (from))
+    return true;
+
+  return false;
+}
+
+/* Returns TRUE if it is a good idea to tie two pseudo registers
+   when one has mode MODE1 and one has mode MODE2.
+   If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
+   for any hard reg, then this must be FALSE for correct output.
+   
+   We should return FALSE for QImode and HImode because these modes
+   are not ok in the floating-point registers.  However, this prevents
+   tieing these modes to SImode and DImode in the general registers.
+   So, this isn't a good idea.  We rely on HARD_REGNO_MODE_OK and
+   CANNOT_CHANGE_MODE_CLASS to prevent these modes from being used
+   in the floating-point registers.  */
+
+bool
+pa_modes_tieable_p (enum machine_mode mode1, enum machine_mode mode2)
+{
+  /* Don't tie modes in different classes.  */
+  if (GET_MODE_CLASS (mode1) != GET_MODE_CLASS (mode2))
+    return false;
+
+  return true;
+}
+
 #include "gt-pa.h"
index 8a7fb63..f8cf9d2 100644 (file)
@@ -349,7 +349,7 @@ typedef struct machine_function GTY(())
    If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
    for any hard reg, then this must be 0 for correct output.  */
 #define MODES_TIEABLE_P(MODE1, MODE2) \
-  (GET_MODE_CLASS (MODE1) == GET_MODE_CLASS (MODE2))
+  pa_modes_tieable_p (MODE1, MODE2)
 
 /* Specify the registers used for certain standard purposes.
    The values of these macros are register numbers.  */
@@ -497,17 +497,6 @@ extern struct rtx_def *hppa_pic_save_rtx (void);
 #define MAYBE_FP_REG_CLASS_P(CLASS) \
   reg_classes_intersect_p ((CLASS), FP_REGS)
 
-/* On the PA it is not possible to directly move data between
-   GENERAL_REGS and FP_REGS.  On the 32-bit port, we use the
-   location at SP-16.  We don't expose this location in the RTL to
-   avoid scheduling related problems.  For example, the store and
-   load could be separated by a call to a pure or const function
-   which has no frame and uses SP-16.  */
-#define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE)                  \
-  (TARGET_64BIT                                                                \
-   && (MAYBE_FP_REG_CLASS_P (CLASS1) != FP_REG_CLASS_P (CLASS2)                \
-       || MAYBE_FP_REG_CLASS_P (CLASS2) != FP_REG_CLASS_P (CLASS1)))
-
 \f
 /* Stack layout; function entry, exit and calling.  */
 
@@ -1116,6 +1105,24 @@ extern int may_call_alloca;
    && REG_OK_FOR_BASE_P (XEXP (OP, 0))                 \
    && GET_CODE (XEXP (OP, 1)) == UNSPEC)
 
+/* Nonzero if 14-bit offsets can be used for all loads and stores.
+   This is not possible when generating PA 1.x code as floating point
+   loads and stores only support 5-bit offsets.  Note that we do not
+   forbid the use of 14-bit offsets in GO_IF_LEGITIMATE_ADDRESS.
+   Instead, we use pa_secondary_reload() to reload integer mode
+   REG+D memory addresses used in floating point loads and stores.
+
+   FIXME: the ELF32 linker clobbers the LSB of the FP register number
+   in PA 2.0 floating-point insns with long displacements.  This is
+   because R_PARISC_DPREL14WR and other relocations like it are not
+   yet supported by GNU ld.  For now, we reject long displacements
+   on this target.  */
+
+#define INT14_OK_STRICT \
+  (TARGET_SOFT_FLOAT                                                   \
+   || TARGET_DISABLE_FPREGS                                            \
+   || (TARGET_PA_20 && !TARGET_ELF32))
+
 /* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
    and check its validity for a certain class.
    We have two alternate definitions for each of them.
@@ -1134,16 +1141,18 @@ extern int may_call_alloca;
 /* Nonzero if X is a hard reg that can be used as an index
    or if it is a pseudo reg.  */
 #define REG_OK_FOR_INDEX_P(X) \
-(REGNO (X) && (REGNO (X) < 32 || REGNO (X) >= FIRST_PSEUDO_REGISTER))
+  (REGNO (X) && (REGNO (X) < 32 || REGNO (X) >= FIRST_PSEUDO_REGISTER))
+
 /* Nonzero if X is a hard reg that can be used as a base reg
    or if it is a pseudo reg.  */
 #define REG_OK_FOR_BASE_P(X) \
-(REGNO (X) && (REGNO (X) < 32 || REGNO (X) >= FIRST_PSEUDO_REGISTER))
+  (REGNO (X) && (REGNO (X) < 32 || REGNO (X) >= FIRST_PSEUDO_REGISTER))
 
 #else
 
 /* Nonzero if X is a hard reg that can be used as an index.  */
 #define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
+
 /* Nonzero if X is a hard reg that can be used as a base reg.  */
 #define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
 
@@ -1195,11 +1204,7 @@ extern int may_call_alloca;
 
    We treat a SYMBOL_REF as legitimate if it is part of the current
    function's constant-pool, because such addresses can actually be
-   output as REG+SMALLINT. 
-
-   Note we only allow 5-bit immediates for access to a constant address;
-   doing so avoids losing for loading/storing a FP register at an address
-   which will not fit in 5 bits.  */
+   output as REG+SMALLINT.  */
 
 #define VAL_5_BITS_P(X) ((unsigned HOST_WIDE_INT)(X) + 0x10 < 0x20)
 #define INT_5_BITS(X) VAL_5_BITS_P (INTVAL (X))
@@ -1227,7 +1232,8 @@ extern int may_call_alloca;
   ((TARGET_64BIT && (MODE) == DImode)                                  \
    || (MODE) == SImode                                                 \
    || (MODE) == HImode                                                 \
-   || (!TARGET_SOFT_FLOAT && ((MODE) == DFmode || (MODE) == SFmode)))
+   || (MODE) == SFmode                                                 \
+   || (MODE) == DFmode)
 
 /* These are the modes that we allow for unscaled indexing.  */
 #define MODE_OK_FOR_UNSCALED_INDEXING_P(MODE) \
@@ -1235,7 +1241,8 @@ extern int may_call_alloca;
    || (MODE) == SImode                                                 \
    || (MODE) == HImode                                                 \
    || (MODE) == QImode                                                 \
-   || (!TARGET_SOFT_FLOAT && ((MODE) == DFmode || (MODE) == SFmode)))
+   || (MODE) == SFmode                                                 \
+   || (MODE) == DFmode)
 
 #define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
 {                                                                      \
@@ -1269,20 +1276,10 @@ extern int may_call_alloca;
                           || (INTVAL (index) % 8) == 0))               \
                   /* Similarly, the base register for SFmode/DFmode    \
                      loads and stores with long displacements must     \
-                     be aligned.                                       \
-                                                                       \
-                     FIXME: the ELF32 linker clobbers the LSB of       \
-                     the FP register number in PA 2.0 floating-point   \
-                     insns with long displacements.  This is because   \
-                     R_PARISC_DPREL14WR and other relocations like     \
-                     it are not supported.  For now, we reject long    \
-                     displacements on this target.  */                 \
+                     be aligned.  */                                   \
                   || (((MODE) == SFmode || (MODE) == DFmode)           \
-                      && (TARGET_SOFT_FLOAT                            \
-                          || (TARGET_PA_20                             \
-                              && !TARGET_ELF32                         \
-                              && (INTVAL (index)                       \
-                                  % GET_MODE_SIZE (MODE)) == 0)))))    \
+                      && INT14_OK_STRICT                               \
+                      && (INTVAL (index) % GET_MODE_SIZE (MODE)) == 0))) \
               || INT_5_BITS (index)))                                  \
        goto ADDR;                                                      \
       if (!TARGET_DISABLE_INDEXING                                     \
@@ -1382,7 +1379,7 @@ do {                                                                      \
   rtx new, temp = NULL_RTX;                                            \
                                                                        \
   mask = (GET_MODE_CLASS (MODE) == MODE_FLOAT                          \
-         ? (TARGET_PA_20 && !TARGET_ELF32 ? 0x3fff : 0x1f) : 0x3fff);  \
+         ? (INT14_OK_STRICT ? 0x3fff : 0x1f) : 0x3fff);                \
                                                                        \
   if (optimize && GET_CODE (AD) == PLUS)                               \
     temp = simplify_binary_operation (PLUS, Pmode,                     \
@@ -1404,9 +1401,10 @@ do {                                                                     \
        newoffset = offset & ~mask;                                     \
                                                                        \
       /* Ensure that long displacements are aligned.  */               \
-      if (!VAL_5_BITS_P (newoffset)                                    \
-         && GET_MODE_CLASS (MODE) == MODE_FLOAT)                       \
-       newoffset &= ~(GET_MODE_SIZE (MODE) -1);                        \
+      if (mask == 0x3fff                                               \
+         && (GET_MODE_CLASS (MODE) == MODE_FLOAT                       \
+             || (TARGET_64BIT && (MODE) == DImode)))                   \
+       newoffset &= ~(GET_MODE_SIZE (MODE) - 1);                       \
                                                                        \
       if (newoffset != 0 && VAL_14_BITS_P (newoffset))                 \
        {                                                               \
index a515980..9487afa 100644 (file)
 
 (define_insn ""
   [(set (match_operand:HI 0 "move_dest_operand"
-                         "=r,r,r,r,r,Q,!*q,!r,!*f,?r,?*f")
-       (match_operand:HI 1 "move_src_operand"
-                         "r,J,N,K,RQ,rM,!rM,!*q,!*fM,*f,r"))]
-  "(register_operand (operands[0], HImode)
-    || reg_or_0_operand (operands[1], HImode))
-   && !TARGET_SOFT_FLOAT
-   && !TARGET_64BIT"
-  "@
-   copy %1,%0
-   ldi %1,%0
-   ldil L'%1,%0
-   {zdepi|depwi,z} %Z1,%0
-   ldh%M1 %1,%0
-   sth%M0 %r1,%0
-   mtsar %r1
-   {mfctl|mfctl,w} %sar,%0
-   fcpy,sgl %f1,%0
-   {fstws|fstw} %1,-16(%%sp)\n\t{ldws|ldw} -16(%%sp),%0
-   {stws|stw} %1,-16(%%sp)\n\t{fldws|fldw} -16(%%sp),%0"
-  [(set_attr "type" "move,move,move,shift,load,store,move,move,move,fpstore_load,store_fpload")
-   (set_attr "pa_combine_type" "addmove")
-   (set_attr "length" "4,4,4,4,4,4,4,4,4,8,8")])
-
-(define_insn ""
-  [(set (match_operand:HI 0 "move_dest_operand"
-                         "=r,r,r,r,r,Q,!*q,!r,!*f")
-       (match_operand:HI 1 "move_src_operand"
-                         "r,J,N,K,RQ,rM,!rM,!*q,!*fM"))]
-  "(register_operand (operands[0], HImode)
-    || reg_or_0_operand (operands[1], HImode))
-   && !TARGET_SOFT_FLOAT
-   && TARGET_64BIT"
-  "@
-   copy %1,%0
-   ldi %1,%0
-   ldil L'%1,%0
-   {zdepi|depwi,z} %Z1,%0
-   ldh%M1 %1,%0
-   sth%M0 %r1,%0
-   mtsar %r1
-   {mfctl|mfctl,w} %sar,%0
-   fcpy,sgl %f1,%0"
-  [(set_attr "type" "move,move,move,shift,load,store,move,move,move")
-   (set_attr "pa_combine_type" "addmove")
-   (set_attr "length" "4,4,4,4,4,4,4,4,4")])
-
-(define_insn ""
-  [(set (match_operand:HI 0 "move_dest_operand"
                          "=r,r,r,r,r,Q,!*q,!r")
        (match_operand:HI 1 "move_src_operand"
                          "r,J,N,K,RQ,rM,!rM,!*q"))]
   "(register_operand (operands[0], HImode)
-    || reg_or_0_operand (operands[1], HImode))
-   && TARGET_SOFT_FLOAT"
+    || reg_or_0_operand (operands[1], HImode))"
   "@
    copy %1,%0
    ldi %1,%0
 
 (define_insn ""
   [(set (match_operand:QI 0 "move_dest_operand"
-                         "=r,r,r,r,r,Q,!*q,!r,!*f,?r,?*f")
-       (match_operand:QI 1 "move_src_operand"
-                         "r,J,N,K,RQ,rM,!rM,!*q,!*fM,*f,r"))]
-  "(register_operand (operands[0], QImode)
-    || reg_or_0_operand (operands[1], QImode))
-   && !TARGET_SOFT_FLOAT
-   && !TARGET_64BIT"
-  "@
-   copy %1,%0
-   ldi %1,%0
-   ldil L'%1,%0
-   {zdepi|depwi,z} %Z1,%0
-   ldb%M1 %1,%0
-   stb%M0 %r1,%0
-   mtsar %r1
-   {mfctl|mfctl,w} %%sar,%0
-   fcpy,sgl %f1,%0
-   {fstws|fstw} %1,-16(%%sp)\n\t{ldws|ldw} -16(%%sp),%0
-   {stws|stw} %1,-16(%%sp)\n\t{fldws|fldw} -16(%%sp),%0"
-  [(set_attr "type" "move,move,move,shift,load,store,move,move,move,fpstore_load,store_fpload")
-   (set_attr "pa_combine_type" "addmove")
-   (set_attr "length" "4,4,4,4,4,4,4,4,4,8,8")])
-
-(define_insn ""
-  [(set (match_operand:QI 0 "move_dest_operand"
-                         "=r,r,r,r,r,Q,!*q,!r,!*f")
-       (match_operand:QI 1 "move_src_operand"
-                         "r,J,N,K,RQ,rM,!rM,!*q,!*fM"))]
-  "(register_operand (operands[0], QImode)
-    || reg_or_0_operand (operands[1], QImode))
-   && !TARGET_SOFT_FLOAT
-   && TARGET_64BIT"
-  "@
-   copy %1,%0
-   ldi %1,%0
-   ldil L'%1,%0
-   {zdepi|depwi,z} %Z1,%0
-   ldb%M1 %1,%0
-   stb%M0 %r1,%0
-   mtsar %r1
-   {mfctl|mfctl,w} %%sar,%0
-   fcpy,sgl %f1,%0"
-  [(set_attr "type" "move,move,move,shift,load,store,move,move,move")
-   (set_attr "pa_combine_type" "addmove")
-   (set_attr "length" "4,4,4,4,4,4,4,4,4")])
-
-(define_insn ""
-  [(set (match_operand:QI 0 "move_dest_operand"
                          "=r,r,r,r,r,Q,!*q,!r")
        (match_operand:QI 1 "move_src_operand"
                          "r,J,N,K,RQ,rM,!rM,!*q"))]
   "(register_operand (operands[0], QImode)
-    || reg_or_0_operand (operands[1], QImode))
-   && TARGET_SOFT_FLOAT"
+    || reg_or_0_operand (operands[1], QImode))"
   "@
    copy %1,%0
    ldi %1,%0
index 782ad8d..89cbb9b 100644 (file)
 #define VALID_FP_MODE_P(MODE)                                          \
   ((MODE) == SFmode || (MODE) == DFmode                                        \
    || (MODE) == SCmode || (MODE) == DCmode                             \
-   || (MODE) == QImode || (MODE) == HImode || (MODE) == SImode         \
-   || (TARGET_PA_11 && (MODE) == DImode))
+   || (MODE) == SImode || (TARGET_PA_11 && (MODE) == DImode))
 
 /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
 
@@ -288,6 +287,11 @@ enum reg_class { NO_REGS, R1_REGS, GENERAL_REGS, FPUPPER_REGS, FP_REGS,
   {0x00000000, 0x00000000, 0x01000000},        /* SHIFT_REGS */                \
   {0xfffffffe, 0xffffffff, 0x01ffffff}}        /* ALL_REGS */
 
+/* Defines invalid mode changes.  */
+
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
+  pa_cannot_change_mode_class (FROM, TO, CLASS)
+
 /* Return the class number of the smallest class containing
    reg number REGNO.  This could be a conditional expression
    or could index an array.  */
index ddc1f06..828265f 100644 (file)
@@ -156,8 +156,7 @@ along with GCC; see the file COPYING3.  If not see
 #define VALID_FP_MODE_P(MODE)                                          \
   ((MODE) == SFmode || (MODE) == DFmode                                        \
    || (MODE) == SCmode || (MODE) == DCmode                             \
-   || (MODE) == QImode || (MODE) == HImode || (MODE) == SImode         \
-   || (MODE) == DImode)
+   || (MODE) == SImode || (MODE) == DImode)
 
 /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
    On the HP-PA, the cpu registers can hold any mode.  We
@@ -242,17 +241,10 @@ enum reg_class { NO_REGS, R1_REGS, GENERAL_REGS, FPUPPER_REGS, FP_REGS,
   {0x00000000, 0x10000000},    /* SHIFT_REGS */                \
   {0xfffffffe, 0x1fffffff}}    /* ALL_REGS */
 
-/* Defines invalid mode changes.
+/* Defines invalid mode changes.  */
 
-   SImode loads to floating-point registers are not zero-extended.
-   The definition for LOAD_EXTEND_OP specifies that integer loads
-   narrower than BITS_PER_WORD will be zero-extended.  As a result,
-   we inhibit changes from SImode unless they are to a mode that is
-   identical in size.  */
-
-#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS)              \
-  ((FROM) == SImode && GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO)       \
-   ? reg_classes_intersect_p (CLASS, FP_REGS) : 0)
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
+  pa_cannot_change_mode_class (FROM, TO, CLASS)
 
 /* Return the class number of the smallest class containing
    reg number REGNO.  This could be a conditional expression