ARM v6T2 - flags, ARM-instruction disassembly

Richard Earnshaw rearnsha@gcc.gnu.org
Sun Mar 13 17:32:00 GMT 2005


On Sat, 2005-03-12 at 18:23, Zack Weinberg wrote:
> Richard Earnshaw <rearnsha@gcc.gnu.org> writes:
> >> 3) Expand the variables that hold these values, to give us more room.
> >>    Lots of work, but mostly mechanical, and would make the problem go
> >>    away for the foreseeable future.
> >> 
> > This would, I think, be the best solution (or something very much like
> > this).
> 
> I am hesitant to do this mainly because I don't know where all those
> variables live, nor do I know what would be a good arrangement.

OK, the attached is a preliminary attempt at sorting this all out.  

The idea behind this change is to get us to the point where
'arm_feature_set' can be some arbitrary opaque structure that the tools
can manipulate as needed.  The type doesn't need to be known to the
tools and may not be a scalar (it still is at the moment, but the change
to make it a structure is probably the next step).

It introduces two new macros:

1) ARM_CPU_HAS_FEATURE(CPU,FEATURE)

which returns non-zero if the CPU has the requested feature.

2) ARM_MERGE_FEATURE_SETS(T,F1,F2)

Which takes two feature sets F1 & F2 (pointers to them) and fills in *T
with the union of the two sets.  T & F1 may be the same object.

There's some shenanigans that have to be played in tc-arm.c, but almost
all of this is in the command parsing code; most of the problems come
from the use of litterals.  I've addressed most of these by creating
static variables that are initialized to the appropriate litteral.  This
change isn't strictly necessary while arm_feature_set remains a scalar,
but will be needed in order to make it a compound type.

No substantive changes were needed to arm-dis.c since it doesn't
currently validate the CPU type.

Thoughts?

R.


-------------- next part --------------
? include/gdb/sim-arm.h.keep
? gas/doc/as.info
Index: include/opcode/arm.h
===================================================================
RCS file: /cvs/src/src/include/opcode/arm.h,v
retrieving revision 1.5
diff -p -r1.5 arm.h
*** include/opcode/arm.h	12 Mar 2005 18:14:05 -0000	1.5
--- include/opcode/arm.h	13 Mar 2005 17:18:36 -0000
***************
*** 75,101 ****
  #define ARM_ARCH_XSCALE	(ARM_ARCH_V5TE	| ARM_CEXT_XSCALE)
  #define ARM_ARCH_IWMMXT	(ARM_ARCH_XSCALE | ARM_CEXT_IWMMXT)
  
! #define FPU_FPA_EXT_V1	 0x80000000	/* Base FPA instruction set.  */
! #define FPU_FPA_EXT_V2	 0x40000000	/* LFM/SFM.		      */
! #define FPU_VFP_EXT_NONE 0x20000000	/* Use VFP word-ordering.     */
  #define FPU_VFP_EXT_V1xD 0x10000000	/* Base VFP instruction set.  */
  #define FPU_VFP_EXT_V1	 0x08000000	/* Double-precision insns.    */
  #define FPU_VFP_EXT_V2	 0x04000000	/* ARM10E VFPr1.	      */
  #define FPU_MAVERICK	 0x02000000	/* Cirrus Maverick.	      */
  #define FPU_NONE	 0
  
  #define FPU_ARCH_FPE	 FPU_FPA_EXT_V1
  #define FPU_ARCH_FPA	(FPU_ARCH_FPE | FPU_FPA_EXT_V2)
  
! #define FPU_ARCH_VFP       FPU_VFP_EXT_NONE
! #define FPU_ARCH_VFP_V1xD (FPU_VFP_EXT_V1xD | FPU_VFP_EXT_NONE)
  #define FPU_ARCH_VFP_V1   (FPU_ARCH_VFP_V1xD | FPU_VFP_EXT_V1)
  #define FPU_ARCH_VFP_V2	  (FPU_ARCH_VFP_V1 | FPU_VFP_EXT_V2)
  
! #define FPU_ARCH_MAVERICK  FPU_MAVERICK
  
  /* Some useful combinations:  */
  #define ARM_ANY		0x0000ffff	/* Any basic core.  */
  #define ARM_ALL		0x00ffffff	/* Any core + co-processor */
  #define CPROC_ANY	0x00ff0000	/* Any co-processor */
  #define FPU_ANY		0xff000000	/* Note this is ~ARM_ALL.  */
--- 75,117 ----
  #define ARM_ARCH_XSCALE	(ARM_ARCH_V5TE	| ARM_CEXT_XSCALE)
  #define ARM_ARCH_IWMMXT	(ARM_ARCH_XSCALE | ARM_CEXT_IWMMXT)
  
