sh-protos.h (binary_float_operator): Remove declaration.
authorJ"orn Rennecke <joern.rennecke@superh.com>
Wed, 17 Jul 2002 15:15:04 +0000 (15:15 +0000)
committerJoern Rennecke <amylaar@gcc.gnu.org>
Wed, 17 Jul 2002 15:15:04 +0000 (16:15 +0100)
* sh-protos.h (binary_float_operator): Remove declaration.
(sh_expand_unop_v2sf, sh_expand_binop_v2sf): Declare.
* sh.c (print_operand, case 'N'): Check against CONST0_RTX.
(unary_float_operator, sh_expand_unop_v2sf): New functions.
(sh_expand_binop_v2sf): Likewise.
(zero_vec_operand): Delete.
(SH_BLTIN_UDI): New builtin shared signature define.  Renumbered
all non-shared ones.
(bdesc): Change all the mextr builtins to use SH_BLTIN_UDI.
Enable nsb and byterev.
* sh.h (CONDITIONAL_REGISTER_USAGE): Initialize DF_HI_REGS.
(HARD_REGNO_MODE_OK): Allow TImode in fp regs.  Allow V2SFmode
in general regs.
(enum reg_class, REG_CLASS_NAMES, REG_CLASS_CONTENTS): Add DF_HI_REGS.
(SECONDARY_OUTPUT_RELOAD_CLASS): Likewise.  Remove clause for
immediate operands.
(SECONDARY_INPUT_RELOAD_CLASS): Add clause for immediate operands.
Add DF_HI_REGS.
(CLASS_CANNOT_CHANGE_MODE, CLASS_CANNOT_CHANGE_MODE_P): Allow
lowpart fp regs - only for big endian for now.
(LEGITIMATE_CONSTANT_P): Don't allow non-zero float vectors
when FPU is in use.
(EXTRA_CONTRAINT_U): Check against CONST0_RTX.
(LOAD_EXTEND_OP): NIL for SImode.
(REGISTER_MOVE_COST): Add DF_HI_REGS.  Const for moves between
general and fp registers is 4.
PREDICATE_CODES: Amend binary_float_operator entry.
Remove zero_vec_operand.  Add unary_float_operator.
* sh.md (udivsi3_i4_media): Use truncate instead of paradoxical
subreg SET_DEST.
(truncdisi2, truncdihi2, movv2sf): Allow memory destinations.
(truncdiqi2): Do sign extension.
(movsi_media, movdi_media): Allow to use r63 to an fp register.
(movdf_media, movsf_media): Likewise.
(movv2sf_i, movv2sf_i+1): Don't use f{ld,st}.p or SUBREGS.
Collapse to one define_insn_and_split.  Allow immediate sources.
(addv2sf3, subv2sf3, mulv2sf3, divv2sf3): New patterns.
(movv4sf_i): Allow immediate sources.  Use simplify_gen_subreg.
(movv4sf): Allow immediate sources.
(movsf_media_nofpu+1): Don't split moves to FP registers.
(unary_sf_op, binary_sf_op, mshflo_w_x, concat_v2sf): New patterns.
(movv8qi_i+3): Check against CONST0_RTX.
(mextr1, mextr2. mextr3. mextr4, mextr5, mextr6, mextr7): Use DImode
for input and output operands.  Fix argument 3 to gen_mextr_rl.
(mmul23_wl, mmul01_wl, mmulsum_wq_i): s/const_vector/parallel/
(msad_ubq_i, mshf4_b, mshf0_b, mshf4_l, mshf0_l, mshf4_w): Likewise.
(mshf0_w, fipr, ftrv): Likewise.
(mshfhi_l_di): Now insn_and_split.  Can handle FP regs.

From-SVN: r55528

gcc/ChangeLog
gcc/config/sh/sh-protos.h
gcc/config/sh/sh.c
gcc/config/sh/sh.h
gcc/config/sh/sh.md

index 49ff07c84741274b916a220b969d3ded47216850..68e89f2ad503bd1ac1990f83a2ffc93611effc7f 100644 (file)
@@ -1,3 +1,54 @@
+Wed Jul 17 14:04:10 2002  J"orn Rennecke <joern.rennecke@superh.com>
+
+       * sh-protos.h (binary_float_operator): Remove declaration.
+       (sh_expand_unop_v2sf, sh_expand_binop_v2sf): Declare.
+       * sh.c (print_operand, case 'N'): Check against CONST0_RTX.
+       (unary_float_operator, sh_expand_unop_v2sf): New functions.
+       (sh_expand_binop_v2sf): Likewise.
+       (zero_vec_operand): Delete.
+       (SH_BLTIN_UDI): New builtin shared signature define.  Renumbered
+       all non-shared ones.
+       (bdesc): Change all the mextr builtins to use SH_BLTIN_UDI.
+       Enable nsb and byterev.
+       * sh.h (CONDITIONAL_REGISTER_USAGE): Initialize DF_HI_REGS.
+       (HARD_REGNO_MODE_OK): Allow TImode in fp regs.  Allow V2SFmode
+       in general regs.
+       (enum reg_class, REG_CLASS_NAMES, REG_CLASS_CONTENTS): Add DF_HI_REGS.
+       (SECONDARY_OUTPUT_RELOAD_CLASS): Likewise.  Remove clause for
+       immediate operands.
+       (SECONDARY_INPUT_RELOAD_CLASS): Add clause for immediate operands.
+       Add DF_HI_REGS.
+       (CLASS_CANNOT_CHANGE_MODE, CLASS_CANNOT_CHANGE_MODE_P): Allow
+       lowpart fp regs - only for big endian for now.
+       (LEGITIMATE_CONSTANT_P): Don't allow non-zero float vectors
+       when FPU is in use.
+       (EXTRA_CONTRAINT_U): Check against CONST0_RTX.
+       (LOAD_EXTEND_OP): NIL for SImode.
+       (REGISTER_MOVE_COST): Add DF_HI_REGS.  Const for moves between
+       general and fp registers is 4.
+       PREDICATE_CODES: Amend binary_float_operator entry.
+       Remove zero_vec_operand.  Add unary_float_operator.
+       * sh.md (udivsi3_i4_media): Use truncate instead of paradoxical
+       subreg SET_DEST.
+       (truncdisi2, truncdihi2, movv2sf): Allow memory destinations.
+       (truncdiqi2): Do sign extension.
+       (movsi_media, movdi_media): Allow to use r63 to an fp register.
+       (movdf_media, movsf_media): Likewise.
+       (movv2sf_i, movv2sf_i+1): Don't use f{ld,st}.p or SUBREGS.
+       Collapse to one define_insn_and_split.  Allow immediate sources.
+       (addv2sf3, subv2sf3, mulv2sf3, divv2sf3): New patterns.
+       (movv4sf_i): Allow immediate sources.  Use simplify_gen_subreg.
+       (movv4sf): Allow immediate sources.
+       (movsf_media_nofpu+1): Don't split moves to FP registers.
+       (unary_sf_op, binary_sf_op, mshflo_w_x, concat_v2sf): New patterns.
+       (movv8qi_i+3): Check against CONST0_RTX.
+       (mextr1, mextr2. mextr3. mextr4, mextr5, mextr6, mextr7): Use DImode
+       for input and output operands.  Fix argument 3 to gen_mextr_rl.
+       (mmul23_wl, mmul01_wl, mmulsum_wq_i): s/const_vector/parallel/
+       (msad_ubq_i, mshf4_b, mshf0_b, mshf4_l, mshf0_l, mshf4_w): Likewise.
+       (mshf0_w, fipr, ftrv): Likewise.
+       (mshfhi_l_di): Now insn_and_split.  Can handle FP regs.
+
 2002-07-17  Jeroen Dobbelaere  <jeroen.dobbelaere@acunia.com>
 
        * arm.h (ARM_NUM_INTS, ARM_NUM_REGS, ARM_NUM_REGS2): Renamed from
