arm.c (arm_arch5e): New variable.
authorRichard Earnshaw <rearnsha@arm.com>
Mon, 8 Jan 2001 15:33:06 +0000 (15:33 +0000)
committerRichard Earnshaw <rearnsha@gcc.gnu.org>
Mon, 8 Jan 2001 15:33:06 +0000 (15:33 +0000)
* arm.c (arm_arch5e): New variable.
(all_cores): XScale is a 5TE device.
(arm_override_options): Set arm_arch5e.
(arm_init_builtins): __builtin_prefetch is in arch5e.
* arm.h (arm_arch5e): Declare it.

* arm.h (PREDICATE_CODES): Add arm_hard_register_operand.

* arm.md (define_constants): Add defines for UNSPEC and
UNSPEC_VOLATILE insns.  Update all users.
(define_constants): Add constants for IP_REGNUM, SP_REGNUM, PC_REGNUM.
* arm.c (multi_register_push, note_invalid_constants)
(emit_multi_reg_push, emit_sfm, expand_prologue): Use constants.
* arm.h (SP_REGNUM, IP_REGNUM, PC_REGNUM): Delete defines.
(STACK_POINTER_REGNUM): Define in terms of SP_REGNUM.

From-SVN: r38803

gcc/ChangeLog
gcc/config/arm/arm.c
gcc/config/arm/arm.h
gcc/config/arm/arm.md

index 721b1c7097f0b3c78950110a8d896af60eec0df8..363513ad6ba708196089e52d3a74178152f77621 100644 (file)
@@ -1,3 +1,21 @@
+2001-01-08  Richard Earnshaw  <rearnsha@arm.com>
+
+       * arm.c (arm_arch5e): New variable.
+       (all_cores): XScale is a 5TE device.
+       (arm_override_options): Set arm_arch5e.
+       (arm_init_builtins): __builtin_prefetch is in arch5e.
+       * arm.h (arm_arch5e): Declare it.
+
+       * arm.h (PREDICATE_CODES): Add arm_hard_register_operand.
+
+       * arm.md (define_constants): Add defines for UNSPEC and
+       UNSPEC_VOLATILE insns.  Update all users.
+       (define_constants): Add constants for IP_REGNUM, SP_REGNUM, PC_REGNUM.
+       * arm.c (multi_register_push, note_invalid_constants)
+       (emit_multi_reg_push, emit_sfm, expand_prologue): Use constants.
+       * arm.h (SP_REGNUM, IP_REGNUM, PC_REGNUM): Delete defines.
+       (STACK_POINTER_REGNUM): Define in terms of SP_REGNUM.
+       
 Mon Jan  8 16:14:56 MET 2001  Jan Hubicka  <jh@suse.cz>
 
        * jump.c (jump_optimize_1): Use reversed_comparison_code
index 16479d4fba733566a6da48ee6cc4db8f4e7bfc26..5401773288998a879e0045848d67a49cdb0371d9 100644 (file)
@@ -151,7 +151,7 @@ int    arm_structure_size_boundary = DEFAULT_STRUCTURE_SIZE_BOUNDARY;
 #define FL_THUMB      (1 << 6)        /* Thumb aware */
 #define FL_LDSCHED    (1 << 7)       /* Load scheduling necessary */
 #define FL_STRONG     (1 << 8)       /* StrongARM */
-#define FL_ARCH5E     (1 << 9)        /* El Segundo extenstions to v5 */
+#define FL_ARCH5E     (1 << 9)        /* DSP extenstions to v5 */
 #define FL_XSCALE     (1 << 10)              /* XScale */
 
 /* The bits in this mask specify which instructions we are
@@ -176,6 +176,9 @@ int arm_arch4 = 0;
 /* Nonzero if this chip supports the ARM Architecture 5 extensions.  */
 int arm_arch5 = 0;
 
+/* Nonzero if this chip supports the ARM Architecture 5E extensions.  */
+int arm_arch5e = 0;
+
 /* Nonzero if this chip can benefit from load scheduling.  */
 int arm_ld_sched = 0;
 
@@ -279,7 +282,7 @@ static struct processors all_cores[] =
   {"strongarm",                     FL_MODE26 | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 |            FL_LDSCHED | FL_STRONG },
   {"strongarm110",           FL_MODE26 | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 |            FL_LDSCHED | FL_STRONG },
   {"strongarm1100",          FL_MODE26 | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 |            FL_LDSCHED | FL_STRONG },