! #define FPU_ENDIAN_PURE	 0x80000000	/* Pure-endian doubles.	      */
! #define FPU_ENDIAN_BIG	 0		/* Double words-big-endian    */
! 
! #define FPU_FPA_EXT_V1	 0x40000000	/* Base FPA instruction set.  */
! #define FPU_FPA_EXT_V2	 0x20000000	/* LFM/SFM.		      */
  #define FPU_VFP_EXT_V1xD 0x10000000	/* Base VFP instruction set.  */
  #define FPU_VFP_EXT_V1	 0x08000000	/* Double-precision insns.    */
  #define FPU_VFP_EXT_V2	 0x04000000	/* ARM10E VFPr1.	      */
  #define FPU_MAVERICK	 0x02000000	/* Cirrus Maverick.	      */
  #define FPU_NONE	 0
  
+ 
+ #define FPU_VFP_EXT_NONE FPU_ENDIAN_PURE /* Use VFP word-ordering.     */
+ 
  #define FPU_ARCH_FPE	 FPU_FPA_EXT_V1
  #define FPU_ARCH_FPA	(FPU_ARCH_FPE | FPU_FPA_EXT_V2)
  
! /* Deprecated */
! #define FPU_ARCH_VFP       FPU_ENDIAN_PURE
! 
! #define FPU_ARCH_VFP_V1xD (FPU_VFP_EXT_V1xD | FPU_ENDIAN_PURE)
  #define FPU_ARCH_VFP_V1   (FPU_ARCH_VFP_V1xD | FPU_VFP_EXT_V1)
  #define FPU_ARCH_VFP_V2	  (FPU_ARCH_VFP_V1 | FPU_VFP_EXT_V2)
+ #define FPU_ARCH_VFP_HARD (FPU_VFP_EXT_V1xD | FPU_VFP_EXT_V1 | FPU_VFP_EXT_V2)
  
! #define FPU_ARCH_MAVERICK  (FPU_MAVERICK | FPU_ENDIAN_PURE)
  
  /* Some useful combinations:  */
  #define ARM_ANY		0x0000ffff	/* Any basic core.  */
  #define ARM_ALL		0x00ffffff	/* Any core + co-processor */
  #define CPROC_ANY	0x00ff0000	/* Any co-processor */
  #define FPU_ANY		0xff000000	/* Note this is ~ARM_ALL.  */
+ #define FPU_ANY_HARD	(FPU_ARCH_FPA | FPU_ARCH_VFP_HARD | FPU_ARCH_MAVERICK)
+ 
+ /* This will become a structure soon.  */
+ typedef unsigned long arm_feature_set;
+ 
+ #define ARM_CPU_HAS_FEATURE(CPU,FEAT) (((CPU) & (FEAT)) != 0)
+ 
+ #define ARM_MERGE_FEATURE_SETS(TARG,F1,F2) ((*TARG) = (*F1) | (*F2))
Index: opcodes/arm-opc.h
===================================================================
RCS file: /cvs/src/src/opcodes/arm-opc.h,v
retrieving revision 1.22
diff -p -r1.22 arm-opc.h
*** opcodes/arm-opc.h	3 Mar 2005 11:49:47 -0000	1.22
--- opcodes/arm-opc.h	13 Mar 2005 17:18:36 -0000
***************
*** 20,33 ****
  
  struct arm_opcode
  {
!   unsigned long arch;		/* Architecture defining this insn.  */
    unsigned long value, mask;	/* Recognise insn if (op&mask)==value.  */
    char *assembler;		/* How to disassemble this insn.  */
  };
  
  struct thumb_opcode
  {
!   unsigned long arch;		/* Architecture defining this insn.  */
    unsigned short value, mask;	/* Recognise insn if (op&mask)==value.  */
    char * assembler;		/* How to disassemble this insn.  */
  };
--- 20,33 ----
  
  struct arm_opcode
  {
!   arm_feature_set arch;		/* Architecture defining this insn.  */
    unsigned long value, mask;	/* Recognise insn if (op&mask)==value.  */
    char *assembler;		/* How to disassemble this insn.  */
  };
  
  struct thumb_opcode
  {
!   arm_feature_set arch;		/* Architecture defining this insn.  */
    unsigned short value, mask;	/* Recognise insn if (op&mask)==value.  */
    char * assembler;		/* How to disassemble this insn.  */
  };
Index: gas/config/tc-arm.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-arm.c,v
retrieving revision 1.194
diff -p -r1.194 tc-arm.c
*** gas/config/tc-arm.c	12 Mar 2005 18:25:46 -0000	1.194
--- gas/config/tc-arm.c	13 Mar 2005 17:18:38 -0000
***************
*** 45,52 ****
  #include "dw2gencfi.h"
  #endif
  
! /* XXX Set this to 1 after the next binutils release.  */
! #define WARN_DEPRECATED 0
  
  #ifdef OBJ_ELF
  /* Must be at least the size of the largest unwind opcode (currently two).  */
