diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f300b16e137d8f018b042a8689c04c625c32426f..4f6d2c3359fd96b6db5f4234bcae69b49e5c249f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,33 @@
+2011-05-18  Joseph Myers  <joseph@codesourcery.com>
+
+	* config/arm/arm-opts.h (enum arm_fp16_format_type, enum
+	arm_abi_type, enum float_abi_type, enum arm_tp_type): Move from
+	arm.h.
+	* config/arm/arm.c (arm_float_abi, arm_fp16_format, arm_abi,
+	target_thread_pointer, arm_structure_size_boundary, struct
+	float_abi, all_float_abis, struct fp16_format, all_fp16_formats,
+	struct abi_name, arm_all_abis): Remove.
+	(arm_option_override) Don't process most enumerated option values
+	here.  Don't process target_fpe_name here.  Work with integer not
+	string for structure size boundary; use separate diagnostics for
+	each case.
+	* config/arm/arm.h (enum float_abi_type, enum
+	arm_fp16_format_type, enum arm_abi_type, enum arm_tp_type): Move
+	to arm-opts.h.
+	(arm_float_abi, arm_fp16_format, arm_abi, target_thread_pointer,
+	arm_structure_size_boundary): Remove.
+	* config/arm/arm.opt (mabi=): Use Enum and Init.
+	(arm_abi_type): New Enum and EnumValue entries.
+	(mfloat-abi=): Use Enum and Init.
+	(float_abi_type): New Enum and EnumValue entries.
+	(mfp=, mfpe=): Replace by separate Alias entries for each
+	argument.
+	(mfp16-format=): Use Enum and Init.
+	(arm_fp16_format_type): New Enum and EnumValue entries.
+	(mstructure-size-boundary=): Use UInteger and Init.
+	(mtp=): Use Enum and Init.
+	(arm_tp_type): New Enum and EnumValue entries.
+
 2011-05-18  Richard Guenther  <rguenther@suse.de>
 
 	PR tree-optimization/49018
diff --git a/gcc/config/arm/arm-opts.h b/gcc/config/arm/arm-opts.h
index f9f18036b92519b512a7a9d37b4f9a80acea94a6..c35224eaf5cd00534cbead35cd5abb98f2aad0f9 100644
--- a/gcc/config/arm/arm-opts.h
+++ b/gcc/config/arm/arm-opts.h
@@ -33,4 +33,39 @@ enum processor_type
   arm_none
 };
 
+/* Which __fp16 format to use.
+   The enumeration values correspond to the numbering for the
+   Tag_ABI_FP_16bit_format attribute.
+ */
+enum arm_fp16_format_type
+{
+  ARM_FP16_FORMAT_NONE = 0,
+  ARM_FP16_FORMAT_IEEE = 1,
+  ARM_FP16_FORMAT_ALTERNATIVE = 2
+};
+
+/* Which ABI to use.  */
+enum arm_abi_type
+{
+  ARM_ABI_APCS,
+  ARM_ABI_ATPCS,
+  ARM_ABI_AAPCS,
+  ARM_ABI_IWMMXT,
+  ARM_ABI_AAPCS_LINUX
+};
+
+enum float_abi_type
+{
+  ARM_FLOAT_ABI_SOFT,
+  ARM_FLOAT_ABI_SOFTFP,
+  ARM_FLOAT_ABI_HARD
+};
+
+/* Which thread pointer access sequence to use.  */
+enum arm_tp_type {
+  TP_AUTO,
+  TP_SOFT,
+  TP_CP15
+};
+
 #endif
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 4f9c2aa706371997372984c130038f1c6d84f3ec..2b599346eddc83ce509a9fb458361bb611159690 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -636,21 +636,6 @@ int arm_fpu_attr;
 /* Which floating popint hardware to use.  */
 const struct arm_fpu_desc *arm_fpu_desc;
 