index ba74158d713e6e9336b6e2a4e4d90c01538441d8..432ab63367e0457d657fe9749edc4d18c505f548 100644 (file)
@@ -92,7 +92,6 @@ extern int fpscr_operand PARAMS ((rtx, enum machine_mode));
 extern int fpul_operand PARAMS ((rtx, enum machine_mode));
 extern int commutative_float_operator PARAMS ((rtx, enum machine_mode));
 extern int noncommutative_float_operator PARAMS ((rtx, enum machine_mode));
-extern int binary_float_operator PARAMS ((rtx, enum machine_mode));
 extern int reg_unused_after PARAMS ((rtx, rtx));
 extern void expand_sf_unop PARAMS ((rtx (*)(rtx, rtx, rtx), rtx *));
 extern void expand_sf_binop PARAMS ((rtx (*)(rtx, rtx, rtx, rtx), rtx *));
@@ -118,6 +117,8 @@ extern void output_file_start PARAMS ((FILE *));
 extern int sh_media_register_for_return PARAMS ((void));
 extern void sh_expand_prologue PARAMS ((void));
 extern void sh_expand_epilogue PARAMS ((void));
+extern void sh_expand_unop_v2sf (enum rtx_code, rtx, rtx);
+extern void sh_expand_binop_v2sf (enum rtx_code, rtx, rtx, rtx);
 extern int sh_need_epilogue PARAMS ((void));
 extern int initial_elimination_offset PARAMS ((int, int));
 extern int fldi_ok PARAMS ((void));
index 5687c0a8c525a216a03a08df3ad121b6d92b5159..315cdec5484d2b888aaf8ffbb08249f3bf09791a 100644 (file)
@@ -449,8 +449,7 @@ print_operand (stream, x, code)
       break;
 
     case 'N':
-      if (x == const0_rtx
-         || (GET_CODE (x) == CONST_VECTOR && zero_vec_operand (x, VOIDmode)))
+      if (x == CONST0_RTX (GET_MODE (x)))
        {
          fprintf ((stream), "r63");
          break;
@@ -6121,6 +6120,25 @@ noncommutative_float_operator (op, mode)
   return 0;
 }
 
+int
+unary_float_operator (op, mode)
+     rtx op;
+     enum machine_mode mode;
+{
+  if (GET_MODE (op) != mode)
+    return 0;
+  switch (GET_CODE (op))
+    {
+    case ABS:
+    case NEG:
+    case SQRT:
+      return 1;
+    default:
+      break;
+    }
+  return 0;
+}
+
 int
 binary_float_operator (op, mode)
      rtx op;
@@ -6285,23 +6303,6 @@ inqhi_operand (op, mode)
   return GET_CODE (op) == REG && FP_REGISTER_P (REGNO (op));
 }
 
-/* Return nonzero if V is a zero vector matching MODE.  */
-int
-zero_vec_operand (v, mode)
-     rtx v;
-     enum machine_mode mode;
-{
-  int i;
-
-  if (GET_CODE (v) != CONST_VECTOR
-      || (GET_MODE (v) != mode && mode != VOIDmode))
-    return 0;
-  for (i = XVECLEN (v, 0) - 1; i >= 0; i--)
-    if (XVECEXP (v, 0, i) != const0_rtx)
-      return 0;
-  return 1;
-}
-
 int
 sh_rep_vec (v, mode)
      rtx v;
@@ -7156,19 +7157,21 @@ static const char signature_args[][4] =
   { 0, 8, 2 },
 #define SH_BLTIN_STUA_Q 14
   { 0, 8, 1 },
-#define SH_BLTIN_NUM_SHARED_SIGNATURES 15
-#define SH_BLTIN_2 15
-#define SH_BLTIN_SU 15
+#define SH_BLTIN_UDI 15
+  { 0, 8, 1 },
+#define SH_BLTIN_NUM_SHARED_SIGNATURES 16
+#define SH_BLTIN_2 16
+#define SH_BLTIN_SU 16
   { 1, 2 },
-#define SH_BLTIN_3 16
-#define SH_BLTIN_SUS 16
+#define SH_BLTIN_3 17
+#define SH_BLTIN_SUS 17
   { 2, 2, 1 },
-#define SH_BLTIN_PSSV 17
+#define SH_BLTIN_PSSV 18
   { 0, 8, 2, 2 },
-#define SH_BLTIN_XXUU 18
-#define SH_BLTIN_UUUU 18
+#define SH_BLTIN_XXUU 19
+#define SH_BLTIN_UUUU 19
   { 1, 1, 1, 1 },
-#define SH_BLTIN_PV 19
+#define SH_BLTIN_PV 20
   { 0, 8 },
 };
 /* mcmv: operands considered unsigned. */
@@ -7200,13 +7203,13 @@ static const struct builtin_description bdesc[] =
   { CODE_FOR_mcnvs_lw, "__builtin_sh_media_MCNVS_LW", SH_BLTIN_3 },
   { CODE_FOR_mcnvs_wb, "__builtin_sh_media_MCNVS_WB", SH_BLTIN_V4HI2V8QI },
   { CODE_FOR_mcnvs_wub,        "__builtin_sh_media_MCNVS_WUB", SH_BLTIN_V4HI2V8QI },
-  { CODE_FOR_mextr1,   "__builtin_sh_media_MEXTR1", SH_BLTIN_V8QI3 },
-  { CODE_FOR_mextr2,   "__builtin_sh_media_MEXTR2", SH_BLTIN_V8QI3 },
-  { CODE_FOR_mextr3,   "__builtin_sh_media_MEXTR3", SH_BLTIN_V8QI3 },
-  { CODE_FOR_mextr4,   "__builtin_sh_media_MEXTR4", SH_BLTIN_V8QI3 },
-  { CODE_FOR_mextr5,   "__builtin_sh_media_MEXTR5", SH_BLTIN_V8QI3 },
-  { CODE_FOR_mextr6,   "__builtin_sh_media_MEXTR6", SH_BLTIN_V8QI3 },
-  { CODE_FOR_mextr7,   "__builtin_sh_media_MEXTR7", SH_BLTIN_V8QI3 },
+  { CODE_FOR_mextr1,   "__builtin_sh_media_MEXTR1", SH_BLTIN_UDI },
+  { CODE_FOR_mextr2,   "__builtin_sh_media_MEXTR2", SH_BLTIN_UDI },
+  { CODE_FOR_mextr3,   "__builtin_sh_media_MEXTR3", SH_BLTIN_UDI },
+  { CODE_FOR_mextr4,   "__builtin_sh_media_MEXTR4", SH_BLTIN_UDI },
+  { CODE_FOR_mextr5,   "__builtin_sh_media_MEXTR5", SH_BLTIN_UDI },
+  { CODE_FOR_mextr6,   "__builtin_sh_media_MEXTR6", SH_BLTIN_UDI },
+  { CODE_FOR_mextr7,   "__builtin_sh_media_MEXTR7", SH_BLTIN_UDI },
   { CODE_FOR_mmacfx_wl,        "__builtin_sh_media_MMACFX_WL", SH_BLTIN_MAC_HISI },
   { CODE_FOR_mmacnfx_wl,"__builtin_sh_media_MMACNFX_WL", SH_BLTIN_MAC_HISI },
   { CODE_FOR_mulv2si3, "__builtin_mulv2si3", SH_BLTIN_V2SI3, },
@@ -7261,8 +7264,10 @@ static const struct builtin_description bdesc[] =
   { CODE_FOR_sthi_q64, "__builtin_sh_media_STHI_Q", SH_BLTIN_STUA_Q },
   { CODE_FOR_stlo_l64, "__builtin_sh_media_STLO_L", SH_BLTIN_STUA_L },
   { CODE_FOR_stlo_q64, "__builtin_sh_media_STLO_Q", SH_BLTIN_STUA_Q },
+#endif
   { CODE_FOR_nsb,      "__builtin_sh_media_NSB", SH_BLTIN_SU },
   { CODE_FOR_byterev,  "__builtin_sh_media_BYTEREV", SH_BLTIN_2 },