--- 45,51 ----
  #include "dw2gencfi.h"
  #endif
  
! #define WARN_DEPRECATED 1
  
  #ifdef OBJ_ELF
  /* Must be at least the size of the largest unwind opcode (currently two).  */
*************** enum arm_float_abi
*** 92,109 ****
    ARM_FLOAT_ABI_SOFT
  };
  
- /* Types of processor to assemble for.  */
- #define ARM_1		ARM_ARCH_V1
- #define ARM_2		ARM_ARCH_V2
- #define ARM_3		ARM_ARCH_V2S
- #define ARM_250		ARM_ARCH_V2S
- #define ARM_6		ARM_ARCH_V3
- #define ARM_7		ARM_ARCH_V3
- #define ARM_8		ARM_ARCH_V4
- #define ARM_9		ARM_ARCH_V4T
- #define ARM_STRONG	ARM_ARCH_V4
- #define ARM_CPU_MASK	0x0000000f              /* XXX? */
- 
  #ifndef CPU_DEFAULT
  #if defined __XSCALE__
  #define CPU_DEFAULT	(ARM_ARCH_XSCALE)
--- 91,96 ----
*************** enum arm_float_abi
*** 137,143 ****
  #define streq(a, b)           (strcmp (a, b) == 0)
  #define skip_whitespace(str)  while (*(str) == ' ') ++(str)
  
! static unsigned long cpu_variant;
  
  /* Flags stored in private area of BFD structure.  */
  static int uses_apcs_26      = FALSE;
--- 124,130 ----
  #define streq(a, b)           (strcmp (a, b) == 0)
  #define skip_whitespace(str)  while (*(str) == ' ') ++(str)
  
! static arm_feature_set cpu_variant;
  
  /* Flags stored in private area of BFD structure.  */
  static int uses_apcs_26      = FALSE;
*************** static int pic_code          = FALSE;
*** 149,162 ****
  /* Variables that we set while parsing command-line options.  Once all
     options have been read we re-process these values to set the real
     assembly flags.  */
! static int legacy_cpu = -1;
! static int legacy_fpu = -1;
  
- static int mcpu_cpu_opt = -1;
- static int mcpu_fpu_opt = -1;
- static int march_cpu_opt = -1;
- static int march_fpu_opt = -1;
- static int mfpu_opt = -1;
  static int mfloat_abi_opt = -1;
  #ifdef OBJ_ELF
  static int meabi_flags = EF_ARM_EABI_UNKNOWN;
--- 136,172 ----
  /* Variables that we set while parsing command-line options.  Once all
     options have been read we re-process these values to set the real
     assembly flags.  */
! static const arm_feature_set *legacy_cpu = NULL;
! static const arm_feature_set *legacy_fpu = NULL;
! 
! static const arm_feature_set *mcpu_cpu_opt = NULL;
! static const arm_feature_set *mcpu_fpu_opt = NULL;
! static const arm_feature_set *march_cpu_opt = NULL;
! static const arm_feature_set *march_fpu_opt = NULL;
! static const arm_feature_set *mfpu_opt = NULL;
! 
! static const arm_feature_set fpu_default = FPU_DEFAULT;
! static const arm_feature_set fpu_arch_vfp_v2 = FPU_ARCH_VFP_V2;
! static const arm_feature_set fpu_arch_fpa = FPU_ARCH_FPA;
! static const arm_feature_set fpu_any_hard = FPU_ANY_HARD;
! static const arm_feature_set fpu_arch_maverick = FPU_ARCH_MAVERICK;
! static const arm_feature_set fpu_endian_pure = FPU_ENDIAN_PURE;
! 
! static const arm_feature_set cpu_default = CPU_DEFAULT;
! static const arm_feature_set arm_ext_v1 = ARM_EXT_V1;
! static const arm_feature_set arm_ext_v2 = ARM_EXT_V1;
! static const arm_feature_set arm_ext_v2s = ARM_EXT_V2S;
! static const arm_feature_set arm_ext_v3 = ARM_EXT_V3;
! static const arm_feature_set arm_ext_v3m = ARM_EXT_V3M;
! static const arm_feature_set arm_ext_v4 = ARM_EXT_V4;
! static const arm_feature_set arm_ext_v4t = ARM_EXT_V4T;
! static const arm_feature_set arm_ext_v5 = ARM_EXT_V5;
! static const arm_feature_set arm_ext_v5e = ARM_EXT_V5E;
! 
! static const arm_feature_set arm_cext_iwmmxt = ARM_CEXT_IWMMXT;
! static const arm_feature_set arm_cext_xscale = ARM_CEXT_XSCALE;
! static const arm_feature_set arm_cext_maverick = ARM_CEXT_MAVERICK;
  
  static int mfloat_abi_opt = -1;
  #ifdef OBJ_ELF
  static int meabi_flags = EF_ARM_EABI_UNKNOWN;