-  {"xscale",                             FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_LDSCHED | FL_STRONG | FL_XSCALE | FL_ARCH5 },
+  {"xscale",                             FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_LDSCHED | FL_STRONG | FL_XSCALE | FL_ARCH5 | FL_ARCH5E },
   
   {NULL, 0}
 };
@@ -586,6 +589,7 @@ arm_override_options ()
   arm_fast_multiply = (insn_flags & FL_FAST_MULT) != 0;
   arm_arch4         = (insn_flags & FL_ARCH4) != 0;
   arm_arch5         = (insn_flags & FL_ARCH5) != 0;
+  arm_arch5e        = (insn_flags & FL_ARCH5E) != 0;
   arm_is_xscale     = (insn_flags & FL_XSCALE) != 0;
 
   arm_ld_sched      = (tune_flags & FL_LDSCHED) != 0;
@@ -4054,7 +4058,7 @@ multi_register_push (op, mode)
   if (GET_CODE (op) != PARALLEL
       || (GET_CODE (XVECEXP (op, 0, 0)) != SET)
       || (GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != UNSPEC)
-      || (XINT (SET_SRC (XVECEXP (op, 0, 0)), 1) != 2))
+      || (XINT (SET_SRC (XVECEXP (op, 0, 0)), 1) != UNSPEC_PUSH_MULT))
     return 0;
 
   return 1;
@@ -5888,7 +5892,7 @@ note_invalid_constants (insn, address)
             this shouldn't be needed any more.  */
 #ifndef AOF_ASSEMBLER
          /* XXX Is this still needed?  */
-         else if (GET_CODE (op) == UNSPEC && XINT (op, 1) == 3)
+         else if (GET_CODE (op) == UNSPEC && XINT (op, 1) == UNSPEC_PIC_SYM)
            push_minipool_fix (insn, address, recog_data.operand_loc[opno],
                               recog_data.operand_mode[opno],
                               XVECEXP (op, 0, 0));