+#if 0
   { CODE_FOR_prefetch32,"__builtin_sh_media_PREFO", SH_BLTIN_PSSV },
   { CODE_FOR_prefetch64,"__builtin_sh_media_PREFO", SH_BLTIN_PSSV }
 #endif
@@ -7408,4 +7413,33 @@ sh_expand_builtin (exp, target, subtarget, mode, ignore)
   emit_insn (pat);
   return target;
 }
+
+void
+sh_expand_unop_v2sf (code, op0, op1)
+     enum rtx_code code;
+     rtx op0, op1;
+{
+  rtx sel0 = const0_rtx;
+  rtx sel1 = const1_rtx;
+  rtx (*fn) (rtx, rtx, rtx, rtx, rtx) = gen_unary_sf_op;
+  rtx op = gen_rtx_fmt_e (code, SFmode, op1);
+
+  emit_insn ((*fn) (op0, op1, op, sel0, sel0));
+  emit_insn ((*fn) (op0, op1, op, sel1, sel1));
+}
+
+void
+sh_expand_binop_v2sf (code, op0, op1, op2)
+     enum rtx_code code;
+     rtx op0, op1, op2;
+{
+  rtx sel0 = const0_rtx;
+  rtx sel1 = const1_rtx;
+  rtx (*fn) (rtx, rtx, rtx, rtx, rtx, rtx, rtx) = gen_binary_sf_op;
+  rtx op = gen_rtx_fmt_ee (code, SFmode, op1, op2);
+
+  emit_insn ((*fn) (op0, op1, op2, op, sel0, sel0, sel0));
+  emit_insn ((*fn) (op0, op1, op2, op, sel1, sel1, sel1));
+}
+
 #include "gt-sh.h"
index 9d15fcf74182a28415ed309646d51d4d89ff0a94..c37b10c207e3da0ff3638e6b22cbb9a0a378f3f4 100644 (file)
@@ -106,6 +106,9 @@ do { \
       call_used_regs[MACH_REG] = 0;                                    \
       call_used_regs[MACL_REG] = 0;                                    \
     }                                                                  \
+  for (regno = FIRST_FP_REG + (TARGET_LITTLE_ENDIAN != 0);             \
+       regno <= LAST_FP_REG; regno += 2)                               \
+    SET_HARD_REG_BIT (reg_class_contents[DF_HI_REGS], regno);          \
   if (TARGET_SHMEDIA)                                                  \
     {                                                                  \
       for (regno = FIRST_TARGET_REG; regno <= LAST_TARGET_REG; regno ++)\
@@ -893,13 +896,16 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
    would require a tertiary reload when reloading from / to memory,
    and a secondary reload to reload from / to general regs; that
    seems to be a loosing proposition.  */
+/* We want to allow TImode FP regs so that when V4SFmode is loaded as TImode,
+   it won't be ferried through GP registers first.  */
 #define HARD_REGNO_MODE_OK(REGNO, MODE)                \
   (SPECIAL_REGISTER_P (REGNO) ? (MODE) == SImode \
    : (REGNO) == FPUL_REG ? (MODE) == SImode || (MODE) == SFmode        \
    : FP_REGISTER_P (REGNO) && (MODE) == SFmode \
    ? 1 \
    : (MODE) == V2SFmode \
-   ? (FP_REGISTER_P (REGNO) && ((REGNO) - FIRST_FP_REG) % 2 == 0) \
+   ? ((FP_REGISTER_P (REGNO) && ((REGNO) - FIRST_FP_REG) % 2 == 0) \
+      || (TARGET_SHMEDIA && GENERAL_REGISTER_P (REGNO))) \
    : (MODE) == V4SFmode \
    ? (FP_REGISTER_P (REGNO) && ((REGNO) - FIRST_FP_REG) % 4 == 0) \
    : (MODE) == V16SFmode \
@@ -912,7 +918,7 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
       || ((TARGET_SH3E || TARGET_SHMEDIA) && (MODE) == SCmode) \
       || (((TARGET_SH4 && (MODE) == DFmode) || (MODE) == DCmode \
           || (TARGET_SHMEDIA && ((MODE) == DFmode || (MODE) == DImode \
-                                 || (MODE) == V2SFmode))) \
+                                 || (MODE) == V2SFmode || (MODE) == TImode))) \
          && (((REGNO) - FIRST_FP_REG) & 1) == 0)) \
    : XD_REGISTER_P (REGNO) \
    ? (MODE) == DFmode \
@@ -1106,6 +1112,7 @@ enum reg_class
   GENERAL_REGS,
   FP0_REGS,
   FP_REGS,
+  DF_HI_REGS,
   DF_REGS,
   FPSCR_REGS,
   GENERAL_FP_REGS,
@@ -1129,6 +1136,7 @@ enum reg_class
   "GENERAL_REGS",      \
   "FP0_REGS",          \
   "FP_REGS",           \
+  "DF_HI_REGS",                \
   "DF_REGS",           \
   "FPSCR_REGS",                \
   "GENERAL_FP_REGS",   \
@@ -1162,6 +1170,8 @@ enum reg_class
   { 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000 },      \
 /* FP_REGS:  */                                                                \
   { 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000 },      \
+/* DF_HI_REGS:  Initialized in CONDITIONAL_REGISTER_USAGE.  */         \
+  { 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x0000ff00 },      \
 /* DF_REGS:  */                                                                \
   { 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x0000ff00 },      \
 /* FPSCR_REGS:  */                                                     \
@@ -1286,7 +1296,7 @@ extern const enum reg_class reg_class_from_letter[];
 
 #define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS,MODE,X) \
   ((((((CLASS) == FP_REGS || (CLASS) == FP0_REGS                       \
-       || (CLASS) == DF_REGS)                                          \
+       || (CLASS) == DF_REGS || (CLASS) == DF_HI_REGS)                 \
       && (GET_CODE (X) == REG && GENERAL_OR_AP_REGISTER_P (REGNO (X))))        \
      || (((CLASS) == GENERAL_REGS || (CLASS) == R0_REGS)               \
         && GET_CODE (X) == REG                                         \
@@ -1301,9 +1311,6 @@ extern const enum reg_class reg_class_from_letter[];
                  || REGNO (X) == T_REG                                 \
                  || system_reg_operand (X, VOIDmode)))))               \
    ? GENERAL_REGS                                                      \