*************** struct asm_opcode
*** 826,832 ****
    unsigned cond_offset;
  
    /* Which architecture variant provides this instruction.  */
!   unsigned long variant;
  
    /* Function to call to parse args.  */
    void (* parms) (char *);
--- 836,842 ----
    unsigned cond_offset;
  
    /* Which architecture variant provides this instruction.  */
!   arm_feature_set variant;
  
    /* Function to call to parse args.  */
    void (* parms) (char *);
*************** struct thumb_opcode
*** 955,961 ****
    int size;
  
    /* Which CPU variants this exists for.  */
!   unsigned long variant;
  
    /* Function to call to parse args.  */
    void (* parms) (char *);
--- 965,971 ----
    int size;
  
    /* Which CPU variants this exists for.  */
!   arm_feature_set variant;
  
    /* Function to call to parse args.  */
    void (* parms) (char *);
*************** opcode_select (int width)
*** 1471,1477 ****
      case 16:
        if (! thumb_mode)
  	{
! 	  if (! (cpu_variant & ARM_EXT_V4T))
  	    as_bad (_("selected processor does not support THUMB opcodes"));
  
  	  thumb_mode = 1;
--- 1481,1487 ----
      case 16:
        if (! thumb_mode)
  	{
! 	  if (! ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v4t))
  	    as_bad (_("selected processor does not support THUMB opcodes"));
  
  	  thumb_mode = 1;
*************** opcode_select (int width)
*** 1485,1491 ****
      case 32:
        if (thumb_mode)
  	{
! 	  if ((cpu_variant & ARM_ALL) == ARM_EXT_V4T)
  	    as_bad (_("selected processor does not support ARM opcodes"));
  
  	  thumb_mode = 0;
--- 1495,1501 ----
      case 32:
        if (thumb_mode)
  	{
! 	  if (! ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v1))
  	    as_bad (_("selected processor does not support ARM opcodes"));
  
  	  thumb_mode = 0;
*************** md_begin (void)
*** 10990,11040 ****
       -mcpu= over -march= if both are set (as for GCC); and we prefer
       -mfpu= over any other way of setting the floating point unit.
       Use of legacy options with new options are faulted.  */
!   if (legacy_cpu != -1)
      {
!       if (mcpu_cpu_opt != -1 || march_cpu_opt != -1)
  	as_bad (_("use of old and new-style options to set CPU type"));
  
        mcpu_cpu_opt = legacy_cpu;
      }
!   else if (mcpu_cpu_opt == -1)
      mcpu_cpu_opt = march_cpu_opt;
  
!   if (legacy_fpu != -1)
      {
!       if (mfpu_opt != -1)
  	as_bad (_("use of old and new-style options to set FPU type"));
  
        mfpu_opt = legacy_fpu;
      }
!   else if (mfpu_opt == -1)
      {
  #if !(defined (TE_LINUX) || defined (TE_NetBSD) || defined (TE_VXWORKS)) 
        /* Some environments specify a default FPU.  If they don't, infer it
  	 from the processor.  */
!       if (mcpu_fpu_opt != -1)
  	mfpu_opt = mcpu_fpu_opt;
        else
  	mfpu_opt = march_fpu_opt;
  #else
!       mfpu_opt = FPU_DEFAULT;
  #endif
      }
  
!   if (mfpu_opt == -1)
      {
!       if (mcpu_cpu_opt == -1)
! 	mfpu_opt = FPU_DEFAULT;
!       else if (mcpu_cpu_opt & ARM_EXT_V5)
! 	mfpu_opt = FPU_ARCH_VFP_V2;
        else
! 	mfpu_opt = FPU_ARCH_FPA;
      }
  
!   if (mcpu_cpu_opt == -1)
!     mcpu_cpu_opt = CPU_DEFAULT;
  
!   cpu_variant = mcpu_cpu_opt | mfpu_opt;
  
  #if defined OBJ_COFF || defined OBJ_ELF
    {
--- 11000,11050 ----
       -mcpu= over -march= if both are set (as for GCC); and we prefer
       -mfpu= over any other way of setting the floating point unit.
       Use of legacy options with new options are faulted.  */
!   if (legacy_cpu != NULL)
      {
!       if (mcpu_cpu_opt != NULL || march_cpu_opt != NULL)
  	as_bad (_("use of old and new-style options to set CPU type"));
  
        mcpu_cpu_opt = legacy_cpu;
      }
!   else if (mcpu_cpu_opt == NULL)
      mcpu_cpu_opt = march_cpu_opt;
  
!   if (legacy_fpu != NULL)
      {
!       if (mfpu_opt != NULL)
  	as_bad (_("use of old and new-style options to set FPU type"));
  
        mfpu_opt = legacy_fpu;
      }
!   else if (mfpu_opt == NULL)
      {
  #if !(defined (TE_LINUX) || defined (TE_NetBSD) || defined (TE_VXWORKS)) 
        /* Some environments specify a default FPU.  If they don't, infer it
  	 from the processor.  */
!       if (mcpu_fpu_opt != NULL)
  	mfpu_opt = mcpu_fpu_opt;
        else
  	mfpu_opt = march_fpu_opt;
  #else
!       mfpu_opt = &fpu_default;
  #endif
      }
  
!   if (mfpu_opt == NULL)
      {
!       if (mcpu_cpu_opt == NULL)
! 	mfpu_opt = &fpu_default;
!       else if (ARM_CPU_HAS_FEATURE (*mcpu_cpu_opt, arm_ext_v5))
! 	mfpu_opt = &fpu_arch_vfp_v2;
        else
! 	mfpu_opt = &fpu_arch_fpa;
      }
  
!   if (mcpu_cpu_opt == NULL)
!     mcpu_cpu_opt = &cpu_default;
  
!   ARM_MERGE_FEATURE_SETS (&cpu_variant, mcpu_cpu_opt, mfpu_opt);
  
  #if defined OBJ_COFF || defined OBJ_ELF
    {
*************** md_begin (void)
*** 11052,11059 ****
  	if (support_interwork) flags |= F_INTERWORK;
  	if (uses_apcs_float)   flags |= F_APCS_FLOAT;
  	if (pic_code)          flags |= F_PIC;
! 	if ((cpu_variant & FPU_ANY) == FPU_NONE
! 	     || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only.  */
  	  flags |= F_SOFT_FLOAT;
  
  	switch (mfloat_abi_opt)
--- 11062,11068 ----
  	if (support_interwork) flags |= F_INTERWORK;
  	if (uses_apcs_float)   flags |= F_APCS_FLOAT;
  	if (pic_code)          flags |= F_PIC;
! 	if (! ARM_CPU_HAS_FEATURE (cpu_variant, fpu_any_hard))
  	  flags |= F_SOFT_FLOAT;
  
  	switch (mfloat_abi_opt)
*************** md_begin (void)
*** 11069,11080 ****
  	    break;
  	  }
  
! 	/* Using VFP conventions (even if soft-float).  */
! 	if (cpu_variant & FPU_VFP_EXT_NONE)
  	  flags |= F_VFP_FLOAT;
  
  #if defined OBJ_ELF
! 	if (cpu_variant & FPU_ARCH_MAVERICK)
  	    flags |= EF_ARM_MAVERICK_FLOAT;
  	break;
  
--- 11078,11089 ----
  	    break;
  	  }
  
! 	/* Using pure-endian doubles (even if soft-float).  */
! 	if (ARM_CPU_HAS_FEATURE (cpu_variant, fpu_endian_pure))
  	  flags |= F_VFP_FLOAT;
  
  #if defined OBJ_ELF
! 	if (ARM_CPU_HAS_FEATURE (cpu_variant, fpu_arch_maverick))
  	    flags |= EF_ARM_MAVERICK_FLOAT;
  	break;
  
*************** md_begin (void)
*** 11109,11158 ****
  #endif
  
    /* Record the CPU type as well.  */
-   switch (cpu_variant & ARM_CPU_MASK)
-     {
-     case ARM_2:
-       mach = bfd_mach_arm_2;
-       break;
- 
-     case ARM_3: 		/* Also ARM_250.  */
-       mach = bfd_mach_arm_2a;
-       break;
- 
-     case ARM_6:			/* Also ARM_7.  */
-       mach = bfd_mach_arm_3;
-       break;
- 
-     default:
-       mach = bfd_mach_arm_unknown;
-       break;
-     }
- 
    /* Catch special cases.  */
!   if (cpu_variant & ARM_CEXT_IWMMXT)
      mach = bfd_mach_arm_iWMMXt;
!   else if (cpu_variant & ARM_CEXT_XSCALE)
      mach = bfd_mach_arm_XScale;
!   else if (cpu_variant & ARM_CEXT_MAVERICK)
      mach = bfd_mach_arm_ep9312;
!   else if (cpu_variant & ARM_EXT_V5E)
      mach = bfd_mach_arm_5TE;
!   else if (cpu_variant & ARM_EXT_V5)
      {
!       if (cpu_variant & ARM_EXT_V4T)
  	mach = bfd_mach_arm_5T;
        else
  	mach = bfd_mach_arm_5;
      }
!   else if (cpu_variant & ARM_EXT_V4)
      {
!       if (cpu_variant & ARM_EXT_V4T)
  	mach = bfd_mach_arm_4T;
        else
  	mach = bfd_mach_arm_4;
      }
!   else if (cpu_variant & ARM_EXT_V3M)
      mach = bfd_mach_arm_3M;
  
    bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
  }
--- 11118,11156 ----
  #endif
  
    /* Record the CPU type as well.  */
    /* Catch special cases.  */
!   if (ARM_CPU_HAS_FEATURE (cpu_variant, arm_cext_iwmmxt))
      mach = bfd_mach_arm_iWMMXt;
!   else if (ARM_CPU_HAS_FEATURE (cpu_variant, arm_cext_xscale))
      mach = bfd_mach_arm_XScale;
!   else if (ARM_CPU_HAS_FEATURE (cpu_variant, arm_cext_maverick))
      mach = bfd_mach_arm_ep9312;
!   else if (ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v5e))
      mach = bfd_mach_arm_5TE;
!   else if (ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v5))
      {
!       if (ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v4t))
  	mach = bfd_mach_arm_5T;
        else
  	mach = bfd_mach_arm_5;
      }