-/* Whether to use floating point hardware.  */
-enum float_abi_type arm_float_abi;
-
-/* Which __fp16 format to use.  */
-enum arm_fp16_format_type arm_fp16_format;
-
-/* Which ABI to use.  */
-enum arm_abi_type arm_abi;
-
-/* Which thread pointer model to use.  */
-enum arm_tp_type target_thread_pointer = TP_AUTO;
-
-/* Used to parse -mstructure_size_boundary command line option.  */
-int    arm_structure_size_boundary = DEFAULT_STRUCTURE_SIZE_BOUNDARY;
-
 /* Used for Thumb call_via trampolines.  */
 rtx thumb_call_via_label[14];
 static int thumb_call_reg_needed;
@@ -976,58 +961,6 @@ static const struct arm_fpu_desc all_fpus[] =
 };
 
 
-struct float_abi
-{
-  const char * name;
-  enum float_abi_type abi_type;
-};
-
-
-/* Available values for -mfloat-abi=.  */
-
-static const struct float_abi all_float_abis[] =
-{
-  {"soft",	ARM_FLOAT_ABI_SOFT},
-  {"softfp",	ARM_FLOAT_ABI_SOFTFP},
-  {"hard",	ARM_FLOAT_ABI_HARD}
-};
-
-
-struct fp16_format
-{
-  const char *name;
-  enum arm_fp16_format_type fp16_format_type;
-};
-
-
-/* Available values for -mfp16-format=.  */
-
-static const struct fp16_format all_fp16_formats[] =
-{
-  {"none",		ARM_FP16_FORMAT_NONE},
-  {"ieee",		ARM_FP16_FORMAT_IEEE},
-  {"alternative",	ARM_FP16_FORMAT_ALTERNATIVE}
-};
-
-
-struct abi_name
-{
-  const char *name;
-  enum arm_abi_type abi_type;
-};
-
-
-/* Available values for -mabi=.  */
-
-static const struct abi_name arm_all_abis[] =
-{
-  {"apcs-gnu",    ARM_ABI_APCS},
-  {"atpcs",   ARM_ABI_ATPCS},
-  {"aapcs",   ARM_ABI_AAPCS},
-  {"iwmmxt",  ARM_ABI_IWMMXT},
-  {"aapcs-linux",   ARM_ABI_AAPCS_LINUX}
-};
-
 /* Supported TLS relocations.  */
 
 enum tls_reloc {
@@ -1447,39 +1380,6 @@ arm_option_override (void)
   tune_flags = arm_selected_tune->flags;
   current_tune = arm_selected_tune->tune;
 
-  if (target_fp16_format_name)
-    {
-      for (i = 0; i < ARRAY_SIZE (all_fp16_formats); i++)
-	{
-	  if (streq (all_fp16_formats[i].name, target_fp16_format_name))
-	    {
-	      arm_fp16_format = all_fp16_formats[i].fp16_format_type;
-	      break;
-	    }
-	}
-      if (i == ARRAY_SIZE (all_fp16_formats))
-	error ("invalid __fp16 format option: -mfp16-format=%s",
-	       target_fp16_format_name);
-    }
-  else
-    arm_fp16_format = ARM_FP16_FORMAT_NONE;
-
-  if (target_abi_name)
-    {
-      for (i = 0; i < ARRAY_SIZE (arm_all_abis); i++)
-	{
-	  if (streq (arm_all_abis[i].name, target_abi_name))
-	    {
-	      arm_abi = arm_all_abis[i].abi_type;
-	      break;
-	    }
-	}
-      if (i == ARRAY_SIZE (arm_all_abis))
-	error ("invalid ABI option: -mabi=%s", target_abi_name);
-    }
-  else
-    arm_abi = ARM_DEFAULT_ABI;
-
   /* Make sure that the processor choice does not conflict with any of the
      other command line choices.  */
   if (TARGET_ARM && !(insn_flags & FL_NOTM))
@@ -1607,17 +1507,6 @@ arm_option_override (void)
   if (TARGET_IWMMXT_ABI && !TARGET_IWMMXT)
     error ("iwmmxt abi requires an iwmmxt capable cpu");
 
-  if (target_fpu_name == NULL && target_fpe_name != NULL)
-    {
-      if (streq (target_fpe_name, "2"))
-	target_fpu_name = "fpe2";
-      else if (streq (target_fpe_name, "3"))
-	target_fpu_name = "fpe3";
-      else
-	error ("invalid floating point emulation option: -mfpe=%s",
-	       target_fpe_name);
-    }
-
   if (target_fpu_name == NULL)
     {
 #ifdef FPUTYPE_DEFAULT
@@ -1669,24 +1558,6 @@ arm_option_override (void)
       gcc_unreachable();
     }
 
-  if (target_float_abi_name != NULL)
-    {
-      /* The user specified a FP ABI.  */
-      for (i = 0; i < ARRAY_SIZE (all_float_abis); i++)
-	{
-	  if (streq (all_float_abis[i].name, target_float_abi_name))
-	    {
-	      arm_float_abi = all_float_abis[i].abi_type;
-	      break;
-	    }
-	}
-      if (i == ARRAY_SIZE (all_float_abis))
-	error ("invalid floating point abi: -mfloat-abi=%s",
-	       target_float_abi_name);
-    }
-  else
-    arm_float_abi = TARGET_DEFAULT_FLOAT_ABI;
-
   if (TARGET_AAPCS_BASED
       && (arm_fpu_desc->model == ARM_FP_MODEL_FPA))
     error ("FPA is unsupported in the AAPCS");
@@ -1747,18 +1618,6 @@ arm_option_override (void)
       && (tune_flags & FL_MODE32) == 0)
     flag_schedule_insns = flag_schedule_insns_after_reload = 0;
 