@@ -7593,7 +7597,8 @@ emit_multi_reg_push (mask)
      something like this:
 
        (parallel [ 
-           (set (mem:BLK (pre_dec:BLK (reg:SI sp))) (unspec:BLK [(reg:SI r4)] 2))
+           (set (mem:BLK (pre_dec:BLK (reg:SI sp)))
+               (unspec:BLK [(reg:SI r4)] UNSPEC_PUSH_MULT))
            (use (reg:SI 11 fp))
            (use (reg:SI 12 ip))
            (use (reg:SI 14 lr))
@@ -7708,7 +7713,7 @@ emit_sfm (base_reg, count)
                                gen_rtx_PRE_DEC (BLKmode, stack_pointer_rtx)),
                   gen_rtx_UNSPEC (BLKmode,
                                   gen_rtvec (1, reg),
-                                  2));
+                                  UNSPEC_PUSH_MULT));
   tmp
     = gen_rtx_SET (VOIDmode, 
                   gen_rtx_MEM (XFmode,
@@ -7941,7 +7946,8 @@ arm_expand_prologue ()
        {
          rtx unspec = gen_rtx_UNSPEC (SImode,
                                       gen_rtvec (2, stack_pointer_rtx,
-                                                 hard_frame_pointer_rtx), 4);
+                                                 hard_frame_pointer_rtx),
+                                      UNSPEC_PRLG_STK);
 
          insn = emit_insn (gen_rtx_CLOBBER (VOIDmode,
                                      gen_rtx_MEM (BLKmode, unspec)));
@@ -8801,6 +8807,11 @@ arm_init_builtins ()
   if (arm_arch5)
     {
       def_builtin ("__builtin_clz", int_ftype_int, ARM_BUILTIN_CLZ);
+    }
+
+  /* Initialize arm V5E builtins.  */
+  if (arm_arch5e)
+    {
       def_builtin ("__builtin_prefetch", void_ftype_pchar,
                   ARM_BUILTIN_PREFETCH);
     }
index 2701e24ce46edf1450da7cbb1bd9bcf9d57b1789..c1abdb2c31c0e57becbfd0e72e0eb1f2aa71a80a 100644 (file)
@@ -561,6 +561,9 @@ extern int arm_arch4;
 /* Nonzero if this chip supports the ARM Architecture 5 extensions */
 extern int arm_arch5;
 
+/* Nonzero if this chip supports the ARM Architecture 5E extensions */
+extern int arm_arch5e;
+
 /* Nonzero if this chip can benefit from load scheduling.  */
 extern int arm_ld_sched;
 
@@ -931,32 +934,21 @@ extern const char * structure_size_string;
    pointer.  */
 #define ARM_HARD_FRAME_POINTER_REGNUM  11
 #define THUMB_HARD_FRAME_POINTER_REGNUM         7
-#define HARD_FRAME_POINTER_REGNUM       (TARGET_ARM ? ARM_HARD_FRAME_POINTER_REGNUM : THUMB_HARD_FRAME_POINTER_REGNUM)
-#define FP_REGNUM                      HARD_FRAME_POINTER_REGNUM
-
-/* Scratch register - used in all kinds of places, eg trampolines.  */
-#define IP_REGNUM              12
-
-/* Register to use for pushing function arguments.  */
-#define STACK_POINTER_REGNUM   13
-#define SP_REGNUM              STACK_POINTER_REGNUM
 
-/* Register which holds return address from a subroutine call.  */
-#define LR_REGNUM              14
+#define HARD_FRAME_POINTER_REGNUM              \
+  (TARGET_ARM                                  \
+   ? ARM_HARD_FRAME_POINTER_REGNUM             \
+   : THUMB_HARD_FRAME_POINTER_REGNUM)
 
-/* Define this if the program counter is overloaded on a register.  */
-#define PC_REGNUM              15
+#define FP_REGNUM                      HARD_FRAME_POINTER_REGNUM
 
-/* The number of the last ARM (integer) register.  */
-#define LAST_ARM_REGNUM        15
+/* Register to use for pushing function arguments.  */
+#define STACK_POINTER_REGNUM   SP_REGNUM
 
 /* ARM floating pointer registers.  */
 #define FIRST_ARM_FP_REGNUM    16
 #define LAST_ARM_FP_REGNUM     23
 
-/* Internal, so that we don't need to refer to a raw number */
-#define CC_REGNUM              24
-
 /* Base register for access to local variables of the function.  */
 #define FRAME_POINTER_REGNUM   25
 
@@ -2949,6 +2941,7 @@ extern int making_const_table;
 /* Define the codes that are matched by predicates in arm.c */
 #define PREDICATE_CODES                                                        \
   {"s_register_operand", {SUBREG, REG}},                               \
+  {"arm_hard_register_operand", {REG}},                                        \
   {"f_register_operand", {SUBREG, REG}},                               \
   {"arm_add_operand",    {SUBREG, REG, CONST_INT}},                    \
   {"fpu_add_operand",    {SUBREG, REG, CONST_DOUBLE}},                 \
index d391dae6f6b351961536f091c763cb2d4f427e36..139257c4276b86d9b53a76f0adb7dda541555786 100644 (file)
 ;; Unfortunately RISC iX doesn't work well with these so they are disabled.
 ;; (See arm.h)
 \f
+;;---------------------------------------------------------------------------
+;; Constants
+
+;; Register numbers
+(define_constants
+  [(IP_REGNUM      12)         ; Scratch register
+   (SP_REGNUM      13)         ; Stack pointer
+   (LR_REGNUM       14)                ; Return address register
+   (PC_REGNUM      15)         ; Program counter
+   (CC_REGNUM       24)                ; Condition code pseudo register
+   (LAST_ARM_REGNUM 15)
+  ]
+)
+
 ;; UNSPEC Usage:
-;; 0 `sin' operation: operand 0 is the result, operand 1 the parameter,
-;;   the mode is MODE_FLOAT
-;; 1 `cos' operation: operand 0 is the result, operand 1 the parameter,
-;;   the mode is MODE_FLOAT
-;; 2 `push multiple' operation: operand 0 is the first register.  Subsequent
-;;   registers are in parallel (use...) expressions.
-;; 3 A symbol that has been treated properly for pic usage, that is, we
-;;   will add the pic_register value to it before trying to dereference it.
 ;; Note: sin and cos are no-longer used.
-;;
+
+(define_constants
+  [(UNSPEC_SIN       0)        ; `sin' operation (MODE_FLOAT):
+                       ;   operand 0 is the result,
+                       ;   operand 1 the parameter.
+   (UNPSEC_COS      1) ; `cos' operation (MODE_FLOAT):
+                       ;   operand 0 is the result,
+                       ;   operand 1 the parameter.
+   (UNSPEC_PUSH_MULT 2)        ; `push multiple' operation:
+                       ;   operand 0 is the first register,
+                       ;   subsequent registers are in parallel (use ...)
+                       ;   expressions.
+   (UNSPEC_PIC_SYM   3) ; A symbol that has been treated properly for pic
+                       ;   usage, that is, we will add the pic_register
+                       ;   value to it before trying to dereference it.
+   (UNSPEC_PRLG_STK  4) ; A special barrier that prevents frame accesses 
+                       ;   being scheduled before the stack adjustment insn.
+   (UNSPEC_CLZ      5) ; `clz' instruction, count leading zeros (SImode):
+                       ;   operand 0 is the result,
+                       ;   operand 1 is the parameter.
+  ]
+)
+
 ;; UNSPEC_VOLATILE Usage:
-;; 0 `blockage' insn to prevent scheduling across an insn in the code.
-;; 1 `epilogue' insn, used to represent any part of the instruction epilogue
-;;   sequence that isn't expanded into normal RTL.  Used for both normal
-;;   and sibcall epilogues.
-;; 2 `align' insn.  Used at the head of a minipool table for inlined 
-;;   constants.
-;; 3 `end-of-table'.  Used to mark the end of a minipool table.
-;; 4 `pool-entry(1)'.  An entry in the constant pool for an 8-bit object.
-;; 5 `pool-entry(2)'.  An entry in the constant pool for a 16-bit object.
-;; 6 `pool-entry(4)'.  An entry in the constant pool for a 32-bit object.
-;; 7 `pool-entry(8)'.  An entry in the constant pool for a 64-bit object.
-;;
+
+(define_constants
+  [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
+                       ;   insn in the code.
+   (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
+                       ;   instruction epilogue sequence that isn't expanded
+                       ;   into normal RTL.  Used for both normal and sibcall
+                       ;   epilogues.
+   (VUNSPEC_ALIGN    2) ; `align' insn.  Used at the head of a minipool table 
+                       ;   for inlined constants.
+   (VUNSPEC_POOL_END 3) ; `end-of-table'.  Used to mark the end of a minipool
+                       ;   table.
+   (VUNSPEC_POOL_1   4) ; `pool-entry(1)'.  An entry in the constant pool for
+                       ;   an 8-bit object.
+   (VUNSPEC_POOL_2   5) ; `pool-entry(2)'.  An entry in the constant pool for
+                       ;   a 16-bit object.
+   (VUNSPEC_POOL_4   6) ; `pool-entry(4)'.  An entry in the constant pool for
+                       ;   a 32-bit object.
+   (VUNSPEC_POOL_8   7) ; `pool-entry(8)'.  An entry in the constant pool for
+                       ;   a 64-bit object.
+   (VUNSPEC_PREFETCH 8) ; `pld' insn to prefetch a cache line:
+                       ;   operand 0 is the address to fetch.
+  ]
+)
 \f
