re PR target/52144 (ARM should support arm/thumb function attribute to permit differe...
authorChristian Bruel <chrbr@gcc.gnu.org>
Tue, 26 May 2015 14:06:17 +0000 (16:06 +0200)
committerChristian Bruel <chrbr@gcc.gnu.org>
Tue, 26 May 2015 14:06:17 +0000 (16:06 +0200)
 2015-05-13  Christian Bruel  <christian.bruel@st.com>

PR target/52144
* config/arm/arm.c (arm_option_check_internal)
(arm_option_params_internal): Check opts->target_flags to set macros.
(TREE_TARGET_ARM, TREE_TARGET_THUMB)
(TREE_TARGET_THUMB1, TREE_TARGET_THUMB2) Replace with...
(TARGET_ARM_P, TARGET_THUMB_P, TARGET_THUMB1_P, TARGET_THUMB2_P)
(builtin_define): Replaced with def_or_undef_macro.
* config/arm/arm.h (TREE_TARGET_ARM, TREE_TARGET_THUMB)
TREE_TARGET_THUMB1, TREE_TARGET_THUMB2) Redefine with...
(TARGET_ARM_P, TARGET_THUMB_P, TARGET_THUMB1_P, TARGET_THUMB2_P)
(TARGET_32BIT_P, TARGET_ARM_QBIT_P, TARGET_ARM_SAT_P, TARGET_IDIV_P)
(TARGET_HAVE_LDREX_P, TARGET_HAVE_LDREXBH_P, TARGET_HAVE_LDREXD_P)
(TARGET_ARM_FEATURE_LDREX_P)
(TARGET_DSP_MULTIPLY_P, TARGET_INT_SIMD_P): New macros.
(def_or_undef_macro): New function.

From-SVN: r223699

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

index 70a8f0ef96dcfdfde1fea7ca8e3d5088d705368a..a9bdd6c24c578d3027f649c54d7ffd6f7625b341 100644 (file)
@@ -1,3 +1,21 @@
+ 2015-05-13  Christian Bruel  <christian.bruel@st.com>
+
+       PR target/52144
+       * config/arm/arm.c (arm_option_check_internal)
+       (arm_option_params_internal): Check opts->target_flags to set macros.
+       (TREE_TARGET_ARM, TREE_TARGET_THUMB)
+       (TREE_TARGET_THUMB1, TREE_TARGET_THUMB2) Replace with...
+       (TARGET_ARM_P, TARGET_THUMB_P, TARGET_THUMB1_P, TARGET_THUMB2_P)
+       (builtin_define): Replaced with def_or_undef_macro.
+       * config/arm/arm.h (TREE_TARGET_ARM, TREE_TARGET_THUMB)
+       TREE_TARGET_THUMB1, TREE_TARGET_THUMB2) Redefine with...
+       (TARGET_ARM_P, TARGET_THUMB_P, TARGET_THUMB1_P, TARGET_THUMB2_P)
+       (TARGET_32BIT_P, TARGET_ARM_QBIT_P, TARGET_ARM_SAT_P, TARGET_IDIV_P)
+       (TARGET_HAVE_LDREX_P, TARGET_HAVE_LDREXBH_P, TARGET_HAVE_LDREXD_P)
+       (TARGET_ARM_FEATURE_LDREX_P)
+       (TARGET_DSP_MULTIPLY_P, TARGET_INT_SIMD_P): New macros.
+       (def_or_undef_macro): New function.
+
 2015-05-26  Christian Bruel  <christian.bruel@st.com>
 
        * c-common.h (builtin_define_with_int_value)
index 8dfbd78f46c9e8f8a4b7646dbbe2bb4fb68b29a7..8f9a867a989ab53b84f07848d20203cd5d86ce59 100644 (file)
@@ -55,31 +55,49 @@ arm_lang_object_attributes_init (void)
 #define builtin_define(TXT) cpp_define (pfile, TXT)
 #define builtin_assert(TXT) cpp_assert (pfile, TXT)
 