-   : (((CLASS) == FP_REGS || (CLASS) == DF_REGS) && TARGET_SHMEDIA     \
-      && immediate_operand ((X), (MODE)))                              \
-   ? GENERAL_REGS                                                      \
    : ((CLASS) == TARGET_REGS                                           \
       || (TARGET_SHMEDIA && (CLASS) == SIBCALL_REGS))                  \
    ? ((target_operand ((X), (MODE))                                    \
@@ -1312,10 +1319,14 @@ extern const enum reg_class reg_class_from_letter[];
    : (((CLASS) == MAC_REGS || (CLASS) == PR_REGS)                      \
       && GET_CODE (X) == REG && ! GENERAL_REGISTER_P (REGNO (X))       \
       && (CLASS) != REGNO_REG_CLASS (REGNO (X)))                       \
+   ? GENERAL_REGS                                                      \
+   : ((CLASS) != GENERAL_REGS && GET_CODE (X) == REG                   \
+      && TARGET_REGISTER_P (REGNO (X)))                                        \
    ? GENERAL_REGS : NO_REGS)
 
 #define SECONDARY_INPUT_RELOAD_CLASS(CLASS,MODE,X)  \
-  ((((CLASS) == FP_REGS || (CLASS) == FP0_REGS || (CLASS) == DF_REGS)  \
+  ((((CLASS) == FP_REGS || (CLASS) == FP0_REGS || (CLASS) == DF_REGS   \
+     || (CLASS) == DF_HI_REGS)                                         \
     && ! TARGET_SHMEDIA                                                        \
     && immediate_operand ((X), (MODE))                                 \
     && ! ((fp_zero_operand (X) || fp_one_operand (X))                  \
@@ -1334,6 +1345,12 @@ extern const enum reg_class reg_class_from_letter[];
       && ((GET_CODE (X) == REG && REGNO (X) >= FIRST_PSEUDO_REGISTER)  \
          || (GET_CODE (X) == MEM && GET_CODE (XEXP ((X), 0)) == PLUS)))\
    ? GENERAL_REGS                                                      \
+   : (((CLASS) == FP_REGS || (CLASS) == DF_REGS || (CLASS) == DF_HI_REGS)\
+      && TARGET_SHMEDIA                                                        \
+      && immediate_operand ((X), (MODE))                               \
+      && (X) != CONST0_RTX (GET_MODE (X))                              \
+      && GET_MODE (X) != V4SFmode)                                     \
+   ? GENERAL_REGS                                                      \
    : SECONDARY_OUTPUT_RELOAD_CLASS((CLASS),(MODE),(X)))
 
 /* Return the maximum number of consecutive registers
@@ -1345,13 +1362,17 @@ extern const enum reg_class reg_class_from_letter[];
 
 /* If defined, gives a class of registers that cannot be used as the
    operand of a SUBREG that changes the mode of the object illegally.  */
+/* ??? We need to renumber the internal numbers for the frnn registers
+   when in little endian in order to allow mode size changes.  */
 
-#define CLASS_CANNOT_CHANGE_MODE        DF_REGS
+#define CLASS_CANNOT_CHANGE_MODE (TARGET_LITTLE_ENDIAN ? DF_REGS : DF_HI_REGS)
 
 /* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE.  */
 
 #define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) \
-  (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO))
+  (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
+   && ((TARGET_LITTLE_ENDIAN  && GET_MODE_SIZE (TO) < 8) \
+       || GET_MODE_SIZE (FROM) < 8))
 \f
 /* Stack layout; function entry, exit and calling.  */
 
@@ -2192,7 +2213,8 @@ while (0)
 
 #define LEGITIMATE_CONSTANT_P(X) \
   (TARGET_SHMEDIA                                                      \
-   ? (GET_MODE (X) != DFmode                                           \
+   ? ((GET_MODE (X) != DFmode                                          \
+       && GET_MODE_CLASS (GET_MODE (X)) != MODE_VECTOR_FLOAT)          \
       || (X) == CONST0_RTX (GET_MODE (X))                              \
       || ! TARGET_SHMEDIA_FPU                                          \
       || TARGET_SHMEDIA64)                                             \
@@ -2316,10 +2338,7 @@ while (0)
 
 /* A zero in any shape or form.  */
 #define EXTRA_CONSTRAINT_U(OP) \
-  ((OP) == const0_rtx \
-   || (GET_CODE (OP) == SUBREG && VECTOR_MODE_SUPPORTED_P(GET_MODE (OP)) \
-       && SUBREG_REG (OP) == const0_rtx && SUBREG_BYTE (OP) == 0) \
-   || GET_CODE (OP) == CONST_VECTOR && zero_vec_operand ((OP), VOIDmode))
+  ((OP) == CONST0_RTX (GET_MODE (OP)))
 
 /* Any vector constant we can handle.  */
 #define EXTRA_CONSTRAINT_W(OP) \
@@ -2642,7 +2661,9 @@ while (0)
    will either zero-extend or sign-extend.  The value of this macro should
    be the code that says which one of the two operations is implicitly
    done, NIL if none.  */
-#define LOAD_EXTEND_OP(MODE) SIGN_EXTEND
+/* FP registers can load SImode values, but don't implicitly sign-extend
+   them to DImode.  */
+#define LOAD_EXTEND_OP(MODE) ((MODE) != SImode ? SIGN_EXTEND : NIL)
 
 /* Define if loading short immediate values into registers sign extends.  */
 #define SHORT_IMMEDIATES_SIGN_EXTEND
@@ -2821,12 +2842,13 @@ while (0)
    register information here is not used for SFmode.  */
 #define REGISTER_MOVE_COST(MODE, SRCCLASS, DSTCLASS) \
  (((((DSTCLASS) == T_REGS) || ((DSTCLASS) == PR_REGS)) ? 10            \
-   : ((((DSTCLASS) == FP0_REGS || (DSTCLASS) == FP_REGS || (DSTCLASS) == DF_REGS) \
+   : ((((DSTCLASS) == FP0_REGS || (DSTCLASS) == FP_REGS                        \
+       || (DSTCLASS) == DF_REGS || (DSTCLASS) == DF_HI_REGS)           \
        && ((SRCCLASS) == GENERAL_REGS || (SRCCLASS) == R0_REGS))       \
       || (((DSTCLASS) == GENERAL_REGS || (DSTCLASS) == R0_REGS)                \
          && ((SRCCLASS) == FP0_REGS || (SRCCLASS) == FP_REGS           \
-             || (SRCCLASS) == DF_REGS)))                               \
-   ? (TARGET_SHMEDIA ? 2                                               \
+             || (SRCCLASS) == DF_REGS || (SRCCLASS) == DF_HI_REGS)))   \
+   ? (TARGET_SHMEDIA ? 4                                               \
       : TARGET_FMOVD ? 8 : 12)                                         \
    : (((DSTCLASS) == FPUL_REGS                                         \
        && ((SRCCLASS) == GENERAL_REGS || (SRCCLASS) == R0_REGS))       \
@@ -3231,7 +3253,7 @@ extern int rtx_equal_function_value_matters;
   {"arith_reg_dest", {SUBREG, REG}},                                   \
   {"arith_reg_operand", {SUBREG, REG}},                                        \
   {"arith_reg_or_0_operand", {SUBREG, REG, CONST_INT, CONST_VECTOR}},  \
-  {"binary_float_operator", {PLUS, MULT}},                             \
+  {"binary_float_operator", {PLUS, MINUS, MULT, DIV}},                 \
   {"commutative_float_operator", {PLUS, MULT}},                                \
   {"equality_comparison_operator", {EQ,NE}},                           \
   {"extend_reg_operand", {SUBREG, REG, TRUNCATE}},                     \
@@ -3256,7 +3278,7 @@ extern int rtx_equal_function_value_matters;
   {"sh_1el_vec", {CONST_VECTOR, PARALLEL}},                            \
   {"sh_rep_vec", {CONST_VECTOR, PARALLEL}},                            \
   {"symbol_ref_operand", {SYMBOL_REF}},                                        \
-  {"zero_vec_operand", {CONST_VECTOR}},
+  {"unary_float_operator", {ABS, NEG, SQRT}},                          \
 
 /* Define this macro if it is advisable to hold scalars in registers
    in a wider mode than that declared by the program.  In such cases, 
index 82c1fdc93758abb8ed26d753f46e3a041081b94e..c3ac6e1b41484f1f20413492026e4ec88b2ab045 100644 (file)
    (set (match_dup 6) (float:DF (match_dup 4)))
    (set (match_dup 7) (div:DF (match_dup 5) (match_dup 6)))
    (set (match_dup 8) (fix:DI (match_dup 7)))
-   (set (subreg:DI (match_operand:SI 0 "register_operand" "=r") 0)
-       (sign_extend:DI (match_dup 9)))]
+   (set (match_operand:SI 0 "register_operand" "")
+       (truncate:SI (match_dup 8)))]
   "TARGET_SHMEDIA_FPU"
   "
 {
   operands[6] = gen_reg_rtx (DFmode);
   operands[7] = gen_reg_rtx (DFmode);
   operands[8] = gen_reg_rtx (DImode);
-  operands[9] = gen_lowpart_common (SImode, operands[8]);
 }")
 
 (define_insn "udivsi3_i4"
    patterns, but unary operators are ignored when matching constraints,
    so we need separate patterns.  */
 (define_insn "truncdisi2"
-  [(set (match_operand:SI 0 "register_operand" "=r,m,m,f,r,f")
+  [(set (match_operand:SI 0 "general_movdst_operand" "=r,m,m,f,r,f")
        (truncate:SI (match_operand:DI 1 "register_operand" "r,r,f,r,f,f")))]
   "TARGET_SHMEDIA"
   "@
 
 
 (define_insn "truncdihi2"
-  [(set (match_operand:HI 0 "register_operand" "=?r,m")
+  [(set (match_operand:HI 0 "general_movdst_operand" "=?r,m")
        (truncate:HI (match_operand:DI 1 "register_operand" "r,r")))]
   "TARGET_SHMEDIA"
   "@
   [(set_attr "type"   "arith_media,store_media")
    (set_attr "length" "8,4")])
 
+; N.B. we want sign-extension here because
+; - we need to be consistent with LOAD_EXTEND_OP and movqi
+; - only sign extension allows us to do signed compares transparently.
+;  unsigned compares don't care about the kind of extension as long as
+;   it's consistent.
 (define_insn "truncdiqi2"
   [(set (match_operand:QI 0 "general_movdst_operand" "=r,m")
        (truncate:QI (match_operand:DI 1 "register_operand" "r,r")))]
   "TARGET_SHMEDIA"
   "@
-       andi    %1, 255, %0
+       ori     %1, -256, %0
        st%M0.b %m0, %1"
   [(set_attr "type"   "arith_media,store")])
 
 
 (define_insn "*movsi_media"
   [(set (match_operand:SI 0 "general_movdst_operand" "=r,r,r,r,m,f,m,f,r,f,*b,r,b")
-       (match_operand:SI 1 "general_movsrc_operand" "r,JS,ns,m,r,m,f,r,f,f,r,*b,T"))]
+       (match_operand:SI 1 "general_movsrc_operand" "r,JS,ns,m,r,m,f,rU,f,f,r,*b,T"))]
   "TARGET_SHMEDIA_FPU
    && (register_operand (operands[0], SImode)
        || register_operand (operands[1], SImode))"
        st%M0.l %m0, %1
        fld%M1.s        %m1, %0
        fst%M0.s        %m0, %1
-       fmov.ls %1, %0
+       fmov.ls %N1, %0
        fmov.sl %1, %0
        fmov.s  %1, %0
        ptabs   %1, %0
 
 (define_insn "*movdi_media"
   [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,rl,m,f,m,f,r,f,*b,r,b")
-       (match_operand:DI 1 "general_movsrc_operand" "r,JS,iF,m,rl,m,f,r,f,f,r,*b,T"))]
+       (match_operand:DI 1 "general_movsrc_operand" "r,JS,iF,m,rl,m,f,rU,f,f,r,*b,T"))]
   "TARGET_SHMEDIA_FPU
    && (register_operand (operands[0], DImode)
        || register_operand (operands[1], DImode))"
        st%M0.q %m0, %1
        fld%M1.d        %m1, %0
        fst%M0.d        %m0, %1
-       fmov.qd %1, %0
+       fmov.qd %N1, %0
        fmov.dq %1, %0
        fmov.d  %1, %0
        ptabs   %1, %0
 
 (define_insn "movdf_media"
   [(set (match_operand:DF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
-       (match_operand:DF 1 "general_movsrc_operand" "f,r,f,r,F,m,f,m,r"))]
+       (match_operand:DF 1 "general_movsrc_operand" "f,rU,f,r,F,m,f,m,r"))]
   "TARGET_SHMEDIA_FPU
    && (register_operand (operands[0], DFmode)
        || register_operand (operands[1], DFmode))"
   "@
        fmov.d  %1, %0
-       fmov.qd %1, %0
+       fmov.qd %N1, %0
        fmov.dq %1, %0
        add     %1, r63, %0
        #
     }
 }")
 
-(define_insn "movv2sf_i"
-  [(set (match_operand:V2SF 0 "nonimmediate_operand" "=f,f,m")
-       (match_operand:V2SF 1 "nonimmediate_operand" "f,m,f"))]
-  "TARGET_SHMEDIA_FPU
-   && (fp_arith_reg_operand (operands[0], V2SFmode)
-       || fp_arith_reg_operand (operands[1], V2SFmode))"
-  "@
-       #
-       fld%M1.p        %m1, %0
-       fst%M0.p        %m0, %1"
-  [(set_attr "type" "*,fload_media,fstore_media")])
-
-(define_split
-  [(set (match_operand:V2SF 0 "nonimmediate_operand" "=f")
-       (match_operand:V2SF 1 "nonimmediate_operand" "f"))]
-  "TARGET_SHMEDIA_FPU && reload_completed
-   && fp_arith_reg_operand (operands[0], V2SFmode)
-   && fp_arith_reg_operand (operands[1], V2SFmode)"
-  [(set (subreg:DF (match_dup 0) 0) (subreg:DF (match_dup 1) 0))])
+;;This is incompatible with the way gcc uses subregs.
+;;(define_insn "movv2sf_i"
+;;  [(set (match_operand:V2SF 0 "nonimmediate_operand" "=f,f,m")
+;;     (match_operand:V2SF 1 "nonimmediate_operand" "f,m,f"))]
+;;  "TARGET_SHMEDIA_FPU
+;;   && (fp_arith_reg_operand (operands[0], V2SFmode)
+;;       || fp_arith_reg_operand (operands[1], V2SFmode))"
+;;  "@
+;;     #
+;;     fld%M1.p        %m1, %0
+;;     fst%M0.p        %m0, %1"
+;;  [(set_attr "type" "*,fload_media,fstore_media")])
+
+(define_insn_and_split "movv2sf_i"
+  [(set (match_operand:V2SF 0 "general_movdst_operand" "=f,rf,r,m,mf")
+       (match_operand:V2SF 1 "general_operand" "fm,rfm?,F?,f,rfU?"))]
+  "TARGET_SHMEDIA_FPU"
+  "#"
+  "TARGET_SHMEDIA_FPU && reload_completed"
+  [(set (match_dup 0) (match_dup 1))]
+  "
+{
+  operands[0] = simplify_gen_subreg (DFmode, operands[0], V2SFmode, 0);
+  operands[1] = simplify_gen_subreg (DFmode, operands[1], V2SFmode, 0);
+}")
 
 (define_expand "movv2sf"
-  [(set (match_operand:V2SF 0 "nonimmediate_operand" "=f,f,m")
-       (match_operand:V2SF 1 "nonimmediate_operand" "f,m,f"))]
+  [(set (match_operand:V2SF 0 "general_movdst_operand" "")
+       (match_operand:V2SF 1 "nonimmediate_operand" ""))]
   "TARGET_SHMEDIA_FPU"
   "
 {
     DONE;
 }")
 
+(define_expand "addv2sf3"
+  [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
+   (match_operand:V2SF 1 "fp_arith_reg_operand" "")
+   (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
+  "TARGET_SHMEDIA_FPU"
+  "
+{
+  sh_expand_binop_v2sf (PLUS, operands[0], operands[1], operands[2]);
+  DONE;
+}")
+
+(define_expand "subv2sf3"
+  [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
+   (match_operand:V2SF 1 "fp_arith_reg_operand" "")
+   (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
+  "TARGET_SHMEDIA_FPU"
+  "
+{
+  sh_expand_binop_v2sf (MINUS, operands[0], operands[1], operands[2]);
+  DONE;
+}")
+
+(define_expand "mulv2sf3"
+  [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
+   (match_operand:V2SF 1 "fp_arith_reg_operand" "")
+   (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
+  "TARGET_SHMEDIA_FPU"
+  "
+{
+  sh_expand_binop_v2sf (MULT, operands[0], operands[1], operands[2]);
+  DONE;
+}")
+
+(define_expand "divv2sf3"
+  [(match_operand:V2SF 0 "fp_arith_reg_operand" "")
+   (match_operand:V2SF 1 "fp_arith_reg_operand" "")
+   (match_operand:V2SF 2 "fp_arith_reg_operand" "")]
+  "TARGET_SHMEDIA_FPU"
+  "
+{
+  sh_expand_binop_v2sf (DIV, operands[0], operands[1], operands[2]);
+  DONE;
+}")
+
 (define_insn_and_split "*movv4sf_i"
   [(set (match_operand:V4SF 0 "nonimmediate_operand" "=f,f,m")
-       (match_operand:V4SF 1 "nonimmediate_operand" "f,m,f"))]
+       (match_operand:V4SF 1 "general_operand" "fU,m,f"))]
   "TARGET_SHMEDIA_FPU"
   "#"
   "&& reload_completed"
                         plus_constant (XEXP (operands[0], 0),
                                        i * GET_MODE_SIZE (V2SFmode)));
       else
-       {
-         x = gen_rtx_SUBREG (V2SFmode, operands[0], i * 2);
-         alter_subreg (&x);
-       }
+       x = simplify_gen_subreg (V2SFmode, operands[0], V4SFmode, i * 8);
 
       if (GET_CODE (operands[1]) == MEM)
        y = gen_rtx_MEM (V2SFmode,
                         plus_constant (XEXP (operands[1], 0),
                                        i * GET_MODE_SIZE (V2SFmode)));
       else
-       {
-         y = gen_rtx_SUBREG (V2SFmode, operands[1], i * 2);
-         alter_subreg (&y);
-       }
+       y = simplify_gen_subreg (V2SFmode, operands[1], V4SFmode, i * 8);
 
       emit_insn (gen_movv2sf_i (x, y));
     }
   [(set_attr "length" "8")])
 
 (define_expand "movv4sf"
-  [(set (match_operand:V4SF 0 "nonimmediate_operand" "=f,f,m")
-       (match_operand:V4SF 1 "nonimmediate_operand" "f,m,f"))]
+  [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
+       (match_operand:V4SF 1 "general_operand" ""))]
   "TARGET_SHMEDIA_FPU"
   "
 {
 
 (define_insn "movsf_media"
   [(set (match_operand:SF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
-       (match_operand:SF 1 "general_movsrc_operand" "f,r,f,r,F,m,f,m,r"))]
+       (match_operand:SF 1 "general_movsrc_operand" "f,rU,f,r,F,m,f,m,r"))]
   "TARGET_SHMEDIA_FPU
    && (register_operand (operands[0], SFmode)
        || register_operand (operands[1], SFmode))"
   "@
        fmov.s  %1, %0
-       fmov.ls %1, %0
+       fmov.ls %N1, %0
        fmov.sl %1, %0
        add.l   %1, r63, %0
        #
 (define_split
   [(set (match_operand:SF 0 "arith_reg_operand" "")
        (match_operand:SF 1 "immediate_operand" ""))]
-  "TARGET_SHMEDIA && reload_completed"
+  "TARGET_SHMEDIA && reload_completed
+   && ! FP_REGISTER_P (true_regnum (operands[0]))"
   [(set (match_dup 3) (match_dup 2))]
   "
 {
   "fadd.s      %1, %2, %0"
   [(set_attr "type" "fparith_media")])
 
+(define_insn_and_split "unary_sf_op"
+  [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
+       (vec_select:V2SF
+        (vec_concat:V2SF
+         (vec_select:SF
+          (match_dup 0)
+          (parallel [(not:BI (match_operand 3 "const_int_operand" "n"))]))
+         (match_operator:SF 2 "unary_float_operator"
+           [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
+                           (parallel [(match_operand 4
+                                       "const_int_operand" "n")]))]))
+        (parallel [(not:BI (match_dup 3)) (match_dup 3)])))]
+  "TARGET_SHMEDIA_FPU"
+  "#"
+  "TARGET_SHMEDIA_FPU && reload_completed"
+  [(set (match_dup 5) (match_dup 6))]
+  "
+{
+  int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
+  rtx op1 = gen_rtx_REG (SFmode,
+                        (true_regnum (operands[1])
+                         + (INTVAL (operands[4]) ^ endian)));
+
+  operands[7] = gen_rtx_REG (SFmode,
+                            (true_regnum (operands[0])
+                             + (INTVAL (operands[3]) ^ endian)));
+  operands[6] = gen_rtx (GET_CODE (operands[2]), SFmode, op1);
+}"
+  [(set_attr "type" "fparith_media")])
+
+(define_insn_and_split "binary_sf_op"
+  [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
+       (vec_select:V2SF
+        (vec_concat:V2SF
+         (vec_select:SF
+          (match_dup 0)
+          (parallel [(not:BI (match_operand 4 "const_int_operand" "n"))]))
+         (match_operator:SF 3 "binary_float_operator"
+           [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
+                           (parallel [(match_operand 5
+                                       "const_int_operand" "n")]))
+            (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
+                           (parallel [(match_operand 6
+                                       "const_int_operand" "n")]))]))
+        (parallel [(not:BI (match_dup 4)) (match_dup 4)])))]
+  "TARGET_SHMEDIA_FPU"
+  "#"
+  "TARGET_SHMEDIA_FPU && reload_completed"
+  [(set (match_dup 7) (match_dup 8))]
+  "
+{
+  int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
+  rtx op1 = gen_rtx_REG (SFmode,
+                        (true_regnum (operands[1])
+                         + (INTVAL (operands[5]) ^ endian)));
+  rtx op2 = gen_rtx_REG (SFmode,
+                        (true_regnum (operands[2])
+                         + (INTVAL (operands[6]) ^ endian)));
+
+  operands[7] = gen_rtx_REG (SFmode,
+                            (true_regnum (operands[0])
+                             + (INTVAL (operands[4]) ^ endian)));
+  operands[8] = gen_rtx (GET_CODE (operands[3]), SFmode, op1, op2);
+}"
+  [(set_attr "type" "fparith_media")])
+
 (define_insn "addsf3_i"
   [(set (match_operand:SF 0 "arith_reg_operand" "=f")
        (plus:SF (match_operand:SF 1 "arith_reg_operand" "%0")
   "TARGET_SHMEDIA && reload_completed
    && GET_MODE (operands[0]) == GET_MODE (operands[1])
    && VECTOR_MODE_SUPPORTED_P (GET_MODE (operands[0]))
-   && ! zero_vec_operand (operands[1], VOIDmode)"
+   && operands[1] != CONST0_RTX (GET_MODE (operands[1]))"
   [(set (match_dup 0) (match_dup 1))]
   "
 {
 ; mextrN can be modelled with vec_select / vec_concat, but the selection
 ; vector then varies depending on endianness.
 (define_expand "mextr1"
-  [(match_operand:V8QI 0 "arith_reg_dest" "")
-   (match_operand:V8QI 1 "arith_reg_or_0_operand" "rU")
-   (match_operand:V8QI 2 "arith_reg_or_0_operand" "rU")]
+  [(match_operand:DI 0 "arith_reg_dest" "")
+   (match_operand:DI 1 "arith_reg_or_0_operand" "rU")
+   (match_operand:DI 2 "arith_reg_or_0_operand" "rU")]
   "TARGET_SHMEDIA"
   "
 {
-  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[3],
+  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
                           GEN_INT (1 * 8), GEN_INT (7 * 8)));
   DONE;
 }")
 
 (define_expand "mextr2"
-  [(match_operand:V8QI 0 "arith_reg_dest" "")
-   (match_operand:V8QI 1 "arith_reg_or_0_operand" "rU")
-   (match_operand:V8QI 2 "arith_reg_or_0_operand" "rU")]
+  [(match_operand:DI 0 "arith_reg_dest" "")
+   (match_operand:DI 1 "arith_reg_or_0_operand" "rU")
+   (match_operand:DI 2 "arith_reg_or_0_operand" "rU")]
   "TARGET_SHMEDIA"
   "
 {
-  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[3],
+  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
                           GEN_INT (2 * 8), GEN_INT (6 * 8)));
   DONE;
 }")
 
 (define_expand "mextr3"
-  [(match_operand:V8QI 0 "arith_reg_dest" "")
-   (match_operand:V8QI 1 "arith_reg_or_0_operand" "rU")
-   (match_operand:V8QI 2 "arith_reg_or_0_operand" "rU")]
+  [(match_operand:DI 0 "arith_reg_dest" "")
+   (match_operand:DI 1 "arith_reg_or_0_operand" "rU")
+   (match_operand:DI 2 "arith_reg_or_0_operand" "rU")]
   "TARGET_SHMEDIA"
   "
 {
-  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[3],
+  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
                           GEN_INT (3 * 8), GEN_INT (5 * 8)));
   DONE;
 }")
 
 (define_expand "mextr4"
-  [(match_operand:V8QI 0 "arith_reg_dest" "")
-   (match_operand:V8QI 1 "arith_reg_or_0_operand" "rU")
-   (match_operand:V8QI 2 "arith_reg_or_0_operand" "rU")]
+  [(match_operand:DI 0 "arith_reg_dest" "")
+   (match_operand:DI 1 "arith_reg_or_0_operand" "rU")
+   (match_operand:DI 2 "arith_reg_or_0_operand" "rU")]
   "TARGET_SHMEDIA"
   "
 {
-  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[3],
+  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
                           GEN_INT (4 * 8), GEN_INT (4 * 8)));
   DONE;
 }")
 
 (define_expand "mextr5"
-  [(match_operand:V8QI 0 "arith_reg_dest" "")
-   (match_operand:V8QI 1 "arith_reg_or_0_operand" "rU")
-   (match_operand:V8QI 2 "arith_reg_or_0_operand" "rU")]
+  [(match_operand:DI 0 "arith_reg_dest" "")
+   (match_operand:DI 1 "arith_reg_or_0_operand" "rU")
+   (match_operand:DI 2 "arith_reg_or_0_operand" "rU")]
   "TARGET_SHMEDIA"
   "
 {
-  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[3],
+  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
                           GEN_INT (5 * 8), GEN_INT (3 * 8)));
   DONE;
 }")
 
 (define_expand "mextr6"
-  [(match_operand:V8QI 0 "arith_reg_dest" "")
-   (match_operand:V8QI 1 "arith_reg_or_0_operand" "rU")
-   (match_operand:V8QI 2 "arith_reg_or_0_operand" "rU")]
+  [(match_operand:DI 0 "arith_reg_dest" "")
+   (match_operand:DI 1 "arith_reg_or_0_operand" "rU")
+   (match_operand:DI 2 "arith_reg_or_0_operand" "rU")]
   "TARGET_SHMEDIA"
   "
 {
-  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[3],
+  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
                           GEN_INT (6 * 8), GEN_INT (2 * 8)));
   DONE;
 }")
 
 (define_expand "mextr7"
-  [(match_operand:V8QI 0 "arith_reg_dest" "")
-   (match_operand:V8QI 1 "arith_reg_or_0_operand" "rU")
-   (match_operand:V8QI 2 "arith_reg_or_0_operand" "rU")]
+  [(match_operand:DI 0 "arith_reg_dest" "")
+   (match_operand:DI 1 "arith_reg_or_0_operand" "rU")
+   (match_operand:DI 2 "arith_reg_or_0_operand" "rU")]
   "TARGET_SHMEDIA"
   "
 {
-  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[3],
+  emit_insn (gen_mextr_rl (operands[0], operands[1], operands[2],
                           GEN_INT (7 * 8), GEN_INT (1 * 8)));
   DONE;
 }")
         (mult:V4SI
          (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
          (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
-        (const_vector [(const_int 2) (const_int 3)])))]
+        (parallel [(const_int 2) (const_int 3)])))]
   "TARGET_SHMEDIA"
   "* return (TARGET_LITTLE_ENDIAN
             ? \"mmulhi.wl      %1, %2, %0\"
         (mult:V4SI
          (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r"))
          (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r")))
-        (const_vector [(const_int 0) (const_int 1)])))]
+        (parallel [(const_int 0) (const_int 1)])))]
   "TARGET_SHMEDIA"
   "* return (TARGET_LITTLE_ENDIAN
             ? \"mmullo.wl      %1, %2, %0\"
            (mult:V4DI
             (sign_extend:V4DI (match_operand:V4HI 2 "arith_reg_operand" "r"))
             (sign_extend:V4DI (match_operand:V4HI 3 "arith_reg_operand" "r")))
-           (const_vector [(const_int 0)]))
+           (parallel [(const_int 0)]))
           (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
                                     (sign_extend:V4DI (match_dup 3)))
-                         (const_vector [(const_int 1)])))
+                         (parallel [(const_int 1)])))
          (plus:DI
           (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
                                     (sign_extend:V4DI (match_dup 3)))
-                         (const_vector [(const_int 2)]))
+                         (parallel [(const_int 2)]))
           (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2))
                                     (sign_extend:V4DI (match_dup 3)))