+;;---------------------------------------------------------------------------
 ;; Attributes
 
 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
        (eq_attr "type" "!mult,load,store1,store2,store3,store4")) 32 32)
 \f
 ;;---------------------------------------------------------------------------
-;; Make code more maintainable by using names for fixed registers.
-
-(define_constants
-  [(LR_REGNUM       14)
-   (LAST_ARM_REGNUM 15)
-   (CC_REGNUM       24)]
-)
-
+;; Insn patterns
+;;
 ;; Addition insns.
 
 ;; Note: For DImode insns, there is normally no reason why operands should
 ;; to always call a library function.
 ;(define_insn "sinsf2"
 ;  [(set (match_operand:SF 0 "s_register_operand" "=f")
-;      (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 0))]
+;      (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")]
+;                  UNSPEC_SIN))]
 ;  "TARGET_ARM && TARGET_HARD_FLOAT"
 ;  "sin%?s\\t%0, %1"
 ;[(set_attr "type" "float_em")])
 ;
 ;(define_insn "sindf2"
 ;  [(set (match_operand:DF 0 "s_register_operand" "=f")
-;      (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 0))]
+;      (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")]
+;                  UNSPEC_SIN))]
 ;  "TARGET_ARM && TARGET_HARD_FLOAT"
 ;  "sin%?d\\t%0, %1"
 ;[(set_attr "type" "float_em")])
 ;(define_insn "*sindf_esfdf"
 ;  [(set (match_operand:DF 0 "s_register_operand" "=f")
 ;      (unspec:DF [(float_extend:DF
-;                   (match_operand:SF 1 "s_register_operand" "f"))] 0))]
+;                   (match_operand:SF 1 "s_register_operand" "f"))]
+;                  UNSPEC_SIN))]
 ;  "TARGET_ARM && TARGET_HARD_FLOAT"
 ;  "sin%?d\\t%0, %1"
 ;[(set_attr "type" "float_em")])
 ;
 ;(define_insn "sinxf2"
 ;  [(set (match_operand:XF 0 "s_register_operand" "=f")
-;      (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 0))]
+;      (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")]
+;                 UNSPEC_SIN))]
 ;  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
 ;  "sin%?e\\t%0, %1"
 ;[(set_attr "type" "float_em")])
 ;
 ;(define_insn "cossf2"
 ;  [(set (match_operand:SF 0 "s_register_operand" "=f")
-;      (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 1))]
+;      (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")]
+;                 UNSPEC_COS))]
 ;  "TARGET_ARM && TARGET_HARD_FLOAT"
 ;  "cos%?s\\t%0, %1"
 ;[(set_attr "type" "float_em")])
 ;
 ;(define_insn "cosdf2"
 ;  [(set (match_operand:DF 0 "s_register_operand" "=f")
-;      (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 1))]
+;      (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")]
+;                 UNSPEC_COS))]
 ;  "TARGET_ARM && TARGET_HARD_FLOAT"
 ;  "cos%?d\\t%0, %1"
 ;[(set_attr "type" "float_em")])
 ;(define_insn "*cosdf_esfdf"
 ;  [(set (match_operand:DF 0 "s_register_operand" "=f")
 ;      (unspec:DF [(float_extend:DF
-;                   (match_operand:SF 1 "s_register_operand" "f"))] 1))]
+;                   (match_operand:SF 1 "s_register_operand" "f"))]
+;                 UNSPEC_COS))]
 ;  "TARGET_ARM && TARGET_HARD_FLOAT"
 ;  "cos%?d\\t%0, %1"
 ;[(set_attr "type" "float_em")])
 ;
 ;(define_insn "cosxf2"
 ;  [(set (match_operand:XF 0 "s_register_operand" "=f")
-;      (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 1))]
+;      (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")]
+;                 UNSEPC_COS))]
 ;  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
 ;  "cos%?e\\t%0, %1"
 ;[(set_attr "type" "float_em")])
 
 (define_insn "pic_load_addr_arm"
   [(set (match_operand:SI 0 "s_register_operand" "=r")
-       (unspec:SI [(match_operand:SI 1 "" "mX")] 3))]
+       (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
   "TARGET_ARM && flag_pic"
   "ldr%?\\t%0, %1"
   [(set_attr "type" "load")
 
 (define_insn "pic_load_addr_thumb"
   [(set (match_operand:SI 0 "s_register_operand" "=l")
-       (unspec:SI [(match_operand:SI 1 "" "mX")] 3))]
+       (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
   "TARGET_THUMB && flag_pic"
   "ldr\\t%0, %1"
   [(set_attr "type" "load")
 ;; pic register in the rtl.
 (define_expand "pic_load_addr_based"
   [(set (match_operand:SI 0 "s_register_operand" "=r")
-       (unspec:SI [(match_operand 1 "" "") (match_dup 2)] 3))]
+       (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
   "TARGET_ARM && flag_pic"
   "operands[2] = pic_offset_table_rtx;"
 )
 (define_insn "*pic_load_addr_based_insn"
   [(set (match_operand:SI 0 "s_register_operand" "=r")
        (unspec:SI [(match_operand 1 "" "")
-                   (match_operand 2 "s_register_operand" "r")] 3))]
+                   (match_operand 2 "s_register_operand" "r")]
+                  UNSPEC_PIC_SYM))]
   "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
   "*
 #ifdef AOF_ASSEMBLER
 ;; all of memory.  This blocks insns from being moved across this point.
 
 (define_insn "blockage"
-  [(unspec_volatile [(const_int 0)] 0)]
+  [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
   "TARGET_EITHER"
   ""
   [(set_attr "length" "0")
 )
 
 (define_expand "epilogue"
-  [(unspec_volatile [(return)] 1)]
+  [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
   "TARGET_EITHER"
   "
   if (TARGET_THUMB)
   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
        gen_rtvec (1,
                gen_rtx_RETURN (VOIDmode)),
-       1));
+       VUNSPEC_EPILOGUE));
   DONE;
   "
 )
 
 (define_insn "sibcall_epilogue"
-  [(unspec_volatile [(const_int 0)] 1)]
+  [(unspec_volatile [(const_int 0)] VUNSPEC_EPILOGUE)]
   "TARGET_ARM"
   "*
   output_asm_insn (\"%@ Sibcall epilogue\", operands);
 )
 
 (define_insn "*epilogue_insns"
-  [(unspec_volatile [(return)] 1)]
+  [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
   "TARGET_EITHER"
   "*
   if (TARGET_ARM)
 (define_insn "*push_multi"
   [(match_parallel 2 "multi_register_push"
     [(set (match_operand:BLK 0 "memory_operand" "=m")
-         (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")] 2))])]
+         (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
+                     UNSPEC_PUSH_MULT))])]
   "TARGET_ARM"
   "*
   {
 (define_insn "*push_fp_multi"
   [(match_parallel 2 "multi_register_push"
     [(set (match_operand:BLK 0 "memory_operand" "=m")
-         (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")] 2))])]
+         (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
+                     UNSPEC_PUSH_MULT))])]
   "TARGET_ARM"
   "*
   {
 ;; Special patterns for dealing with the constant pool
 
 (define_insn "align_4"
-  [(unspec_volatile [(const_int 0)] 2)]
+  [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
   "TARGET_EITHER"
   "*
   assemble_align (32);
 )
 
 (define_insn "consttable_end"
-  [(unspec_volatile [(const_int 0)] 3)]
+  [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
   "TARGET_EITHER"
   "*
   making_const_table = FALSE;
 )
 
 (define_insn "consttable_1"
-  [(unspec_volatile [(match_operand 0 "" "")] 4)]
+  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
   "TARGET_THUMB"
   "*
   making_const_table = TRUE;
 )
 
 (define_insn "consttable_2"
-  [(unspec_volatile [(match_operand 0 "" "")] 5)]
+  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
   "TARGET_THUMB"
   "*
   making_const_table = TRUE;
 )
 
 (define_insn "consttable_4"
-  [(unspec_volatile [(match_operand 0 "" "")] 6)]
+  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
   "TARGET_EITHER"
   "*
   {
 )
 
 (define_insn "consttable_8"
-  [(unspec_volatile [(match_operand 0 "" "")] 7)]
+  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
   "TARGET_EITHER"
   "*
   {
 
 (define_insn "clz"
   [(set (match_operand:SI             0 "s_register_operand" "=r")
-       (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] 128))]
-  "TARGET_ARM"
+       (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")]
+                  UNSPEC_CLZ))]
+  "TARGET_ARM && arm_arch5"
   "clz\\t%0, %1")
 
-;; XScale instructions.
+(define_expand "ffssi2"
+  [(set (match_operand:SI 0 "s_register_operand" "")
+       (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
+  "TARGET_ARM && arm_arch5"
+  "
+  {
+    rtx t1, t2, t3;
+
+    t1 = gen_reg_rtx (SImode);
+    t2 = gen_reg_rtx (SImode);
+    t3 = gen_reg_rtx (SImode);
+
+    emit_insn (gen_negsi2 (t1, operands[1]));
+    emit_insn (gen_andsi3 (t2, operands[1], t1));
+    emit_insn (gen_clz (t3, t2));
+    emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
+    DONE;
+  }"
+)
+
+;; V5E instructions.
 
 (define_insn "prefetch"
   [(unspec_volatile
-    [(match_operand:SI 0 "offsettable_memory_operand" "o")] 129)]
-  "TARGET_ARM"
+    [(match_operand:SI 0 "offsettable_memory_operand" "o")] VUNSPEC_PREFETCH)]
+  "TARGET_ARM && arm_arch5e"
   "pld\\t%0")
 
 ;; General predication pattern