+/* Define or undefine macros based on the current target.  If the user does
+   #pragma GCC target, we need to adjust the macros dynamically.  */
+
+static void
+def_or_undef_macro(struct cpp_reader* pfile, const char *name, bool def_p) 
+{
+  if (def_p)
+    cpp_define (pfile, name); 
+  else  
+    cpp_undef (pfile, name); 
+} 
+
 void
 arm_cpu_cpp_builtins (struct cpp_reader * pfile)
 {
-  if (TARGET_DSP_MULTIPLY)
-    builtin_define ("__ARM_FEATURE_DSP");
-  if (TARGET_ARM_QBIT)
-    builtin_define ("__ARM_FEATURE_QBIT");
-  if (TARGET_ARM_SAT)
-    builtin_define ("__ARM_FEATURE_SAT");
+  int flags = target_flags;
+
+  def_or_undef_macro (pfile, "__ARM_FEATURE_DSP",
+                     TARGET_DSP_MULTIPLY_P (flags));
+  def_or_undef_macro (pfile, "__ARM_FEATURE_QBIT",
+                     TARGET_ARM_QBIT_P (flags)); 
+  def_or_undef_macro (pfile, "__ARM_FEATURE_SAT",
+                     TARGET_ARM_SAT_P (flags));
   if (TARGET_CRYPTO)
     builtin_define ("__ARM_FEATURE_CRYPTO");
   if (unaligned_access)
     builtin_define ("__ARM_FEATURE_UNALIGNED");
   if (TARGET_CRC32)
     builtin_define ("__ARM_FEATURE_CRC32");
-  if (TARGET_32BIT)
-    builtin_define ("__ARM_32BIT_STATE");
-  if (TARGET_ARM_FEATURE_LDREX)
+
+  def_or_undef_macro (pfile, "__ARM_32BIT_STATE", TARGET_32BIT_P (flags)); 
+
+  if (TARGET_ARM_FEATURE_LDREX_P (flags))
     builtin_define_with_int_value ("__ARM_FEATURE_LDREX", 
-                                  TARGET_ARM_FEATURE_LDREX);
-  if ((TARGET_ARM_ARCH >= 5 && !TARGET_THUMB)
-      || TARGET_ARM_ARCH_ISA_THUMB >=2)
-    builtin_define ("__ARM_FEATURE_CLZ");
-  if (TARGET_INT_SIMD)
-    builtin_define ("__ARM_FEATURE_SIMD32");
+                                  TARGET_ARM_FEATURE_LDREX_P (flags));
+  else
+    cpp_undef (pfile, "__ARM_FEATURE_LDREX");
+
+  def_or_undef_macro (pfile, "__ARM_FEATURE_CLZ",
+                     ((TARGET_ARM_ARCH >= 5 && !TARGET_THUMB_P (flags))
+                      || TARGET_ARM_ARCH_ISA_THUMB >=2));
+
+  def_or_undef_macro (pfile, "__ARM_FEATURE_SIMD32", TARGET_INT_SIMD_P (flags));
 
   builtin_define_with_int_value ("__ARM_SIZEOF_MINIMAL_ENUM",
                                 flag_short_enums ? 1 : 4);
@@ -96,10 +114,14 @@ arm_cpu_cpp_builtins (struct cpp_reader * pfile)
   if (arm_arch_notm)
     builtin_define ("__ARM_ARCH_ISA_ARM");
   builtin_define ("__APCS_32__");
-  if (TARGET_THUMB)
-    builtin_define ("__thumb__");
-  if (TARGET_THUMB2)
-    builtin_define ("__thumb2__");
+
+  def_or_undef_macro (pfile, "__thumb__", TARGET_THUMB_P (flags));
+  def_or_undef_macro (pfile, "__thumb2__", TARGET_THUMB2_P (flags));
+  if (TARGET_BIG_END)
+    def_or_undef_macro (pfile, "__THUMBEB__", TARGET_THUMB_P (flags));
+  else
+    def_or_undef_macro (pfile, "__THUMBEL__", TARGET_THUMB_P (flags));
+
   if (TARGET_ARM_ARCH_ISA_THUMB)
     builtin_define_with_int_value ("__ARM_ARCH_ISA_THUMB",
                                   TARGET_ARM_ARCH_ISA_THUMB);
@@ -108,14 +130,10 @@ arm_cpu_cpp_builtins (struct cpp_reader * pfile)
     {
       builtin_define ("__ARMEB__");
       builtin_define ("__ARM_BIG_ENDIAN");
-      if (TARGET_THUMB)
-       builtin_define ("__THUMBEB__");
     }
   else
     {
       builtin_define ("__ARMEL__");
-      if (TARGET_THUMB)
-       builtin_define ("__THUMBEL__");
     }
 
   if (TARGET_SOFT_FLOAT)