-                         (const_vector [(const_int 3)]))))))]
+                         (parallel [(const_int 3)]))))))]
   "TARGET_SHMEDIA"
   "mmulsum.wq  %2, %3, %0"
   [(set_attr "type" "mac_media")])
                       (match_operand:V8QI 2 "arith_reg_or_0_operand" "r"))
                      (zero_extend:V8DI
                       (match_operand:V8QI 3 "arith_reg_or_0_operand" "r")))
-                    (const_vector [(const_int 0)]))))
+                    (parallel [(const_int 0)]))))
           (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
                                              (zero_extend:V8DI (match_dup 3)))
-                                 (const_vector [(const_int 1)]))))
+                                 (parallel [(const_int 1)]))))
          (plus:DI
           (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
                                              (zero_extend:V8DI (match_dup 3)))
-                                 (const_vector [(const_int 2)])))
+                                 (parallel [(const_int 2)])))
           (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
                                              (zero_extend:V8DI (match_dup 3)))
-                                 (const_vector [(const_int 3)])))))
+                                 (parallel [(const_int 3)])))))
         (plus:DI
          (plus:DI
           (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
                                              (zero_extend:V8DI (match_dup 3)))
-                                 (const_vector [(const_int 4)])))
+                                 (parallel [(const_int 4)])))
           (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
                                              (zero_extend:V8DI (match_dup 3)))