-  if (target_thread_switch)
-    {
-      if (strcmp (target_thread_switch, "soft") == 0)
-	target_thread_pointer = TP_SOFT;
-      else if (strcmp (target_thread_switch, "auto") == 0)
-	target_thread_pointer = TP_AUTO;
-      else if (strcmp (target_thread_switch, "cp15") == 0)
-	target_thread_pointer = TP_CP15;
-      else
-	error ("invalid thread pointer option: -mtp=%s", target_thread_switch);
-    }
-
   /* Use the cp15 method if it is available.  */
   if (target_thread_pointer == TP_AUTO)
     {
@@ -1772,19 +1631,25 @@ arm_option_override (void)
     error ("can not use -mtp=cp15 with 16-bit Thumb");
 
   /* Override the default structure alignment for AAPCS ABI.  */
-  if (TARGET_AAPCS_BASED)
-    arm_structure_size_boundary = 8;
-
-  if (structure_size_string != NULL)
+  if (!global_options_set.x_arm_structure_size_boundary)
     {
-      int size = strtol (structure_size_string, NULL, 0);
-
-      if (size == 8 || size == 32
-	  || (ARM_DOUBLEWORD_ALIGN && size == 64))
-	arm_structure_size_boundary = size;
-      else
-	warning (0, "structure size boundary can only be set to %s",
-		 ARM_DOUBLEWORD_ALIGN ? "8, 32 or 64": "8 or 32");
+      if (TARGET_AAPCS_BASED)
+	arm_structure_size_boundary = 8;
+    }
+  else
+    {
+      if (arm_structure_size_boundary != 8
+	  && arm_structure_size_boundary != 32
+	  && !(ARM_DOUBLEWORD_ALIGN && arm_structure_size_boundary == 64))
+	{
+	  if (ARM_DOUBLEWORD_ALIGN)
+	    warning (0,
+		     "structure size boundary can only be set to 8, 32 or 64");
+	  else
+	    warning (0, "structure size boundary can only be set to 8 or 32");
+	  arm_structure_size_boundary
+	    = (TARGET_AAPCS_BASED ? 8 : DEFAULT_STRUCTURE_SIZE_BOUNDARY);
+	}
     }
 
   if (!TARGET_ARM && TARGET_VXWORKS_RTP && flag_pic)
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index 43323942a44cb0e63a834d73a826472732344628..86d842ddf4aa71f200e11776960fbc793a028953 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -349,59 +349,17 @@ extern const struct arm_fpu_desc
 /* Which floating point hardware to schedule for.  */
 extern int arm_fpu_attr;
 
-enum float_abi_type
-{
-  ARM_FLOAT_ABI_SOFT,
-  ARM_FLOAT_ABI_SOFTFP,
-  ARM_FLOAT_ABI_HARD
-};
-
-extern enum float_abi_type arm_float_abi;
-
 #ifndef TARGET_DEFAULT_FLOAT_ABI
 #define TARGET_DEFAULT_FLOAT_ABI ARM_FLOAT_ABI_SOFT
 #endif
 
-/* Which __fp16 format to use.
-   The enumeration values correspond to the numbering for the
-   Tag_ABI_FP_16bit_format attribute.
- */
-enum arm_fp16_format_type
-{
-  ARM_FP16_FORMAT_NONE = 0,
-  ARM_FP16_FORMAT_IEEE = 1,
-  ARM_FP16_FORMAT_ALTERNATIVE = 2
-};
-
-extern enum arm_fp16_format_type arm_fp16_format;
 #define LARGEST_EXPONENT_IS_NORMAL(bits) \
     ((bits) == 16 && arm_fp16_format == ARM_FP16_FORMAT_ALTERNATIVE)
 
-/* Which ABI to use.  */
-enum arm_abi_type
-{
-  ARM_ABI_APCS,
-  ARM_ABI_ATPCS,
-  ARM_ABI_AAPCS,
-  ARM_ABI_IWMMXT,
-  ARM_ABI_AAPCS_LINUX
-};
-
-extern enum arm_abi_type arm_abi;
-
 #ifndef ARM_DEFAULT_ABI
 #define ARM_DEFAULT_ABI ARM_ABI_APCS
 #endif
 
-/* Which thread pointer access sequence to use.  */
-enum arm_tp_type {
-  TP_AUTO,
-  TP_SOFT,
-  TP_CP15
-};
-
-extern enum arm_tp_type target_thread_pointer;
-
 /* Nonzero if this chip supports the ARM Architecture 3M extensions.  */
 extern int arm_arch3m;
 
@@ -614,7 +572,6 @@ extern int arm_arch_hwdiv;
    0020D) page 2-20 says "Structures are aligned on word boundaries".
    The AAPCS specifies a value of 8.  */
 #define STRUCTURE_SIZE_BOUNDARY arm_structure_size_boundary