@@ -166,11 +184,11 @@ arm_cpu_cpp_builtins (struct cpp_reader * pfile)
        builtin_define ("__ARM_PCS");
       builtin_define ("__ARM_EABI__");
     }
-  if (TARGET_IDIV)
-    {
-      builtin_define ("__ARM_ARCH_EXT_IDIV__");
-      builtin_define ("__ARM_FEATURE_IDIV");
-    }
-  if (inline_asm_unified)
-    builtin_define ("__ARM_ASM_SYNTAX_UNIFIED__");
+
+
+
+  def_or_undef_macro (pfile, "__ARM_ARCH_EXT_IDIV__", TARGET_IDIV_P (flags));
+  def_or_undef_macro (pfile, "__ARM_FEATURE_IDIV", TARGET_IDIV_P (flags));
+
+  def_or_undef_macro (pfile, "__ARM_ASM_SYNTAX_UNIFIED__", inline_asm_unified);
 }
index fa9543138bcc60490f4e0bbf31e10caeff58c7e5..888813b9c43f2f3b6a7f5eb9143a29c14a84eb0a 100644 (file)
@@ -2702,35 +2702,37 @@ arm_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
 static void
 arm_option_check_internal (struct gcc_options *opts)
 {
+  int flags = opts->x_target_flags;
+
   /* Make sure that the processor choice does not conflict with any of the
      other command line choices.  */
-  if (TREE_TARGET_ARM (opts) && !(insn_flags & FL_NOTM))
+  if (TARGET_ARM_P (flags) && !(insn_flags & FL_NOTM))
     error ("target CPU does not support ARM mode");
 
   /* TARGET_BACKTRACE calls leaf_function_p, which causes a crash if done
      from here where no function is being compiled currently.  */
-  if ((TARGET_TPCS_FRAME || TARGET_TPCS_LEAF_FRAME) && TREE_TARGET_ARM (opts))
+  if ((TARGET_TPCS_FRAME || TARGET_TPCS_LEAF_FRAME) && TARGET_ARM_P (flags))
     warning (0, "enabling backtrace support is only meaningful when compiling for the Thumb");
 
-  if (TREE_TARGET_ARM (opts) && TARGET_CALLEE_INTERWORKING)
+  if (TARGET_ARM_P (flags) && TARGET_CALLEE_INTERWORKING)
     warning (0, "enabling callee interworking support is only meaningful when compiling for the Thumb");
 
   /* If this target is normally configured to use APCS frames, warn if they
      are turned off and debugging is turned on.  */
-  if (TREE_TARGET_ARM (opts)
+  if (TARGET_ARM_P (flags)
       && write_symbols != NO_DEBUG
       && !TARGET_APCS_FRAME
       && (TARGET_DEFAULT & MASK_APCS_FRAME))
     warning (0, "-g with -mno-apcs-frame may not give sensible debugging");
 
   /* iWMMXt unsupported under Thumb mode.  */
-  if (TREE_TARGET_THUMB (opts) && TARGET_IWMMXT)
+  if (TARGET_THUMB_P (flags) && TARGET_IWMMXT)
     error ("iWMMXt unsupported under Thumb mode");
 
-  if (TARGET_HARD_TP && TREE_TARGET_THUMB1 (opts))
+  if (TARGET_HARD_TP && TARGET_THUMB1_P (flags))
     error ("can not use -mtp=cp15 with 16-bit Thumb");
 
-  if (TREE_TARGET_THUMB (opts) && TARGET_VXWORKS_RTP && flag_pic)
+  if (TARGET_THUMB_P (flags) && TARGET_VXWORKS_RTP && flag_pic)
     {
       error ("RTP PIC is incompatible with Thumb");
       flag_pic = 0;
@@ -2739,7 +2741,7 @@ arm_option_check_internal (struct gcc_options *opts)
   /* We only support -mslow-flash-data on armv7-m targets.  */
   if (target_slow_flash_data
       && ((!(arm_arch7 && !arm_arch_notm) && !arm_arch7em)
-         || (TREE_TARGET_THUMB1 (opts) || flag_pic || TARGET_NEON)))
+         || (TARGET_THUMB1_P (flags) || flag_pic || TARGET_NEON)))
     error ("-mslow-flash-data only supports non-pic code on armv7-m targets");
 }
 