-                                 (const_vector [(const_int 5)]))))
+                                 (parallel [(const_int 5)]))))
          (plus:DI
           (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
                                              (zero_extend:V8DI (match_dup 3)))
-                                 (const_vector [(const_int 6)])))
+                                 (parallel [(const_int 6)])))
           (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2))
                                              (zero_extend:V8DI (match_dup 3)))
-                                 (const_vector [(const_int 7)])))))))]
+                                 (parallel [(const_int 7)])))))))]
   "TARGET_SHMEDIA"
   "msad.ubq    %N2, %N3, %0"
   [(set_attr "type" "mac_media")])
     (vec_select:V8QI
      (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rU")
                       (match_operand:V8QI 2 "arith_reg_or_0_operand" "rU"))
-     (const_vector [(const_int 4) (const_int 12) (const_int 5) (const_int 13)
-                   (const_int 6) (const_int 14) (const_int 7) (const_int 15)])))]
+     (parallel [(const_int 4) (const_int 12) (const_int 5) (const_int 13)
+               (const_int 6) (const_int 14) (const_int 7) (const_int 15)])))]
   "TARGET_SHMEDIA"
   "* return (TARGET_LITTLE_ENDIAN
             ? \"mshfhi.b       %N1, %N2, %0\"
     (vec_select:V8QI
      (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rU")
                       (match_operand:V8QI 2 "arith_reg_or_0_operand" "rU"))
-     (const_vector [(const_int 0) (const_int 8) (const_int 1) (const_int 9)
-                   (const_int 2) (const_int 10) (const_int 3) (const_int 11)])))]
+     (parallel [(const_int 0) (const_int 8) (const_int 1) (const_int 9)
+               (const_int 2) (const_int 10) (const_int 3) (const_int 11)])))]
   "TARGET_SHMEDIA"
   "* return (TARGET_LITTLE_ENDIAN
             ? \"mshflo.b       %N1, %N2, %0\"
        (vec_select:V2SI
         (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rU")
                          (match_operand:V2SI 2 "arith_reg_or_0_operand" "rU"))
-        (const_vector [(const_int 1) (const_int 3)])))]
+        (parallel [(const_int 1) (const_int 3)])))]
   "TARGET_SHMEDIA"
   "* return (TARGET_LITTLE_ENDIAN
             ? \"mshfhi.l       %N1, %N2, %0\"
        (vec_select:V2SI
         (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rU")
                          (match_operand:V2SI 2 "arith_reg_or_0_operand" "rU"))
-        (const_vector [(const_int 0) (const_int 2)])))]
+        (parallel [(const_int 0) (const_int 2)])))]
   "TARGET_SHMEDIA"
   "* return (TARGET_LITTLE_ENDIAN
             ? \"mshflo.l       %N1, %N2, %0\"
        (vec_select:V4HI
         (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rU")
                          (match_operand:V4HI 2 "arith_reg_or_0_operand" "rU"))
-        (const_vector [(const_int 2) (const_int 6) (const_int 3) (const_int 7)])))]
+        (parallel [(const_int 2) (const_int 6) (const_int 3) (const_int 7)])))]
   "TARGET_SHMEDIA"
   "* return (TARGET_LITTLE_ENDIAN
             ? \"mshfhi.w       %N1, %N2, %0\"
        (vec_select:V4HI
         (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rU")
                          (match_operand:V4HI 2 "arith_reg_or_0_operand" "rU"))
-        (const_vector [(const_int 0) (const_int 4) (const_int 1) (const_int 5)])))]
+        (parallel [(const_int 0) (const_int 4) (const_int 1) (const_int 5)])))]
   "TARGET_SHMEDIA"
   "* return (TARGET_LITTLE_ENDIAN
             ? \"mshflo.w       %N1, %N2, %0\"
             : \"mshfhi.w       %N1, %N2, %0\");"
   [(set_attr "type" "arith_media")])
 