!   else if (ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v4))
      {
!       if (ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v4t))
  	mach = bfd_mach_arm_4T;
        else
  	mach = bfd_mach_arm_4;
      }
!   else if (ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v3m))
      mach = bfd_mach_arm_3M;
+   else if (ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v3))
+     mach = bfd_mach_arm_3;
+   else if (ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v2s))
+     mach = bfd_mach_arm_2a;
+   else if (ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v2))
+     mach = bfd_mach_arm_2;
+   else
+     mach = bfd_mach_arm_unknown;
  
    bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
  }
*************** md_atof (int type, char * litP, int * si
*** 11267,11273 ****
      }
    else
      {
!       if (cpu_variant & FPU_ARCH_VFP)
  	for (i = prec - 1; i >= 0; i--)
  	  {
  	    md_number_to_chars (litP, (valueT) words[i], 2);
--- 11265,11271 ----
      }
    else
      {
!       if (ARM_CPU_HAS_FEATURE (cpu_variant, FPU_ARCH_VFP))
  	for (i = prec - 1; i >= 0; i--)
  	  {
  	    md_number_to_chars (litP, (valueT) words[i], 2);
*************** md_assemble (char * str)
*** 12361,12367 ****
        if (opcode)
  	{
  	  /* Check that this instruction is supported for this CPU.  */
! 	  if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
  	    {
  	      as_bad (_("selected processor does not support `%s'"), str);
  	      return;
--- 12359,12366 ----
        if (opcode)
  	{
  	  /* Check that this instruction is supported for this CPU.  */
! 	  if (thumb_mode == 1
! 	      && ! ARM_CPU_HAS_FEATURE (cpu_variant, opcode->variant))
  	    {
  	      as_bad (_("selected processor does not support `%s'"), str);
  	      return;
*************** md_assemble (char * str)
*** 12387,12393 ****
        if (opcode)
  	{
  	  /* Check that this instruction is supported for this CPU.  */
! 	  if ((opcode->variant & cpu_variant) == 0)
  	    {
  	      as_bad (_("selected processor does not support `%s'"), str);
  	      return;
--- 12386,12392 ----
        if (opcode)
  	{
  	  /* Check that this instruction is supported for this CPU.  */
! 	  if (! ARM_CPU_HAS_FEATURE (cpu_variant, opcode->variant))
  	    {
  	      as_bad (_("selected processor does not support `%s'"), str);
  	      return;
*************** struct arm_option_table arm_opts[] =
*** 12525,12531 ****
--- 12524,12545 ----
    /* These are recognized by the assembler, but have no affect on code.  */
    {"mapcs-frame", N_("use frame pointer"), NULL, 0, NULL},
    {"mapcs-stack-check", N_("use stack size checking"), NULL, 0, NULL},
+   {NULL, NULL, NULL, 0, NULL}
+ };
+ 
  
+ 
+ struct arm_feature_option_table
+ {
+   char *option;			/* Option name to match.  */
+   char *help;			/* Help information.  */
+   const arm_feature_set **var;	/* Variable to change.  */
+   const arm_feature_set value;	/* What to change it to.  */
+   char *deprecated;		/* If non-null, print this message.  */
+ };
+ 
+ const struct arm_feature_option_table arm_feature_opts[] =
+ {
    /* DON'T add any new processors to this list -- we want the whole list
       to go away...  Add them to the processors table instead.  */
    {"marm1",	 NULL, &legacy_cpu, ARM_ARCH_V1,  N_("use -mcpu=arm1")},
*************** struct arm_option_table arm_opts[] =
*** 12640,12654 ****
  struct arm_cpu_option_table
  {
    char *name;
!   int   value;
    /* For some CPUs we assume an FPU unless the user explicitly sets
       -mfpu=...  */
!   int   default_fpu;
  };
  
  /* This list should, at a minimum, contain all the cpu names
     recognized by GCC.  */
! static struct arm_cpu_option_table arm_cpus[] =
  {
    {"all",		ARM_ANY,	 FPU_ARCH_FPA},
    {"arm1",		ARM_ARCH_V1,	 FPU_ARCH_FPA},
--- 12654,12668 ----
  struct arm_cpu_option_table
  {
    char *name;
!   const arm_feature_set value;
    /* For some CPUs we assume an FPU unless the user explicitly sets
       -mfpu=...  */
!   const arm_feature_set default_fpu;
  };
  
  /* This list should, at a minimum, contain all the cpu names
     recognized by GCC.  */
! static const struct arm_cpu_option_table arm_cpus[] =
  {
    {"all",		ARM_ANY,	 FPU_ARCH_FPA},
    {"arm1",		ARM_ARCH_V1,	 FPU_ARCH_FPA},
*************** static struct arm_cpu_option_table arm_c
*** 12733,12745 ****
  struct arm_arch_option_table
  {
    char *name;
!   int   value;
!   int   default_fpu;
  };
  
  /* This list should, at a minimum, contain all the architecture names
     recognized by GCC.  */
! static struct arm_arch_option_table arm_archs[] =
  {
    {"all",		ARM_ANY,	 FPU_ARCH_FPA},
    {"armv1",		ARM_ARCH_V1,	 FPU_ARCH_FPA},
--- 12747,12759 ----
  struct arm_arch_option_table
  {
    char *name;
!   const arm_feature_set value;
!   const arm_feature_set default_fpu;
  };
  
  /* This list should, at a minimum, contain all the architecture names
     recognized by GCC.  */
! static const struct arm_arch_option_table arm_archs[] =
  {
    {"all",		ARM_ANY,	 FPU_ARCH_FPA},
    {"armv1",		ARM_ARCH_V1,	 FPU_ARCH_FPA},
*************** static struct arm_arch_option_table arm_
*** 12772,12781 ****
  struct arm_arch_extension_table
  {
    char *name;
!   int value;
  };
  
! static struct arm_arch_extension_table arm_extensions[] =
  {
    {"maverick",		ARM_CEXT_MAVERICK},
    {"xscale",		ARM_CEXT_XSCALE},
--- 12786,12795 ----
  struct arm_arch_extension_table
  {
    char *name;
!   const arm_feature_set value;
  };
  
! static const struct arm_arch_extension_table arm_extensions[] =
  {
    {"maverick",		ARM_CEXT_MAVERICK},
    {"xscale",		ARM_CEXT_XSCALE},
*************** static struct arm_arch_extension_table a
*** 12786,12797 ****
  struct arm_fpu_option_table
  {
    char *name;
!   int   value;
  };
  
  /* This list should, at a minimum, contain all the fpu names
     recognized by GCC.  */
! static struct arm_fpu_option_table arm_fpus[] =
  {
    {"softfpa",		FPU_NONE},
    {"fpe",		FPU_ARCH_FPE},
--- 12800,12811 ----
  struct arm_fpu_option_table
  {
    char *name;
!   const arm_feature_set value;
  };
  
  /* This list should, at a minimum, contain all the fpu names
     recognized by GCC.  */
! static const struct arm_fpu_option_table arm_fpus[] =
  {
    {"softfpa",		FPU_NONE},
    {"fpe",		FPU_ARCH_FPE},
*************** static struct arm_eabi_option_table arm_
*** 12848,12865 ****
  
  struct arm_long_option_table
  {
!   char * option;		/* Substring to match.  */
!   char * help;			/* Help information.  */
!   int (* func) (char * subopt);	/* Function to decode sub-option.  */
!   char * deprecated;		/* If non-null, print this message.  */
  };
  
  static int
! arm_parse_extension (char * str, int * opt_p)
  {
    while (str != NULL && *str != 0)
      {
!       struct arm_arch_extension_table * opt;
        char * ext;
        int optlen;
  
--- 12862,12885 ----
  
  struct arm_long_option_table
  {
!   char *option;			/* Substring to match.  */
!   char *help;			/* Help information.  */
!   int (*func) (char *subopt);	/* Function to decode sub-option.  */
!   char *deprecated;		/* If non-null, print this message.  */
  };
  
  static int
! arm_parse_extension (char *str, const arm_feature_set **opt_p)
  {
+   arm_feature_set *ext_set = xmalloc (sizeof (arm_feature_set));
+ 
+   /* Copy the feature set, so that we can modify it.  */
+   *ext_set = **opt_p;
+   *opt_p = ext_set;
+ 
    while (str != NULL && *str != 0)
      {
!       const struct arm_arch_extension_table * opt;
        char * ext;
        int optlen;
  
*************** arm_parse_extension (char * str, int * o
*** 12886,12892 ****
        for (opt = arm_extensions; opt->name != NULL; opt++)
  	if (strncmp (opt->name, str, optlen) == 0)
  	  {
! 	    *opt_p |= opt->value;
  	    break;
  	  }
  
--- 12906,12912 ----
        for (opt = arm_extensions; opt->name != NULL; opt++)
  	if (strncmp (opt->name, str, optlen) == 0)
  	  {
! 	    ARM_MERGE_FEATURE_SETS (ext_set, ext_set, &opt->value);
  	    break;
  	  }
  
*************** arm_parse_extension (char * str, int * o
*** 12905,12911 ****
  static int
  arm_parse_cpu (char * str)
  {
!   struct arm_cpu_option_table * opt;
    char * ext = strchr (str, '+');
    int optlen;
  
--- 12925,12931 ----
  static int
  arm_parse_cpu (char * str)
  {
!   const struct arm_cpu_option_table * opt;
    char * ext = strchr (str, '+');
    int optlen;
  
*************** arm_parse_cpu (char * str)
*** 12923,12930 ****
    for (opt = arm_cpus; opt->name != NULL; opt++)
      if (strncmp (opt->name, str, optlen) == 0)
        {
! 	mcpu_cpu_opt = opt->value;
! 	mcpu_fpu_opt = opt->default_fpu;
  
  	if (ext != NULL)
  	  return arm_parse_extension (ext, &mcpu_cpu_opt);
--- 12943,12950 ----
    for (opt = arm_cpus; opt->name != NULL; opt++)
      if (strncmp (opt->name, str, optlen) == 0)
        {
! 	mcpu_cpu_opt = &opt->value;
! 	mcpu_fpu_opt = &opt->default_fpu;
  
  	if (ext != NULL)
  	  return arm_parse_extension (ext, &mcpu_cpu_opt);
*************** arm_parse_cpu (char * str)
*** 12939,12945 ****
  static int
  arm_parse_arch (char * str)
  {
!   struct arm_arch_option_table *opt;
    char *ext = strchr (str, '+');
    int optlen;
  
--- 12959,12965 ----
  static int
  arm_parse_arch (char * str)
  {
!   const struct arm_arch_option_table *opt;
    char *ext = strchr (str, '+');
    int optlen;
  
*************** arm_parse_arch (char * str)
*** 12958,12965 ****
    for (opt = arm_archs; opt->name != NULL; opt++)
      if (streq (opt->name, str))
        {
! 	march_cpu_opt = opt->value;
! 	march_fpu_opt = opt->default_fpu;
  
  	if (ext != NULL)
  	  return arm_parse_extension (ext, &march_cpu_opt);
--- 12978,12985 ----
    for (opt = arm_archs; opt->name != NULL; opt++)
      if (streq (opt->name, str))
        {
! 	march_cpu_opt = &opt->value;
! 	march_fpu_opt = &opt->default_fpu;
  
  	if (ext != NULL)
  	  return arm_parse_extension (ext, &march_cpu_opt);
*************** arm_parse_arch (char * str)
*** 12974,12985 ****
  static int
  arm_parse_fpu (char * str)
  {
!   struct arm_fpu_option_table * opt;
  
    for (opt = arm_fpus; opt->name != NULL; opt++)
      if (streq (opt->name, str))
        {
! 	mfpu_opt = opt->value;
  	return 1;
        }
  
--- 12994,13005 ----
  static int
  arm_parse_fpu (char * str)
  {
!   const struct arm_fpu_option_table * opt;
  
    for (opt = arm_fpus; opt->name != NULL; opt++)
      if (streq (opt->name, str))
        {
! 	mfpu_opt = &opt->value;
  	return 1;
        }
  
*************** int
*** 13041,13046 ****
--- 13061,13067 ----
  md_parse_option (int c, char * arg)
  {
    struct arm_option_table *opt;
+   const struct arm_feature_option_table *fopt;
    struct arm_long_option_table *lopt;
  
    switch (c)
*************** md_parse_option (int c, char * arg)
*** 13083,13088 ****
--- 13104,13129 ----
  	    }
  	}
  
+       for (fopt = arm_feature_opts; fopt->option != NULL; fopt++)
+ 	{
+ 	  if (c == fopt->option[0]
+ 	      && ((arg == NULL && fopt->option[1] == 0)
+ 		  || streq (arg, fopt->option + 1)))
+ 	    {
+ #if WARN_DEPRECATED
+ 	      /* If the option is deprecated, tell the user.  */
+ 	      if (fopt->deprecated != NULL)
+ 		as_tsktsk (_("option `-%c%s' is deprecated: %s"), c,
+ 			   arg ? arg : "", _(fopt->deprecated));
+ #endif
+ 
+ 	      if (fopt->var != NULL)
+ 		*fopt->var = &fopt->value;
+ 
+ 	      return 1;
+ 	    }
+ 	}
+ 
        for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
  	{
  	  /* These options are expected to have an argument.  */


More information about the Binutils mailing list