@@ -2747,9 +2749,11 @@ arm_option_check_internal (struct gcc_options *opts)
 static void
 arm_option_params_internal (struct gcc_options *opts)
 {
+  int flags = opts->x_target_flags;
+
  /* If we are not using the default (ARM mode) section anchor offset
      ranges, then set the correct ranges now.  */
-  if (TREE_TARGET_THUMB1 (opts))
+  if (TARGET_THUMB1_P (flags))
     {
       /* Thumb-1 LDR instructions cannot have negative offsets.
          Permissible positive offset ranges are 5-bit (for byte loads),
@@ -2759,7 +2763,7 @@ arm_option_params_internal (struct gcc_options *opts)
       targetm.min_anchor_offset = 0;
       targetm.max_anchor_offset = 127;
     }
-  else if (TREE_TARGET_THUMB2 (opts))
+  else if (TARGET_THUMB2_P (flags))
     {
       /* The minimum is set such that the total size of the block
          for a particular anchor is 248 + 1 + 4095 bytes, which is
@@ -2780,7 +2784,7 @@ arm_option_params_internal (struct gcc_options *opts)
       max_insns_skipped = 6;
 
       /* For THUMB2, we limit the conditional sequence to one IT block.  */
-      if (TREE_TARGET_THUMB2 (opts))
+      if (TARGET_THUMB2_P (flags))
         max_insns_skipped = opts->x_arm_restrict_it ? 1 : 4;
     }
   else
@@ -2792,13 +2796,13 @@ static void
 arm_option_override_internal (struct gcc_options *opts,
                              struct gcc_options *opts_set)
 {
-  if (TREE_TARGET_THUMB (opts) && !(insn_flags & FL_THUMB))
+  if (TARGET_THUMB_P (opts->x_target_flags) && !(insn_flags & FL_THUMB))
     {
       warning (0, "target CPU does not support THUMB instructions");
       opts->x_target_flags &= ~MASK_THUMB;
     }
 
-  if (TARGET_APCS_FRAME && TREE_TARGET_THUMB (opts))
+  if (TARGET_APCS_FRAME && TARGET_THUMB_P (opts->x_target_flags))
     {
       /* warning (0, "ignoring -mapcs-frame because -mthumb was used"); */
       opts->x_target_flags &= ~MASK_APCS_FRAME;
@@ -2806,16 +2810,16 @@ arm_option_override_internal (struct gcc_options *opts,
 
   /* Callee super interworking implies thumb interworking.  Adding
      this to the flags here simplifies the logic elsewhere.  */
-  if (TREE_TARGET_THUMB (opts) && TARGET_CALLEE_INTERWORKING)
+  if (TARGET_THUMB_P (opts->x_target_flags) && TARGET_CALLEE_INTERWORKING)
     opts->x_target_flags |= MASK_INTERWORK;
 
   if (! opts_set->x_arm_restrict_it)
     opts->x_arm_restrict_it = arm_arch8;
 
-  if (!TREE_TARGET_THUMB2 (opts))
+  if (!TARGET_THUMB2_P (opts->x_target_flags))
     opts->x_arm_restrict_it = 0;
 
-  if (TREE_TARGET_THUMB1 (opts))
+  if (TARGET_THUMB1_P (opts->x_target_flags))
     {
       /* Don't warn since it's on by default in -O2.  */
       opts->x_flag_schedule_insns = 0;
@@ -2823,7 +2827,8 @@ arm_option_override_internal (struct gcc_options *opts,
 
   /* Disable shrink-wrap when optimizing function for size, since it tends to
      generate additional returns.  */
-  if (optimize_function_for_size_p (cfun) && TREE_TARGET_THUMB2 (opts))
+  if (optimize_function_for_size_p (cfun)
+      && TARGET_THUMB2_P (opts->x_target_flags))
     opts->x_flag_shrink_wrap = false;
 
   /* In Thumb1 mode, we emit the epilogue in RTL, but the last insn
@@ -2834,12 +2839,12 @@ arm_option_override_internal (struct gcc_options *opts,
      finding out about it.  Therefore, disable fipa-ra in Thumb1 mode.
      TODO: Accurately model clobbers for epilogue_insns and reenable
      fipa-ra.  */
-  if (TREE_TARGET_THUMB1 (opts))
+  if (TARGET_THUMB1_P (opts->x_target_flags))
     opts->x_flag_ipa_ra = 0;
 
   /* Thumb2 inline assembly code should always use unified syntax.
      This will apply to ARM and Thumb1 eventually.  */
-  opts->x_inline_asm_unified = TREE_TARGET_THUMB2 (opts);
+  opts->x_inline_asm_unified = TARGET_THUMB2_P (opts->x_target_flags);
 }
 
 /* Fix up any incompatible options that the user has specified.  */
index 4cdd60d69b46e0396afd73eee681e08b5eb0ea0a..df0aeb4a825503cc7f941cc7768ab51a4971d839 100644 (file)
@@ -128,12 +128,10 @@ extern void (*arm_lang_output_object_attributes_hook)(void);
 #endif
 \f
 /* Tree Target Specification.  */
-#define TREE_TARGET_THUMB(opts)  (TARGET_THUMB_P (opts->x_target_flags))
-#define TREE_TARGET_ARM(opts)    (!TARGET_THUMB_P (opts->x_target_flags))
-#define TREE_TARGET_THUMB1(opts) (TARGET_THUMB_P (opts->x_target_flags) \
-                                 && !arm_arch_thumb2)
-#define TREE_TARGET_THUMB2(opts) (TARGET_THUMB_P (opts->x_target_flags) \
-                                 && arm_arch_thumb2)
+#define TARGET_ARM_P(flags)    (!TARGET_THUMB_P (flags))
+#define TARGET_THUMB1_P(flags) (TARGET_THUMB_P (flags) && !arm_arch_thumb2)
+#define TARGET_THUMB2_P(flags) (TARGET_THUMB_P (flags) && arm_arch_thumb2)
+
 /* Run-time Target Specification.  */
 #define TARGET_SOFT_FLOAT              (arm_float_abi == ARM_FLOAT_ABI_SOFT)
 /* Use hardware floating point instructions. */
@@ -162,6 +160,8 @@ extern void (*arm_lang_output_object_attributes_hook)(void);
 #define TARGET_THUMB1                  (TARGET_THUMB && !arm_arch_thumb2)
 /* Arm or Thumb-2 32-bit code.  */
 #define TARGET_32BIT                   (TARGET_ARM || arm_arch_thumb2)
+#define TARGET_32BIT_P(flags)          (TARGET_ARM_P (flags) \
+                                        || arm_arch_thumb2)
 /* 32-bit Thumb-2 code.  */
 #define TARGET_THUMB2                  (TARGET_THUMB && arm_arch_thumb2)
 /* Thumb-1 only.  */
@@ -216,17 +216,21 @@ extern void (*arm_lang_output_object_attributes_hook)(void);
                     && TARGET_VFP && arm_fpu_desc->neon)
 
 /* Q-bit is present.  */
-#define TARGET_ARM_QBIT \
-  (TARGET_32BIT && arm_arch5e && (arm_arch_notm || arm_arch7))
+#define TARGET_ARM_QBIT_P(flags) \
+  (TARGET_32BIT_P (flags) && arm_arch5e && (arm_arch_notm || arm_arch7))
+#define TARGET_ARM_QBIT TARGET_ARM_QBIT_P(target_flags)
 /* Saturation operation, e.g. SSAT.  */
-#define TARGET_ARM_SAT \
-  (TARGET_32BIT && arm_arch6 && (arm_arch_notm || arm_arch7))
+#define TARGET_ARM_SAT_P(flags) \
+  (TARGET_32BIT_P (flags) && arm_arch6 && (arm_arch_notm || arm_arch7))
+#define TARGET_ARM_SAT TARGET_ARM_SAT_P(target_flags)
 /* "DSP" multiply instructions, eg. SMULxy.  */
-#define TARGET_DSP_MULTIPLY \
-  (TARGET_32BIT && arm_arch5e && (arm_arch_notm || arm_arch7em))
+#define TARGET_DSP_MULTIPLY_P(flags) \
+  (TARGET_32BIT_P (flags) && arm_arch5e && (arm_arch_notm || arm_arch7em))
+#define TARGET_DSP_MULTIPLY TARGET_DSP_MULTIPLY_P(target_flags)
 /* Integer SIMD instructions, and extend-accumulate instructions.  */
-#define TARGET_INT_SIMD \
-  (TARGET_32BIT && arm_arch6 && (arm_arch_notm || arm_arch7em))
+#define TARGET_INT_SIMD_P(flags) \
+  (TARGET_32BIT_P (flags) && arm_arch6 && (arm_arch_notm || arm_arch7em))
+#define TARGET_INT_SIMD TARGET_INT_SIMD_P(target_flags)
 
 /* Should MOVW/MOVT be used in preference to a constant pool.  */
 #define TARGET_USE_MOVT \
@@ -249,21 +253,30 @@ extern void (*arm_lang_output_object_attributes_hook)(void);
 #define TARGET_HAVE_MEMORY_BARRIER (TARGET_HAVE_DMB || TARGET_HAVE_DMB_MCR)
 
 /* Nonzero if this chip supports ldrex and strex */
-#define TARGET_HAVE_LDREX      ((arm_arch6 && TARGET_ARM) || arm_arch7)
+#define TARGET_HAVE_LDREX_P(flags) ((arm_arch6 && TARGET_ARM_P (flags)) \
+                                   || arm_arch7)
+#define TARGET_HAVE_LDREX        TARGET_HAVE_LDREX_P (target_flags) 
 
 /* Nonzero if this chip supports ldrex{bh} and strex{bh}.  */