+(define_insn "mshflo_w_x"
+  [(set (match_operand:V4HI 0 "arith_reg_dest" "=r")
+       (vec_select:V4HI
+        (vec_concat:V4HI (match_operand:V2HI 1 "extend_reg_or_0_operand" "rU")
+                         (match_operand:V2HI 2 "extend_reg_or_0_operand" "rU"))
+        (parallel [(const_int 0) (const_int 2) (const_int 1) (const_int 3)])))]
+  "TARGET_SHMEDIA"
+  "mshflo.w    %N1, %N2, %0"
+  [(set_attr "type" "arith_media")])
+
 /* These are useful to expand ANDs and as combiner patterns.  */
-(define_insn "mshfhi_l_di"
-  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
-       (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rU")
+(define_insn_and_split "mshfhi_l_di"
+  [(set (match_operand:DI 0 "arith_reg_dest" "=r,f")
+       (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rU,f")
                              (const_int 32))
-               (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rU")
+               (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rU,?f")
                        (const_int -4294967296))))]
   "TARGET_SHMEDIA"
-  "mshfhi.l    %N1, %N2, %0"
+  "@
+       mshfhi.l        %N1, %N2, %0
+       #"
+  "TARGET_SHMEDIA && reload_completed
+   && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
+  [(set (match_dup 3) (match_dup 4))
+   (set (match_dup 5) (match_dup 6))]
+  "
+{
+  operands[3] = gen_lowpart (SImode, operands[0]);
+  operands[4] = gen_highpart (SImode, operands[1]);
+  operands[5] = gen_highpart (SImode, operands[0]);
+  operands[6] = gen_highpart (SImode, operands[2]);
+}"
   [(set_attr "type" "arith_media")])
 
 (define_insn "*mshfhi_l_di_rev"
 
 (define_insn "*mshflo_l_di_x"
   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
-       (ior:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_or_0_operand" "rU"))
+       (ior:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_or_0_operand"
+                                "rU"))
                (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rU")
                            (const_int 32))))]
                                
   "mshflo.l    %N1, %N2, %0"
   [(set_attr "type" "arith_media")])
 