-extern int arm_structure_size_boundary;
 
 /* This is the value used to initialize arm_structure_size_boundary.  If a
    particular arm target wants to change the default value it should change
diff --git a/gcc/config/arm/arm.opt b/gcc/config/arm/arm.opt
index 89c8cbd47d4722e03d53c091f8f824efb715184a..96e4b864917179d59dbb98b22fb111e97e8d346b 100644
--- a/gcc/config/arm/arm.opt
+++ b/gcc/config/arm/arm.opt
@@ -22,9 +22,28 @@ HeaderInclude
 config/arm/arm-opts.h
 
 mabi=
-Target RejectNegative Joined Var(target_abi_name)
+Target RejectNegative Joined Enum(arm_abi_type) Var(arm_abi) Init(ARM_DEFAULT_ABI)
 Specify an ABI
 
+Enum
+Name(arm_abi_type) Type(enum arm_abi_type)
+Known ARM ABIs (for use with the -mabi= option):
+
+EnumValue
+Enum(arm_abi_type) String(apcs-gnu) Value(ARM_ABI_APCS)
+
+EnumValue
+Enum(arm_abi_type) String(atpcs) Value(ARM_ABI_ATPCS)
+
+EnumValue
+Enum(arm_abi_type) String(aapcs) Value(ARM_ABI_AAPCS)
+
+EnumValue
+Enum(arm_abi_type) String(iwmmxt) Value(ARM_ABI_IWMMXT)
+
+EnumValue
+Enum(arm_abi_type) String(aapcs-linux) Value(ARM_ABI_AAPCS_LINUX)
+
 mabort-on-noreturn
 Target Report Mask(ABORT_NORETURN)
 Generate a call to abort if a noreturn function returns
@@ -76,22 +95,54 @@ Target RejectNegative Joined Enum(processor_type) Var(arm_cpu_option) Init(arm_n
 Specify the name of the target CPU
 
 mfloat-abi=
-Target RejectNegative Joined Var(target_float_abi_name)
+Target RejectNegative Joined Enum(float_abi_type) Var(arm_float_abi) Init(TARGET_DEFAULT_FLOAT_ABI)
 Specify if floating point hardware should be used
 
-mfp=
-Target RejectNegative Joined Undocumented Var(target_fpe_name)
+Enum
+Name(float_abi_type) Type(enum float_abi_type)
+Known floating-point ABIs (for use with the -mfloat-abi= option):
+
+EnumValue
+Enum(float_abi_type) String(soft) Value(ARM_FLOAT_ABI_SOFT)
+
+EnumValue
+Enum(float_abi_type) String(softfp) Value(ARM_FLOAT_ABI_SOFTFP)
+
+EnumValue
+Enum(float_abi_type) String(hard) Value(ARM_FLOAT_ABI_HARD)
+
+mfp=2
+Target RejectNegative Undocumented Alias(mfpu=, fpe2)
+
+mfp=3
+Target RejectNegative Undocumented Alias(mfpu=, fpe3)
 
 mfp16-format=
-Target RejectNegative Joined Var(target_fp16_format_name)
+Target RejectNegative Joined Enum(arm_fp16_format_type) Var(arm_fp16_format) Init(ARM_FP16_FORMAT_NONE)
 Specify the __fp16 floating-point format
 
+Enum
+Name(arm_fp16_format_type) Type(enum arm_fp16_format_type)
+Known __fp16 formats (for use with the -mfp16-format= option):
+
+EnumValue
+Enum(arm_fp16_format_type) String(none) Value(ARM_FP16_FORMAT_NONE)
+
+EnumValue
+Enum(arm_fp16_format_type) String(ieee) Value(ARM_FP16_FORMAT_IEEE)
+
+EnumValue
+Enum(arm_fp16_format_type) String(alternative) Value(ARM_FP16_FORMAT_ALTERNATIVE)
+
 ;; Now ignored.
 mfpe
 Target RejectNegative Mask(FPE) Undocumented
 
-mfpe=
-Target RejectNegative Joined Undocumented Var(target_fpe_name)
+mfpe=2
+Target RejectNegative Undocumented Alias(mfpu=, fpe2)
+
+mfpe=3
+Target RejectNegative Undocumented Alias(mfpu=, fpe3)
 
 mfpu=
 Target RejectNegative Joined Var(target_fpu_name)
@@ -128,7 +179,7 @@ msoft-float
 Target RejectNegative Alias(mfloat-abi=, soft) Undocumented
 
 mstructure-size-boundary=
-Target RejectNegative Joined Var(structure_size_string)
+Target RejectNegative Joined UInteger Var(arm_structure_size_boundary) Init(DEFAULT_STRUCTURE_SIZE_BOUNDARY)
 Specify the minimum bit alignment of structures
 
 mthumb
@@ -140,9 +191,22 @@ Target Report Mask(INTERWORK)
 Support calls between Thumb and ARM instruction sets
 
 mtp=
-Target RejectNegative Joined Var(target_thread_switch)
+Target RejectNegative Joined Enum(arm_tp_type) Var(target_thread_pointer) Init(TP_AUTO)
 Specify how to access the thread pointer
 
+Enum
+Name(arm_tp_type) Type(enum arm_tp_type)
+Valid arguments to -mtp=:
+
+EnumValue
+Enum(arm_tp_type) String(soft) Value(TP_SOFT)
+
+EnumValue
+Enum(arm_tp_type) String(auto) Value(TP_AUTO)
+
+EnumValue
+Enum(arm_tp_type) String(cp15) Value(TP_CP15)
+
 mtpcs-frame
 Target Report Mask(TPCS_FRAME)
 Thumb: Generate (non-leaf) stack frames even if not needed