-#define TARGET_HAVE_LDREXBH    ((arm_arch6k && TARGET_ARM) || arm_arch7)
+#define TARGET_HAVE_LDREXBH_P(flags) ((arm_arch6k && TARGET_ARM_P (flags)) \
+                                     || arm_arch7)
+#define TARGET_HAVE_LDREXBH         TARGET_HAVE_LDREXBH_P (target_flags)
 
 /* Nonzero if this chip supports ldrexd and strexd.  */
-#define TARGET_HAVE_LDREXD     (((arm_arch6k && TARGET_ARM) || arm_arch7) \
-                                && arm_arch_notm)
+#define TARGET_HAVE_LDREXD_P(flags) (((arm_arch6k && TARGET_ARM_P (flags)) \
+                                     || arm_arch7) && arm_arch_notm)
+#define TARGET_HAVE_LDREXD         TARGET_HAVE_LDREXD_P (target_flags)
+                               
 
 /* Nonzero if this chip supports load-acquire and store-release.  */
 #define TARGET_HAVE_LDACQ      (TARGET_ARM_ARCH >= 8)
 
 /* Nonzero if integer division instructions supported.  */
-#define TARGET_IDIV            ((TARGET_ARM && arm_arch_arm_hwdiv) \
-                                || (TARGET_THUMB2 && arm_arch_thumb_hwdiv))
+#define TARGET_IDIV_P(flags)   ((TARGET_ARM_P (flags) && arm_arch_arm_hwdiv) \
+                                || (TARGET_THUMB2_P (flags)                  \
+                                    && arm_arch_thumb_hwdiv))
+#define TARGET_IDIV             TARGET_IDIV_P (target_flags)           
+
 
 /* Nonzero if disallow volatile memory access in IT block.  */
 #define TARGET_NO_VOLATILE_CE          (arm_arch_no_volatile_ce)
@@ -2189,6 +2202,11 @@ extern int making_const_table;
    | (TARGET_HAVE_LDREXBH ? 3 : 0)                             \
    | (TARGET_HAVE_LDREXD ? 8 : 0))
 
+#define TARGET_ARM_FEATURE_LDREX_P(flags)                      \
+  ((TARGET_HAVE_LDREX_P (flags) ? 4 : 0)                       \
+   | (TARGET_HAVE_LDREXBH_P (flags) ? 3 : 0)                   \
+   | (TARGET_HAVE_LDREXD_P (flags) ? 8 : 0))
+
 /* Set as a bit mask indicating the available widths of hardware floating
    point types.  Where bit 1 indicates 16-bit support, bit 2 indicates
    32-bit support, bit 3 indicates 64-bit support.  */