+(define_insn_and_split "concat_v2sf"
+  [(set (match_operand:V2SF 0 "register_operand" "=r,f,f?")
+;;     (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rU,0,f")
+       (vec_concat:V2SF (match_operand:SF 1 "register_operand" "rU,f,f")
+                        (match_operand:SF 2 "register_operand" "rU,f,f")))]
+                               
+  "TARGET_SHMEDIA"
+  "@
+       mshflo.l        %N1, %N2, %0
+       #
+       #"
+  "TARGET_SHMEDIA && reload_completed
+   && ! GENERAL_REGISTER_P (true_regnum (operands[0]))"
+  [(set (match_dup 3) (match_dup 1))
+   (set (match_dup 4) (match_dup 2))]
+  "
+{
+  operands[3] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 0);
+  operands[4] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 4);
+}"
+  [(set_attr "type" "arith_media")])
+
 (define_insn "*mshflo_l_di_x_rev"
   [(set (match_operand:DI 0 "arith_reg_dest" "=r")
        (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rU")
                                                    "fp_arith_reg_operand" "f")
                                                   (match_operand:V4SF 2
                                                    "fp_arith_reg_operand" "f"))
-                                        (const_vector [(const_int 0)]))
+                                        (parallel [(const_int 0)]))
                          (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
-                                        (const_vector [(const_int 1)])))
+                                        (parallel [(const_int 1)])))
                 (plus:SF (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
-                                        (const_vector [(const_int 2)]))
+                                        (parallel [(const_int 2)]))
                          (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2))
-                                        (const_vector [(const_int 3)])))))]
+                                        (parallel [(const_int 3)])))))]
   "TARGET_SHMEDIA"
   "fipr        %1, %2, %0"
   [(set_attr "type" "fparith_media")])
         (plus:V4SF
          (mult:V4SF
           (vec_select:V4SF (match_operand:V16SF 1 "fp_arith_reg_operand" "f")
-                           (const_vector [(const_int 0) (const_int 5)
-                                          (const_int 10) (const_int 15)]))
+                           (parallel [(const_int 0) (const_int 5)
+                                      (const_int 10) (const_int 15)]))
           (match_operand:V4SF 2 "fp_arith_reg_operand" "f"))
          (mult:V4SF
           (vec_select:V4SF (match_dup 1)
-                           (const_vector [(const_int 4) (const_int 9)
-                                          (const_int 14) (const_int 3)]))
+                           (parallel [(const_int 4) (const_int 9)
+                                      (const_int 14) (const_int 3)]))
           (vec_select:V4SF (match_dup 2)
-                           (const_vector [(const_int 1) (const_int 2)
-                                          (const_int 3) (const_int 0)]))))
+                           (parallel [(const_int 1) (const_int 2)
+                                     (const_int 3) (const_int 0)]))))
         (plus:V4SF
          (mult:V4SF
           (vec_select:V4SF (match_dup 1)
-                           (const_vector [(const_int 8) (const_int 13)
-                                          (const_int 2) (const_int 7)]))
+                           (parallel [(const_int 8) (const_int 13)
+                                      (const_int 2) (const_int 7)]))
           (vec_select:V4SF (match_dup 2)
-                           (const_vector [(const_int 2) (const_int 3)
-                                          (const_int 0) (const_int 1)])))
+                           (parallel [(const_int 2) (const_int 3)
+                                      (const_int 0) (const_int 1)])))
          (mult:V4SF
           (vec_select:V4SF (match_dup 1)
-                           (const_vector [(const_int 12) (const_int 1)
-                                          (const_int 6) (const_int 11)]))
+                           (parallel [(const_int 12) (const_int 1)
+                                      (const_int 6) (const_int 11)]))
           (vec_select:V4SF (match_dup 2)
-                           (const_vector [(const_int 3) (const_int 0)
-                                          (const_int 1) (const_int 2)]))))))]
+                           (parallel [(const_int 3) (const_int 0)
+                                      (const_int 1) (const_int 2)]))))))]
   "TARGET_SHMEDIA"
   "ftrv %1, %2, %0"
   [(set_attr "type" "fparith_media")])