[Arm] Remove dead FPA code

Message ID 20220920123012.189293-1-luis.machado@arm.com
State New
Headers
Series [Arm] Remove dead FPA code |

Commit Message

Luis Machado Sept. 20, 2022, 12:30 p.m. UTC
  FPA has been deprecated for a while now. It was removed from GCC in 2012,
but somehow it managed to survive in GDB for a little while longer.

It is time to let FPA rest in peace.

While at it, make VFP the default floating point model for 32-bit Arm.

It would be nice to get some *BSD testing as some changes touch that code
and I'm not properly setup to validate the changes for those OS'.
---
 gdb/NEWS                                    |   4 +
 gdb/aarch64-linux-nat.c                     |   4 +-
 gdb/arch/arm.c                              |   5 -
 gdb/arch/arm.h                              |   9 -
 gdb/arm-bsd-tdep.c                          |  48 ----
 gdb/arm-linux-nat.c                         | 106 +-------
 gdb/arm-linux-tdep.c                        | 131 +--------
 gdb/arm-linux-tdep.h                        |  29 --
 gdb/arm-netbsd-nat.c                        |   4 +-
 gdb/arm-tdep.c                              | 286 +-------------------
 gdb/arm-tdep.h                              |   3 -
 gdb/doc/gdb.texinfo                         |  13 +-
 gdb/features/Makefile                       |   2 -
 gdb/features/arm/arm-fpa.c                  |  23 --
 gdb/features/arm/arm-fpa.xml                |  23 --
 gdb/features/arm/arm-m-profile-with-fpa.c   |  39 ---
 gdb/features/arm/arm-m-profile-with-fpa.xml |  39 ---
 gdb/target-descriptions.c                   |   4 -
 gdb/testsuite/gdb.base/long_long.exp        |  18 +-
 gdbserver/linux-arm-low.cc                  |   7 +-
 gdbsupport/tdesc.cc                         |   1 -
 gdbsupport/tdesc.h                          |   1 -
 22 files changed, 33 insertions(+), 766 deletions(-)
 delete mode 100644 gdb/features/arm/arm-fpa.c
 delete mode 100644 gdb/features/arm/arm-fpa.xml
 delete mode 100644 gdb/features/arm/arm-m-profile-with-fpa.c
 delete mode 100644 gdb/features/arm/arm-m-profile-with-fpa.xml
  

Comments

Eli Zaretskii Sept. 20, 2022, 12:47 p.m. UTC | #1
> Date: Tue, 20 Sep 2022 13:30:12 +0100
> From: Luis Machado via Gdb-patches <gdb-patches@sourceware.org>
> 
> FPA has been deprecated for a while now. It was removed from GCC in 2012,
> but somehow it managed to survive in GDB for a little while longer.
> 
> It is time to let FPA rest in peace.
> 
> While at it, make VFP the default floating point model for 32-bit Arm.
> 
> It would be nice to get some *BSD testing as some changes touch that code
> and I'm not properly setup to validate the changes for those OS'.
> ---
>  gdb/NEWS                                    |   4 +
>  gdb/aarch64-linux-nat.c                     |   4 +-
>  gdb/arch/arm.c                              |   5 -
>  gdb/arch/arm.h                              |   9 -
>  gdb/arm-bsd-tdep.c                          |  48 ----
>  gdb/arm-linux-nat.c                         | 106 +-------
>  gdb/arm-linux-tdep.c                        | 131 +--------
>  gdb/arm-linux-tdep.h                        |  29 --
>  gdb/arm-netbsd-nat.c                        |   4 +-
>  gdb/arm-tdep.c                              | 286 +-------------------
>  gdb/arm-tdep.h                              |   3 -
>  gdb/doc/gdb.texinfo                         |  13 +-
>  gdb/features/Makefile                       |   2 -
>  gdb/features/arm/arm-fpa.c                  |  23 --
>  gdb/features/arm/arm-fpa.xml                |  23 --
>  gdb/features/arm/arm-m-profile-with-fpa.c   |  39 ---
>  gdb/features/arm/arm-m-profile-with-fpa.xml |  39 ---
>  gdb/target-descriptions.c                   |   4 -
>  gdb/testsuite/gdb.base/long_long.exp        |  18 +-
>  gdbserver/linux-arm-low.cc                  |   7 +-
>  gdbsupport/tdesc.cc                         |   1 -
>  gdbsupport/tdesc.h                          |   1 -
>  22 files changed, 33 insertions(+), 766 deletions(-)
>  delete mode 100644 gdb/features/arm/arm-fpa.c
>  delete mode 100644 gdb/features/arm/arm-fpa.xml
>  delete mode 100644 gdb/features/arm/arm-m-profile-with-fpa.c
>  delete mode 100644 gdb/features/arm/arm-m-profile-with-fpa.xml

OK for the NEWS part, thanks.
  
Enze Li Oct. 2, 2022, 1:39 p.m. UTC | #2
On Tue, Sep 20 2022 at 01:30:12 PM +0100, Luis Machado via Gdb-patches wrote:

> FPA has been deprecated for a while now. It was removed from GCC in 2012,
> but somehow it managed to survive in GDB for a little while longer.
>
> It is time to let FPA rest in peace.
>
> While at it, make VFP the default floating point model for 32-bit Arm.
>
> It would be nice to get some *BSD testing as some changes touch that code
> and I'm not properly setup to validate the changes for those OS'.

Hi Luis,

I have tested this patch on FreeBSD, NetBSD and OpenBSD and found no
build errors.  All these tests are based on this commit[1].

[1] 6519cd1a15fda2b67ae3e4ad8a2758615d3e0f9f

Thanks,
Enze

> ---
>  gdb/NEWS                                    |   4 +
>  gdb/aarch64-linux-nat.c                     |   4 +-
>  gdb/arch/arm.c                              |   5 -
>  gdb/arch/arm.h                              |   9 -
>  gdb/arm-bsd-tdep.c                          |  48 ----
>  gdb/arm-linux-nat.c                         | 106 +-------
>  gdb/arm-linux-tdep.c                        | 131 +--------
>  gdb/arm-linux-tdep.h                        |  29 --
>  gdb/arm-netbsd-nat.c                        |   4 +-
>  gdb/arm-tdep.c                              | 286 +-------------------
>  gdb/arm-tdep.h                              |   3 -
>  gdb/doc/gdb.texinfo                         |  13 +-
>  gdb/features/Makefile                       |   2 -
>  gdb/features/arm/arm-fpa.c                  |  23 --
>  gdb/features/arm/arm-fpa.xml                |  23 --
>  gdb/features/arm/arm-m-profile-with-fpa.c   |  39 ---
>  gdb/features/arm/arm-m-profile-with-fpa.xml |  39 ---
>  gdb/target-descriptions.c                   |   4 -
>  gdb/testsuite/gdb.base/long_long.exp        |  18 +-
>  gdbserver/linux-arm-low.cc                  |   7 +-
>  gdbsupport/tdesc.cc                         |   1 -
>  gdbsupport/tdesc.h                          |   1 -
>  22 files changed, 33 insertions(+), 766 deletions(-)
>  delete mode 100644 gdb/features/arm/arm-fpa.c
>  delete mode 100644 gdb/features/arm/arm-fpa.xml
>  delete mode 100644 gdb/features/arm/arm-m-profile-with-fpa.c
>  delete mode 100644 gdb/features/arm/arm-m-profile-with-fpa.xml
>
> diff --git a/gdb/NEWS b/gdb/NEWS
> index 555ef2ddf77..fcd7b686e02 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -3,6 +3,10 @@
>  
>  *** Changes since GDB 12
>  
> +* Removed support for the 32-bit Arm FPA floating point format.  FPA is an
> +  old floating point format that is no longer supported in GCC since at least
> +  2012.
> +
>  * GDB now supports dumping memory tag data for AArch64 MTE.  It also supports
>    reading memory tag data for AArch64 MTE from core files generated by
>    the gcore command or the Linux kernel.
> diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c
> index eda79ec6d35..4d36cd47567 100644
> --- a/gdb/aarch64-linux-nat.c
> +++ b/gdb/aarch64-linux-nat.c
> @@ -551,7 +551,7 @@ aarch32_fetch_registers (struct regcache *regcache, int regno)
>        if (tdep->vfp_register_count > 0)
>  	fetch_fpregs_from_thread (regcache);
>      }
> -  else if (regno < ARM_F0_REGNUM || regno == ARM_PS_REGNUM)
> +  else if (regno <= ARM_PC_REGNUM || regno == ARM_PS_REGNUM)
>      fetch_gregs_from_thread (regcache);
>    else if (tdep->vfp_register_count > 0
>  	   && regno >= ARM_D0_REGNUM
> @@ -627,7 +627,7 @@ aarch32_store_registers (struct regcache *regcache, int regno)
>        if (tdep->vfp_register_count > 0)
>  	store_fpregs_to_thread (regcache);
>      }
> -  else if (regno < ARM_F0_REGNUM || regno == ARM_PS_REGNUM)
> +  else if (regno <= ARM_PC_REGNUM || regno == ARM_PS_REGNUM)
>      store_gregs_to_thread (regcache);
>    else if (tdep->vfp_register_count > 0
>  	   && regno >= ARM_D0_REGNUM
> diff --git a/gdb/arch/arm.c b/gdb/arch/arm.c
> index 14f0a7a7f6c..9771a60f30f 100644
> --- a/gdb/arch/arm.c
> +++ b/gdb/arch/arm.c
> @@ -27,7 +27,6 @@
>  #include "../features/arm/arm-vfpv3.c"
>  #include "../features/arm/xscale-iwmmxt.c"
>  #include "../features/arm/arm-m-profile.c"
> -#include "../features/arm/arm-m-profile-with-fpa.c"
>  #include "../features/arm/arm-m-profile-mve.c"
>  #include "../features/arm/arm-m-system.c"
>  
> @@ -441,10 +440,6 @@ arm_create_mprofile_target_description (arm_m_profile_type m_type)
>        regnum = create_feature_arm_arm_vfpv2 (tdesc, regnum);
>        break;
>  
> -    case ARM_M_TYPE_WITH_FPA:
> -      regnum = create_feature_arm_arm_m_profile_with_fpa (tdesc, regnum);
> -      break;
> -
>      case ARM_M_TYPE_MVE:
>        regnum = create_feature_arm_arm_m_profile (tdesc, regnum);
>        regnum = create_feature_arm_arm_vfpv2 (tdesc, regnum);
> diff --git a/gdb/arch/arm.h b/gdb/arch/arm.h
> index 36757493406..74a6ba93bc7 100644
> --- a/gdb/arch/arm.h
> +++ b/gdb/arch/arm.h
> @@ -44,11 +44,6 @@ enum gdb_regnum {
>    ARM_SP_REGNUM = 13,		/* Contains address of top of stack */
>    ARM_LR_REGNUM = 14,		/* address to return to from a function call */
>    ARM_PC_REGNUM = 15,		/* Contains program counter */
> -  /* F0..F7 are the fp registers for the (obsolete) FPA architecture.  */
> -  ARM_F0_REGNUM = 16,		/* first floating point register */
> -  ARM_F3_REGNUM = 19,		/* last floating point argument register */
> -  ARM_F7_REGNUM = 23, 		/* last floating point register */
> -  ARM_FPS_REGNUM = 24,		/* floating point status register */
>    ARM_PS_REGNUM = 25,		/* Contains processor status */
>    ARM_WR0_REGNUM,		/* WMMX data registers.  */
>    ARM_WR15_REGNUM = ARM_WR0_REGNUM + 15,
> @@ -67,7 +62,6 @@ enum gdb_regnum {
>    ARM_FP_REGNUM = 11,		/* Frame register in ARM code, if used.  */
>    THUMB_FP_REGNUM = 7,		/* Frame register in Thumb code, if used.  */
>    ARM_LAST_ARG_REGNUM = ARM_A4_REGNUM,
> -  ARM_LAST_FP_ARG_REGNUM = ARM_F3_REGNUM
>  };
>  
>  /* Register count constants.  */
> @@ -103,7 +97,6 @@ enum arm_fp_type {
>  enum arm_m_profile_type {
>     ARM_M_TYPE_M_PROFILE,
>     ARM_M_TYPE_VFP_D16,
> -   ARM_M_TYPE_WITH_FPA,
>     ARM_M_TYPE_MVE,
>     ARM_M_TYPE_SYSTEM,
>     ARM_M_TYPE_INVALID
> @@ -157,8 +150,6 @@ enum system_register_address : CORE_ADDR
>  
>  /* r0-r12,sp,lr,pc,cpsr.  */
>  #define ARM_CORE_REGS_SIZE (17 * ARM_INT_REGISTER_SIZE)
> -/* f0-f8,fps.  */
> -#define ARM_FP_REGS_SIZE (8 * ARM_FP_REGISTER_SIZE + ARM_INT_REGISTER_SIZE)
>  /* d0-d15,fpscr.  */
>  #define ARM_VFP2_REGS_SIZE (16 * ARM_VFP_REGISTER_SIZE + ARM_INT_REGISTER_SIZE)
>  /* d0-d31,fpscr.  */
> diff --git a/gdb/arm-bsd-tdep.c b/gdb/arm-bsd-tdep.c
> index 13d6e527d58..72421bb26d5 100644
> --- a/gdb/arm-bsd-tdep.c
> +++ b/gdb/arm-bsd-tdep.c
> @@ -29,39 +29,6 @@
>  /* Sizeof `struct reg' in <machine/reg.h>.  */
>  #define ARMBSD_SIZEOF_GREGS	(17 * 4)
>  
> -/* Sizeof `struct fpreg' in <machine/reg.h.  */
> -#define ARMBSD_SIZEOF_FPREGS	((1 + (8 * 3)) * 4)
> -
> -static int
> -armbsd_fpreg_offset (int regnum)
> -{
> -  if (regnum == ARM_FPS_REGNUM)
> -    return 0;
> -
> -  return 4 + (regnum - ARM_F0_REGNUM) * 12;
> -}
> -
> -/* Supply register REGNUM from the buffer specified by FPREGS and LEN
> -   in the floating-point register set REGSET to register cache
> -   REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
> -
> -static void
> -armbsd_supply_fpregset (const struct regset *regset,
> -			struct regcache *regcache,
> -			int regnum, const void *fpregs, size_t len)
> -{
> -  const gdb_byte *regs = (const gdb_byte *) fpregs;
> -  int i;
> -
> -  gdb_assert (len >= ARMBSD_SIZEOF_FPREGS);
> -
> -  for (i = ARM_F0_REGNUM; i <= ARM_FPS_REGNUM; i++)
> -    {
> -      if (regnum == i || regnum == -1)
> -	regcache->raw_supply (i, regs + armbsd_fpreg_offset (i));
> -    }
> -}
> -
>  /* Supply register REGNUM from the buffer specified by GREGS and LEN
>     in the general-purpose register set REGSET to register cache
>     REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
> @@ -84,13 +51,6 @@ armbsd_supply_gregset (const struct regset *regset,
>  
>    if (regnum == ARM_PS_REGNUM || regnum == -1)
>      regcache->raw_supply (i, regs + 16 * 4);
> -
> -  if (len >= ARMBSD_SIZEOF_GREGS + ARMBSD_SIZEOF_FPREGS)
> -    {
> -      regs += ARMBSD_SIZEOF_GREGS;
> -      len -= ARMBSD_SIZEOF_GREGS;
> -      armbsd_supply_fpregset (regset, regcache, regnum, regs, len);
> -    }
>  }
>  
>  /* ARM register sets.  */
> @@ -103,12 +63,6 @@ static const struct regset armbsd_gregset =
>    REGSET_VARIABLE_SIZE
>  };
>  
> -static const struct regset armbsd_fpregset =
> -{
> -  NULL,
> -  armbsd_supply_fpregset
> -};
> -
>  /* Iterate over supported core file register note sections. */
>  
>  void
> @@ -119,6 +73,4 @@ armbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
>  {
>    cb (".reg", ARMBSD_SIZEOF_GREGS, ARMBSD_SIZEOF_GREGS, &armbsd_gregset, NULL,
>        cb_data);
> -  cb (".reg2", ARMBSD_SIZEOF_FPREGS, ARMBSD_SIZEOF_FPREGS, &armbsd_fpregset,
> -      NULL, cb_data);
>  }
> diff --git a/gdb/arm-linux-nat.c b/gdb/arm-linux-nat.c
> index 0188c78fe7a..a6a5745fdf9 100644
> --- a/gdb/arm-linux-nat.c
> +++ b/gdb/arm-linux-nat.c
> @@ -109,96 +109,6 @@ class arm_linux_nat_target final : public linux_nat_target
>  
>  static arm_linux_nat_target the_arm_linux_nat_target;
>  
> -/* Get the whole floating point state of the process and store it
> -   into regcache.  */
> -
> -static void
> -fetch_fpregs (struct regcache *regcache)
> -{
> -  int ret, regno, tid;
> -  gdb_byte fp[ARM_LINUX_SIZEOF_NWFPE];
> -
> -  /* Get the thread id for the ptrace call.  */
> -  tid = regcache->ptid ().lwp ();
> -
> -  /* Read the floating point state.  */
> -  if (have_ptrace_getregset == TRIBOOL_TRUE)
> -    {
> -      struct iovec iov;
> -
> -      iov.iov_base = &fp;
> -      iov.iov_len = ARM_LINUX_SIZEOF_NWFPE;
> -
> -      ret = ptrace (PTRACE_GETREGSET, tid, NT_FPREGSET, &iov);
> -    }
> -  else
> -    ret = ptrace (PT_GETFPREGS, tid, 0, fp);
> -
> -  if (ret < 0)
> -    perror_with_name (_("Unable to fetch the floating point registers"));
> -
> -  /* Fetch fpsr.  */
> -  regcache->raw_supply (ARM_FPS_REGNUM, fp + NWFPE_FPSR_OFFSET);
> -
> -  /* Fetch the floating point registers.  */
> -  for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
> -    supply_nwfpe_register (regcache, regno, fp);
> -}
> -
> -/* Save the whole floating point state of the process using
> -   the contents from regcache.  */
> -
> -static void
> -store_fpregs (const struct regcache *regcache)
> -{
> -  int ret, regno, tid;
> -  gdb_byte fp[ARM_LINUX_SIZEOF_NWFPE];
> -
> -  /* Get the thread id for the ptrace call.  */
> -  tid = regcache->ptid ().lwp ();
> -
> -  /* Read the floating point state.  */
> -  if (have_ptrace_getregset == TRIBOOL_TRUE)
> -    {
> -      elf_fpregset_t fpregs;
> -      struct iovec iov;
> -
> -      iov.iov_base = &fpregs;
> -      iov.iov_len = sizeof (fpregs);
> -
> -      ret = ptrace (PTRACE_GETREGSET, tid, NT_FPREGSET, &iov);
> -    }
> -  else
> -    ret = ptrace (PT_GETFPREGS, tid, 0, fp);
> -
> -  if (ret < 0)
> -    perror_with_name (_("Unable to fetch the floating point registers"));
> -
> -  /* Store fpsr.  */
> -  if (REG_VALID == regcache->get_register_status (ARM_FPS_REGNUM))
> -    regcache->raw_collect (ARM_FPS_REGNUM, fp + NWFPE_FPSR_OFFSET);
> -
> -  /* Store the floating point registers.  */
> -  for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
> -    if (REG_VALID == regcache->get_register_status (regno))
> -      collect_nwfpe_register (regcache, regno, fp);
> -
> -  if (have_ptrace_getregset == TRIBOOL_TRUE)
> -    {
> -      struct iovec iov;
> -
> -      iov.iov_base = &fp;
> -      iov.iov_len = ARM_LINUX_SIZEOF_NWFPE;
> -
> -      ret = ptrace (PTRACE_SETREGSET, tid, NT_FPREGSET, &iov);
> -    }
> -  else
> -    ret = ptrace (PTRACE_SETFPREGS, tid, 0, fp);
> -
> -  if (ret < 0)
> -    perror_with_name (_("Unable to store floating point registers"));
> -}
> -
>  /* Fetch all general registers of the process and store into
>     regcache.  */
>  
> @@ -422,15 +332,11 @@ arm_linux_nat_target::fetch_registers (struct regcache *regcache, int regno)
>  	fetch_wmmx_regs (regcache);
>        if (tdep->vfp_register_count > 0)
>  	fetch_vfp_regs (regcache);
> -      if (tdep->have_fpa_registers)
> -	fetch_fpregs (regcache);
>      }
>    else
>      {
> -      if (regno < ARM_F0_REGNUM || regno == ARM_PS_REGNUM)
> +      if (regno <= ARM_PC_REGNUM || regno == ARM_PS_REGNUM)
>  	fetch_regs (regcache);
> -      else if (regno >= ARM_F0_REGNUM && regno <= ARM_FPS_REGNUM)
> -	fetch_fpregs (regcache);
>        else if (tdep->have_wmmx_registers
>  	       && regno >= ARM_WR0_REGNUM && regno <= ARM_WCGR7_REGNUM)
>  	fetch_wmmx_regs (regcache);
> @@ -459,15 +365,11 @@ arm_linux_nat_target::store_registers (struct regcache *regcache, int regno)
>  	store_wmmx_regs (regcache);
>        if (tdep->vfp_register_count > 0)
>  	store_vfp_regs (regcache);
> -      if (tdep->have_fpa_registers)
> -	store_fpregs (regcache);
>      }
>    else
>      {
> -      if (regno < ARM_F0_REGNUM || regno == ARM_PS_REGNUM)
> +      if (regno <= ARM_PC_REGNUM || regno == ARM_PS_REGNUM)
>  	store_regs (regcache);
> -      else if ((regno >= ARM_F0_REGNUM) && (regno <= ARM_FPS_REGNUM))
> -	store_fpregs (regcache);
>        else if (tdep->have_wmmx_registers
>  	       && regno >= ARM_WR0_REGNUM && regno <= ARM_WCGR7_REGNUM)
>  	store_wmmx_regs (regcache);
> @@ -499,7 +401,7 @@ void
>  fill_fpregset (const struct regcache *regcache,
>  	       gdb_fpregset_t *fpregsetp, int regno)
>  {
> -  arm_linux_collect_nwfpe (NULL, regcache, regno, fpregsetp, 0);
> +  /* FPA is no longer supported.  */
>  }
>  
>  /* Fill GDB's register array with the floating-point register values
> @@ -508,7 +410,7 @@ fill_fpregset (const struct regcache *regcache,
>  void
>  supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregsetp)
>  {
> -  arm_linux_supply_nwfpe (NULL, regcache, -1, fpregsetp, 0);
> +  /* FPA is no longer supported.  */
>  }
>  
>  /* Fetch the thread-local storage pointer for libthread_db.  */
> diff --git a/gdb/arm-linux-tdep.c b/gdb/arm-linux-tdep.c
> index 1feb69fe6dd..d5ada33a05c 100644
> --- a/gdb/arm-linux-tdep.c
> +++ b/gdb/arm-linux-tdep.c
> @@ -102,10 +102,8 @@ static const gdb_byte arm_linux_thumb2_le_breakpoint[] = { 0xf0, 0xf7, 0x00, 0xa
>  
>     For glibc, eglibc, and uclibc the following holds:  If the FP model is 
>     SoftVFP or VFP (which implies EABI) then the PC is at offset 9 in the 
> -   buffer.  This is also true for the SoftFPA model.  However, for the FPA 
> -   model the PC is at offset 21 in the buffer.  */
> +   buffer.  */
>  #define ARM_LINUX_JB_ELEMENT_SIZE	ARM_INT_REGISTER_SIZE
> -#define ARM_LINUX_JB_PC_FPA		21
>  #define ARM_LINUX_JB_PC_EABI		9
>  
>  /*
> @@ -540,119 +538,6 @@ arm_linux_collect_gregset (const struct regset *regset,
>  			   gregs + ARM_INT_REGISTER_SIZE * ARM_PC_REGNUM);
>  }
>  
> -/* Support for register format used by the NWFPE FPA emulator.  */
> -
> -#define typeNone		0x00
> -#define typeSingle		0x01
> -#define typeDouble		0x02
> -#define typeExtended		0x03
> -
> -void
> -supply_nwfpe_register (struct regcache *regcache, int regno,
> -		       const gdb_byte *regs)
> -{
> -  const gdb_byte *reg_data;
> -  gdb_byte reg_tag;
> -  gdb_byte buf[ARM_FP_REGISTER_SIZE];
> -
> -  reg_data = regs + (regno - ARM_F0_REGNUM) * ARM_FP_REGISTER_SIZE;
> -  reg_tag = regs[(regno - ARM_F0_REGNUM) + NWFPE_TAGS_OFFSET];
> -  memset (buf, 0, ARM_FP_REGISTER_SIZE);
> -
> -  switch (reg_tag)
> -    {
> -    case typeSingle:
> -      memcpy (buf, reg_data, 4);
> -      break;
> -    case typeDouble:
> -      memcpy (buf, reg_data + 4, 4);
> -      memcpy (buf + 4, reg_data, 4);
> -      break;
> -    case typeExtended:
> -      /* We want sign and exponent, then least significant bits,
> -	 then most significant.  NWFPE does sign, most, least.  */
> -      memcpy (buf, reg_data, 4);
> -      memcpy (buf + 4, reg_data + 8, 4);
> -      memcpy (buf + 8, reg_data + 4, 4);
> -      break;
> -    default:
> -      break;
> -    }
> -
> -  regcache->raw_supply (regno, buf);
> -}
> -
> -void
> -collect_nwfpe_register (const struct regcache *regcache, int regno,
> -			gdb_byte *regs)
> -{
> -  gdb_byte *reg_data;
> -  gdb_byte reg_tag;
> -  gdb_byte buf[ARM_FP_REGISTER_SIZE];
> -
> -  regcache->raw_collect (regno, buf);
> -
> -  /* NOTE drow/2006-06-07: This code uses the tag already in the
> -     register buffer.  I've preserved that when moving the code
> -     from the native file to the target file.  But this doesn't
> -     always make sense.  */
> -
> -  reg_data = regs + (regno - ARM_F0_REGNUM) * ARM_FP_REGISTER_SIZE;
> -  reg_tag = regs[(regno - ARM_F0_REGNUM) + NWFPE_TAGS_OFFSET];
> -
> -  switch (reg_tag)
> -    {
> -    case typeSingle:
> -      memcpy (reg_data, buf, 4);
> -      break;
> -    case typeDouble:
> -      memcpy (reg_data, buf + 4, 4);
> -      memcpy (reg_data + 4, buf, 4);
> -      break;
> -    case typeExtended:
> -      memcpy (reg_data, buf, 4);
> -      memcpy (reg_data + 4, buf + 8, 4);
> -      memcpy (reg_data + 8, buf + 4, 4);
> -      break;
> -    default:
> -      break;
> -    }
> -}
> -
> -void
> -arm_linux_supply_nwfpe (const struct regset *regset,
> -			struct regcache *regcache,
> -			int regnum, const void *regs_buf, size_t len)
> -{
> -  const gdb_byte *regs = (const gdb_byte *) regs_buf;
> -  int regno;
> -
> -  if (regnum == ARM_FPS_REGNUM || regnum == -1)
> -    regcache->raw_supply (ARM_FPS_REGNUM,
> -			 regs + NWFPE_FPSR_OFFSET);
> -
> -  for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
> -    if (regnum == -1 || regnum == regno)
> -      supply_nwfpe_register (regcache, regno, regs);
> -}
> -
> -void
> -arm_linux_collect_nwfpe (const struct regset *regset,
> -			 const struct regcache *regcache,
> -			 int regnum, void *regs_buf, size_t len)
> -{
> -  gdb_byte *regs = (gdb_byte *) regs_buf;
> -  int regno;
> -
> -  for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
> -    if (regnum == -1 || regnum == regno)
> -      collect_nwfpe_register (regcache, regno, regs);
> -
> -  if (regnum == ARM_FPS_REGNUM || regnum == -1)
> -    regcache->raw_collect (ARM_FPS_REGNUM,
> -			   regs + ARM_INT_REGISTER_SIZE * ARM_FPS_REGNUM);
> -}
> -
>  /* Support VFP register format.  */
>  
>  #define ARM_LINUX_SIZEOF_VFP (32 * 8 + 4)
> @@ -694,11 +579,6 @@ static const struct regset arm_linux_gregset =
>      NULL, arm_linux_supply_gregset, arm_linux_collect_gregset
>    };
>  
> -static const struct regset arm_linux_fpregset =
> -  {
> -    NULL, arm_linux_supply_nwfpe, arm_linux_collect_nwfpe
> -  };
> -
>  static const struct regset arm_linux_vfpregset =
>    {
>      NULL, arm_linux_supply_vfp, arm_linux_collect_vfp
> @@ -720,9 +600,6 @@ arm_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
>    if (tdep->vfp_register_count > 0)
>      cb (".reg-arm-vfp", ARM_LINUX_SIZEOF_VFP, ARM_LINUX_SIZEOF_VFP,
>  	&arm_linux_vfpregset, "VFP floating-point", cb_data);
> -  else if (tdep->have_fpa_registers)
> -    cb (".reg2", ARM_LINUX_SIZEOF_NWFPE, ARM_LINUX_SIZEOF_NWFPE,
> -	&arm_linux_fpregset, "FPA floating-point", cb_data);
>  }
>  
>  /* Determine target description from core file.  */
> @@ -1744,14 +1621,10 @@ arm_linux_init_abi (struct gdbarch_info info,
>    tdep->thumb2_breakpoint_size = sizeof (arm_linux_thumb2_le_breakpoint);
>  
>    if (tdep->fp_model == ARM_FLOAT_AUTO)
> -    tdep->fp_model = ARM_FLOAT_FPA;
> +    tdep->fp_model = ARM_FLOAT_SOFT_VFP;
>  
>    switch (tdep->fp_model)
>      {
> -    case ARM_FLOAT_FPA:
> -      tdep->jb_pc = ARM_LINUX_JB_PC_FPA;
> -      break;
> -    case ARM_FLOAT_SOFT_FPA:
>      case ARM_FLOAT_SOFT_VFP:
>      case ARM_FLOAT_VFP:
>        tdep->jb_pc = ARM_LINUX_JB_PC_EABI;
> diff --git a/gdb/arm-linux-tdep.h b/gdb/arm-linux-tdep.h
> index 6ed55acf9b0..cb92c3f6bbe 100644
> --- a/gdb/arm-linux-tdep.h
> +++ b/gdb/arm-linux-tdep.h
> @@ -23,23 +23,6 @@
>  struct regset;
>  struct regcache;
>  
> -#define ARM_LINUX_SIZEOF_NWFPE (8 * ARM_FP_REGISTER_SIZE \
> -				+ 2 * ARM_INT_REGISTER_SIZE \
> -				+ 8 + ARM_INT_REGISTER_SIZE)
> -
> -/* Support for register format used by the NWFPE FPA emulator.  Each
> -   register takes three words, where either the first one, two, or
> -   three hold a single, double, or extended precision value (depending
> -   on the corresponding tag).  The register set is eight registers,
> -   followed by the fpsr and fpcr, followed by eight tag bytes, and a
> -   final word flag which indicates whether NWFPE has been
> -   initialized.  */
> -
> -#define NWFPE_FPSR_OFFSET (8 * ARM_FP_REGISTER_SIZE)
> -#define NWFPE_FPCR_OFFSET (NWFPE_FPSR_OFFSET + ARM_INT_REGISTER_SIZE)
> -#define NWFPE_TAGS_OFFSET (NWFPE_FPCR_OFFSET + ARM_INT_REGISTER_SIZE)
> -#define NWFPE_INITFLAG_OFFSET (NWFPE_TAGS_OFFSET + 8)
> -
>  void arm_linux_supply_gregset (const struct regset *regset,
>  			       struct regcache *regcache,
>  			       int regnum, const void *gregs_buf, size_t len);
> @@ -47,18 +30,6 @@ void arm_linux_collect_gregset (const struct regset *regset,
>  				const struct regcache *regcache,
>  				int regnum, void *gregs_buf, size_t len);
>  
> -void supply_nwfpe_register (struct regcache *regcache, int regno,
> -			    const gdb_byte *regs);
> -void collect_nwfpe_register (const struct regcache *regcache, int regno,
> -			     gdb_byte *regs);
> -
> -void arm_linux_supply_nwfpe (const struct regset *regset,
> -			     struct regcache *regcache,
> -			     int regnum, const void *regs_buf, size_t len);
> -void arm_linux_collect_nwfpe (const struct regset *regset,
> -			      const struct regcache *regcache,
> -			      int regnum, void *regs_buf, size_t len);
> -
>  /* ARM GNU/Linux HWCAP values.  These are in defined in
>     <asm/elf.h> in current kernels.  */
>  #define HWCAP_VFP       64
> diff --git a/gdb/arm-netbsd-nat.c b/gdb/arm-netbsd-nat.c
> index 251159154c9..d37a1951c21 100644
> --- a/gdb/arm-netbsd-nat.c
> +++ b/gdb/arm-netbsd-nat.c
> @@ -135,7 +135,7 @@ arm_netbsd_nat_target::fetch_registers (struct regcache *regcache, int regno)
>  {
>    if (regno >= 0)
>      {
> -      if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
> +      if (regno <= ARM_PC_REGNUM || regno >= ARM_PS_REGNUM)
>  	fetch_register (regcache, regno);
>        else
>  	fetch_fp_register (regcache, regno);
> @@ -326,7 +326,7 @@ arm_netbsd_nat_target::store_registers (struct regcache *regcache, int regno)
>  {
>    if (regno >= 0)
>      {
> -      if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
> +      if (regno <= ARM_PC_REGNUM || regno >= ARM_PS_REGNUM)
>  	store_register (regcache, regno);
>        else
>  	store_fp_register (regcache, regno);
> diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
> index ead9bbf46c5..b33a53612a6 100644
> --- a/gdb/arm-tdep.c
> +++ b/gdb/arm-tdep.c
> @@ -134,8 +134,6 @@ static struct cmd_list_element *showarmcmdlist = NULL;
>  static const char *const fp_model_strings[] =
>  {
>    "auto",
> -  "softfpa",
> -  "fpa",
>    "softvfp",
>    "vfp",
>    NULL
> @@ -226,9 +224,7 @@ static const char *const arm_register_names[] =
>   "r4",  "r5",  "r6",  "r7",	/*  4  5  6  7 */
>   "r8",  "r9",  "r10", "r11",	/*  8  9 10 11 */
>   "r12", "sp",  "lr",  "pc",	/* 12 13 14 15 */
> - "f0",  "f1",  "f2",  "f3",	/* 16 17 18 19 */
> - "f4",  "f5",  "f6",  "f7",	/* 20 21 22 23 */
> - "fps", "cpsr" };		/* 24 25       */
> + "cpsr" };			/* 25 */
>  
>  /* Holds the current set of options to be passed to the disassembler.  */
>  static char *arm_disassembler_options;
> @@ -1877,7 +1873,7 @@ arm_analyze_prologue (struct gdbarch *gdbarch,
>    enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
>    int regno;
>    CORE_ADDR offset, current_pc;
> -  pv_t regs[ARM_FPS_REGNUM];
> +  pv_t regs[ARM_PC_REGNUM];
>    CORE_ADDR unrecognized_pc = 0;
>    arm_gdbarch_tdep *tdep = gdbarch_tdep<arm_gdbarch_tdep> (gdbarch);
>  
> @@ -1891,7 +1887,7 @@ arm_analyze_prologue (struct gdbarch *gdbarch,
>       and other operations that rely on a knowledge of the stack
>       traceback.  */
>  
> -  for (regno = 0; regno < ARM_FPS_REGNUM; regno++)
> +  for (regno = 0; regno < ARM_PC_REGNUM; regno++)
>      regs[regno] = pv_register (regno, 0);
>    pv_area stack (ARM_SP_REGNUM, gdbarch_addr_bit (gdbarch));
>  
> @@ -1982,51 +1978,6 @@ arm_analyze_prologue (struct gdbarch *gdbarch,
>  	  uint32_t imm = arm_expand_immediate(insn & 0xfff);
>  	  regs[ARM_SP_REGNUM] = pv_add_constant (regs[ARM_SP_REGNUM], -imm);
>  	}
> -      else if ((insn & 0xffff7fff) == 0xed6d0103	/* stfe f?,
> -							   [sp, -#c]! */
> -	       && tdep->have_fpa_registers)
> -	{
> -	  if (stack.store_would_trash (regs[ARM_SP_REGNUM]))
> -	    break;
> -
> -	  regs[ARM_SP_REGNUM] = pv_add_constant (regs[ARM_SP_REGNUM], -12);
> -	  regno = ARM_F0_REGNUM + ((insn >> 12) & 0x07);
> -	  stack.store (regs[ARM_SP_REGNUM], 12, regs[regno]);
> -	}
> -      else if ((insn & 0xffbf0fff) == 0xec2d0200	/* sfmfd f0, 4,
> -							   [sp!] */
> -	       && tdep->have_fpa_registers)
> -	{
> -	  int n_saved_fp_regs;
> -	  unsigned int fp_start_reg, fp_bound_reg;
> -
> -	  if (stack.store_would_trash (regs[ARM_SP_REGNUM]))
> -	    break;
> -
> -	  if ((insn & 0x800) == 0x800)		/* N0 is set */
> -	    {
> -	      if ((insn & 0x40000) == 0x40000)	/* N1 is set */
> -		n_saved_fp_regs = 3;
> -	      else
> -		n_saved_fp_regs = 1;
> -	    }
> -	  else
> -	    {
> -	      if ((insn & 0x40000) == 0x40000)	/* N1 is set */
> -		n_saved_fp_regs = 2;
> -	      else
> -		n_saved_fp_regs = 4;
> -	    }
> -
> -	  fp_start_reg = ARM_F0_REGNUM + ((insn >> 12) & 0x7);
> -	  fp_bound_reg = fp_start_reg + n_saved_fp_regs;
> -	  for (; fp_start_reg < fp_bound_reg; fp_start_reg++)
> -	    {
> -	      regs[ARM_SP_REGNUM] = pv_add_constant (regs[ARM_SP_REGNUM], -12);
> -	      stack.store (regs[ARM_SP_REGNUM], 12,
> -			   regs[fp_start_reg++]);
> -	    }
> -	}
>        else if ((insn & 0xff000000) == 0xeb000000 && cache == NULL) /* bl */
>  	{
>  	  /* Allow some special function calls when skipping the
> @@ -2103,7 +2054,7 @@ arm_analyze_prologue (struct gdbarch *gdbarch,
>        cache->framereg = framereg;
>        cache->framesize = framesize;
>  
> -      for (regno = 0; regno < ARM_FPS_REGNUM; regno++)
> +      for (regno = 0; regno < ARM_PC_REGNUM; regno++)
>  	if (stack.find_reg (gdbarch, regno, &offset))
>  	  {
>  	    cache->saved_regs[regno].set_addr (offset);
> @@ -4666,58 +4617,6 @@ arm_frame_align (struct gdbarch *gdbarch, CORE_ADDR sp)
>    return sp & ~ (CORE_ADDR) 7;
>  }
>  
> -static void
> -print_fpu_flags (struct ui_file *file, int flags)
> -{
> -  if (flags & (1 << 0))
> -    gdb_puts ("IVO ", file);
> -  if (flags & (1 << 1))
> -    gdb_puts ("DVZ ", file);
> -  if (flags & (1 << 2))
> -    gdb_puts ("OFL ", file);
> -  if (flags & (1 << 3))
> -    gdb_puts ("UFL ", file);
> -  if (flags & (1 << 4))
> -    gdb_puts ("INX ", file);
> -  gdb_putc ('\n', file);
> -}
> -
> -/* Print interesting information about the floating point processor
> -   (if present) or emulator.  */
> -static void
> -arm_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
> -		      struct frame_info *frame, const char *args)
> -{
> -  unsigned long status = get_frame_register_unsigned (frame, ARM_FPS_REGNUM);
> -  int type;
> -
> -  type = (status >> 24) & 127;
> -  if (status & (1 << 31))
> -    gdb_printf (file, _("Hardware FPU type %d\n"), type);
> -  else
> -    gdb_printf (file, _("Software FPU type %d\n"), type);
> -  /* i18n: [floating point unit] mask */
> -  gdb_puts (_("mask: "), file);
> -  print_fpu_flags (file, status >> 16);
> -  /* i18n: [floating point unit] flags */
> -  gdb_puts (_("flags: "), file);
> -  print_fpu_flags (file, status);
> -}
> -
> -/* Construct the ARM extended floating point type.  */
> -static struct type *
> -arm_ext_type (struct gdbarch *gdbarch)
> -{
> -  arm_gdbarch_tdep *tdep = gdbarch_tdep<arm_gdbarch_tdep> (gdbarch);
> -
> -  if (!tdep->arm_ext_type)
> -    tdep->arm_ext_type
> -      = arch_float_type (gdbarch, -1, "builtin_type_arm_ext",
> -			 floatformats_arm_ext);
> -
> -  return tdep->arm_ext_type;
> -}
> -
>  static struct type *
>  arm_neon_double_type (struct gdbarch *gdbarch)
>  {
> @@ -4902,14 +4801,7 @@ arm_register_type (struct gdbarch *gdbarch, int regnum)
>  	return t;
>      }
>  
> -  if (regnum >= ARM_F0_REGNUM && regnum < ARM_F0_REGNUM + NUM_FREGS)
> -    {
> -      if (!tdep->have_fpa_registers)
> -	return builtin_type (gdbarch)->builtin_void;
> -
> -      return arm_ext_type (gdbarch);
> -    }
> -  else if (regnum == ARM_SP_REGNUM)
> +  if (regnum == ARM_SP_REGNUM)
>      return builtin_type (gdbarch)->builtin_data_ptr;
>    else if (regnum == ARM_PC_REGNUM)
>      return builtin_type (gdbarch)->builtin_func_ptr;
> @@ -4931,17 +4823,6 @@ arm_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int reg)
>    if (reg >= 0 && reg <= 15)
>      return reg;
>  
> -  /* Legacy FPA encoding.  These were once used in a way which
> -     overlapped with VFP register numbering, so their use is
> -     discouraged, but GDB doesn't support the ARM toolchain
> -     which used them for VFP.  */
> -  if (reg >= 16 && reg <= 23)
> -    return ARM_F0_REGNUM + reg - 16;
> -
> -  /* New assignments for the FPA registers.  */
> -  if (reg >= 96 && reg <= 103)
> -    return ARM_F0_REGNUM + reg - 96;
> -
>    /* WMMX register assignments.  */
>    if (reg >= 104 && reg <= 111)
>      return ARM_WCGR0_REGNUM + reg - 104;
> @@ -5014,14 +4895,6 @@ arm_register_sim_regno (struct gdbarch *gdbarch, int regnum)
>      return SIM_ARM_R0_REGNUM + reg;
>    reg -= NUM_GREGS;
>  
> -  if (reg < NUM_FREGS)
> -    return SIM_ARM_FP0_REGNUM + reg;
> -  reg -= NUM_FREGS;
> -
> -  if (reg < NUM_SREGS)
> -    return SIM_ARM_FPS_REGNUM + reg;
> -  reg -= NUM_SREGS;
> -
>    internal_error (__FILE__, __LINE__, _("Bad REGNUM %d"), regnum);
>  }
>  
> @@ -8686,20 +8559,6 @@ arm_extract_return_value (struct type *type, struct regcache *regs,
>      {
>        switch (tdep->fp_model)
>  	{
> -	case ARM_FLOAT_FPA:
> -	  {
> -	    /* The value is in register F0 in internal format.  We need to
> -	       extract the raw value and then convert it to the desired
> -	       internal type.  */
> -	    bfd_byte tmpbuf[ARM_FP_REGISTER_SIZE];
> -
> -	    regs->cooked_read (ARM_F0_REGNUM, tmpbuf);
> -	    target_float_convert (tmpbuf, arm_ext_type (gdbarch),
> -				  valbuf, type);
> -	  }
> -	  break;
> -
> -	case ARM_FLOAT_SOFT_FPA:
>  	case ARM_FLOAT_SOFT_VFP:
>  	  /* ARM_FLOAT_VFP can arise if this is a variadic function so
>  	     not using the VFP ABI code.  */
> @@ -8896,18 +8755,10 @@ arm_store_return_value (struct type *type, struct regcache *regs,
>  
>    if (type->code () == TYPE_CODE_FLT)
>      {
> -      gdb_byte buf[ARM_FP_REGISTER_SIZE];
>        arm_gdbarch_tdep *tdep = gdbarch_tdep<arm_gdbarch_tdep> (gdbarch);
>  
>        switch (tdep->fp_model)
>  	{
> -	case ARM_FLOAT_FPA:
> -
> -	  target_float_convert (valbuf, type, buf, arm_ext_type (gdbarch));
> -	  regs->cooked_write (ARM_F0_REGNUM, buf);
> -	  break;
> -
> -	case ARM_FLOAT_SOFT_FPA:
>  	case ARM_FLOAT_SOFT_VFP:
>  	  /* ARM_FLOAT_VFP can arise if this is a variadic function so
>  	     not using the VFP ABI code.  */
> @@ -9722,71 +9573,6 @@ arm_elf_osabi_sniffer (bfd *abfd)
>    return osabi;
>  }
>  
> -static int
> -arm_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
> -			 const struct reggroup *group)
> -{
> -  /* FPS register's type is INT, but belongs to float_reggroup.  Beside
> -     this, FPS register belongs to save_regroup, restore_reggroup, and
> -     all_reggroup, of course.  */
> -  if (regnum == ARM_FPS_REGNUM)
> -    return (group == float_reggroup
> -	    || group == save_reggroup
> -	    || group == restore_reggroup
> -	    || group == all_reggroup);
> -  else
> -    return default_register_reggroup_p (gdbarch, regnum, group);
> -}
> -
> -/* For backward-compatibility we allow two 'g' packet lengths with
> -   the remote protocol depending on whether FPA registers are
> -   supplied.  M-profile targets do not have FPA registers, but some
> -   stubs already exist in the wild which use a 'g' packet which
> -   supplies them albeit with dummy values.  The packet format which
> -   includes FPA registers should be considered deprecated for
> -   M-profile targets.  */
> -
> -static void
> -arm_register_g_packet_guesses (struct gdbarch *gdbarch)
> -{
> -  arm_gdbarch_tdep *tdep = gdbarch_tdep<arm_gdbarch_tdep> (gdbarch);
> -
> -  if (tdep->is_m)
> -    {
> -      const target_desc *tdesc;
> -
> -      /* If we know from the executable this is an M-profile target,
> -	 cater for remote targets whose register set layout is the
> -	 same as the FPA layout.  */
> -      tdesc = arm_read_mprofile_description (ARM_M_TYPE_WITH_FPA);
> -      register_remote_g_packet_guess (gdbarch,
> -				      ARM_CORE_REGS_SIZE + ARM_FP_REGS_SIZE,
> -				      tdesc);
> -
> -      /* The regular M-profile layout.  */
> -      tdesc = arm_read_mprofile_description (ARM_M_TYPE_M_PROFILE);
> -      register_remote_g_packet_guess (gdbarch, ARM_CORE_REGS_SIZE,
> -				      tdesc);
> -
> -      /* M-profile plus M4F VFP.  */
> -      tdesc = arm_read_mprofile_description (ARM_M_TYPE_VFP_D16);
> -      register_remote_g_packet_guess (gdbarch,
> -				      ARM_CORE_REGS_SIZE + ARM_VFP2_REGS_SIZE,
> -				      tdesc);
> -      /* M-profile plus MVE.  */
> -      tdesc = arm_read_mprofile_description (ARM_M_TYPE_MVE);
> -      register_remote_g_packet_guess (gdbarch, ARM_CORE_REGS_SIZE
> -				      + ARM_VFP2_REGS_SIZE
> -				      + ARM_INT_REGISTER_SIZE, tdesc);
> -
> -      /* M-profile system (stack pointers).  */
> -      tdesc = arm_read_mprofile_description (ARM_M_TYPE_SYSTEM);
> -      register_remote_g_packet_guess (gdbarch, 2 * ARM_INT_REGISTER_SIZE, tdesc);
> -    }
> -
> -  /* Otherwise we don't have a useful guess.  */
> -}
> -
>  /* Implement the code_of_frame_writable gdbarch method.  */
>  
>  static int
> @@ -9848,7 +9634,6 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
>    bool have_s_pseudos = false, have_q_pseudos = false;
>    bool have_wmmx_registers = false;
>    bool have_neon = false;
> -  bool have_fpa_registers = true;
>    const struct target_desc *tdesc = info.target_desc;
>    bool have_vfp = false;
>    bool have_mve = false;
> @@ -10015,21 +9800,13 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
>  	    {
>  	      switch (e_flags & (EF_ARM_SOFT_FLOAT | EF_ARM_VFP_FLOAT))
>  		{
> -		case 0:
> -		  /* Leave it as "auto".  Strictly speaking this case
> -		     means FPA, but almost nobody uses that now, and
> -		     many toolchains fail to set the appropriate bits
> -		     for the floating-point model they use.  */
> -		  break;
> -		case EF_ARM_SOFT_FLOAT:
> -		  fp_model = ARM_FLOAT_SOFT_FPA;
> +		case 0: /* Default to soft-float VFP.  */
> +		case EF_ARM_SOFT_FLOAT | EF_ARM_VFP_FLOAT:
> +		  fp_model = ARM_FLOAT_SOFT_VFP;
>  		  break;
>  		case EF_ARM_VFP_FLOAT:
>  		  fp_model = ARM_FLOAT_VFP;
>  		  break;
> -		case EF_ARM_SOFT_FLOAT | EF_ARM_VFP_FLOAT:
> -		  fp_model = ARM_FLOAT_SOFT_VFP;
> -		  break;
>  		}
>  	    }
>  
> @@ -10122,20 +9899,6 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
>  	    }
>  	}
>  
> -      feature = tdesc_find_feature (tdesc,
> -				    "org.gnu.gdb.arm.fpa");
> -      if (feature != NULL)
> -	{
> -	  valid_p = 1;
> -	  for (i = ARM_F0_REGNUM; i <= ARM_FPS_REGNUM; i++)
> -	    valid_p &= tdesc_numbered_register (feature, tdesc_data.get (), i,
> -						arm_register_names[i]);
> -	  if (!valid_p)
> -	    return NULL;
> -	}
> -      else
> -	have_fpa_registers = false;
> -
>        feature = tdesc_find_feature (tdesc,
>  				    "org.gnu.gdb.xscale.iwmmxt");
>        if (feature != NULL)
> @@ -10389,7 +10152,6 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
>    tdep->fp_model = fp_model;
>    tdep->is_m = is_m;
>    tdep->have_sec_ext = have_sec_ext;
> -  tdep->have_fpa_registers = have_fpa_registers;
>    tdep->have_wmmx_registers = have_wmmx_registers;
>    gdb_assert (vfp_register_count == 0
>  	      || vfp_register_count == 16
> @@ -10421,8 +10183,6 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
>        tdep->m_profile_psp_s_regnum = m_profile_psp_s_regnum;
>      }
>  
> -  arm_register_g_packet_guesses (gdbarch);
> -
>    /* Breakpoints.  */
>    switch (info.byte_order_for_code)
>      {
> @@ -10508,12 +10268,6 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
>    set_gdbarch_pc_regnum (gdbarch, ARM_PC_REGNUM);
>    set_gdbarch_num_regs (gdbarch, register_count);
>    set_gdbarch_register_type (gdbarch, arm_register_type);
> -  set_gdbarch_register_reggroup_p (gdbarch, arm_register_reggroup_p);
> -
> -  /* This "info float" is FPA-specific.  Use the generic version if we
> -     do not have FPA.  */
> -  if (tdep->have_fpa_registers)
> -    set_gdbarch_print_float_info (gdbarch, arm_print_float_info);
>  
>    /* Internal <-> external register number maps.  */
>    set_gdbarch_dwarf2_reg_to_regnum (gdbarch, arm_dwarf_reg_to_regnum);
> @@ -10565,29 +10319,13 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
>    /* Watchpoints are not steppable.  */
>    set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1);
>  
> -  /* We used to default to FPA for generic ARM, but almost nobody
> -     uses that now, and we now provide a way for the user to force
> -     the model.  So default to the most useful variant.  */
> -  if (tdep->fp_model == ARM_FLOAT_AUTO)
> -    tdep->fp_model = ARM_FLOAT_SOFT_FPA;
> -
>    if (tdep->jb_pc >= 0)
>      set_gdbarch_get_longjmp_target (gdbarch, arm_get_longjmp_target);
>  
>    /* Floating point sizes and format.  */
>    set_gdbarch_float_format (gdbarch, floatformats_ieee_single);
> -  if (tdep->fp_model == ARM_FLOAT_SOFT_FPA || tdep->fp_model == ARM_FLOAT_FPA)
> -    {
> -      set_gdbarch_double_format
> -	(gdbarch, floatformats_ieee_double_littlebyte_bigword);
> -      set_gdbarch_long_double_format
> -	(gdbarch, floatformats_ieee_double_littlebyte_bigword);
> -    }
> -  else
> -    {
> -      set_gdbarch_double_format (gdbarch, floatformats_ieee_double);
> -      set_gdbarch_long_double_format (gdbarch, floatformats_ieee_double);
> -    }
> +  set_gdbarch_double_format (gdbarch, floatformats_ieee_double);
> +  set_gdbarch_long_double_format (gdbarch, floatformats_ieee_double);
>  
>    /* Hook used to decorate frames with signed return addresses, only available
>       for ARMv8.1-m PACBTI.  */
> @@ -10678,8 +10416,6 @@ arm_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file)
>  
>    gdb_printf (file, _("arm_dump_tdep: fp_model = %i\n"),
>  	      (int) tdep->fp_model);
> -  gdb_printf (file, _("arm_dump_tdep: have_fpa_registers = %i\n"),
> -	      (int) tdep->have_fpa_registers);
>    gdb_printf (file, _("arm_dump_tdep: have_wmmx_registers = %i\n"),
>  	      (int) tdep->have_wmmx_registers);
>    gdb_printf (file, _("arm_dump_tdep: vfp_register_count = %i\n"),
> @@ -10820,8 +10556,6 @@ _initialize_arm_tdep ()
>  			_("Set the floating point type."),
>  			_("Show the floating point type."),
>  			_("auto - Determine the FP typefrom the OS-ABI.\n\
> -softfpa - Software FP, mixed-endian doubles on little-endian ARMs.\n\
> -fpa - FPA co-processor (GCC compiled).\n\
>  softvfp - Software FP with pure-endian doubles.\n\
>  vfp - VFP co-processor."),
>  			set_fp_model_sfunc, show_fp_model,
> diff --git a/gdb/arm-tdep.h b/gdb/arm-tdep.h
> index 67dd1151da4..594961e52ec 100644
> --- a/gdb/arm-tdep.h
> +++ b/gdb/arm-tdep.h
> @@ -62,8 +62,6 @@ extern bool arm_apcs_32;
>  enum arm_float_model
>  {
>    ARM_FLOAT_AUTO,	/* Automatic detection.  Do not set in tdep.  */
> -  ARM_FLOAT_SOFT_FPA,	/* Traditional soft-float (mixed-endian on LE ARM).  */
> -  ARM_FLOAT_FPA,	/* FPA co-processor.  GCC calling convention.  */
>    ARM_FLOAT_SOFT_VFP,	/* Soft-float with pure-endian doubles.  */
>    ARM_FLOAT_VFP,	/* Full VFP calling convention.  */
>    ARM_FLOAT_LAST	/* Keep at end.  */
> @@ -95,7 +93,6 @@ struct arm_gdbarch_tdep : gdbarch_tdep_base
>  
>    enum arm_float_model fp_model {}; /* Floating point calling conventions.  */
>  
> -  bool have_fpa_registers = false;	/* Does the target report the FPA registers?  */
>    bool have_wmmx_registers = false;	/* Does the target report the WMMX registers?  */
>    /* The number of VFP registers reported by the target.  It is zero
>       if VFP registers are not supported.  */
> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
> index 238a49b027d..2111a584b88 100644
> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo
> @@ -25309,11 +25309,6 @@ argument @var{fputype} can be one of these:
>  @table @code
>  @item auto
>  Determine the FPU type by querying the OS ABI.
> -@item softfpa
> -Software FPU, with mixed-endian doubles on little-endian ARM
> -processors.
> -@item fpa
> -GCC-compiled FPA co-processor.
>  @item softvfp
>  Software FPU with pure-endian doubles.
>  @item vfp
> @@ -46919,9 +46914,6 @@ Double precision IEEE floating point.
>  @item bfloat16
>  The 16-bit @dfn{brain floating point} format used e.g.@: by x86 and ARM.
>  
> -@item arm_fpa_ext
> -The 12-byte extended precision format used by ARM FPA registers.
> -
>  @item i387_ext
>  The 10-byte extended precision format used by x87 registers.
>  
> @@ -47106,8 +47098,9 @@ feature is replaced by @samp{org.gnu.gdb.arm.m-profile}.  It should contain
>  registers @samp{r0} through @samp{r13}, @samp{sp}, @samp{lr}, @samp{pc},
>  and @samp{xpsr}.
>  
> -The @samp{org.gnu.gdb.arm.fpa} feature is optional.  If present, it
> -should contain registers @samp{f0} through @samp{f7} and @samp{fps}.
> +The @samp{org.gnu.gdb.arm.fpa} feature is no longer supported.  It
> +used to contain registers @samp{f0} through @samp{f7} and @samp{fps}, for the
> +legacy FPA feature.
>  
>  The @samp{org.gnu.gdb.arm.m-profile-mve} feature is optional.  If present, it
>  must contain register @samp{vpr}.
> diff --git a/gdb/features/Makefile b/gdb/features/Makefile
> index 061cb2ed032..3d0ed4edafa 100644
> --- a/gdb/features/Makefile
> +++ b/gdb/features/Makefile
> @@ -204,11 +204,9 @@ FEATURE_XMLFILES = aarch64-core.xml \
>  	arc/v2-core.xml \
>  	arc/v2-aux.xml \
>  	arm/arm-core.xml \
> -	arm/arm-fpa.xml \
>  	arm/arm-m-profile.xml \
>  	arm/arm-m-profile-mve.xml \
>  	arm/arm-m-system.xml \
> -	arm/arm-m-profile-with-fpa.xml \
>  	arm/arm-tls.xml \
>  	arm/arm-vfpv2.xml \
>  	arm/arm-vfpv3.xml \
> diff --git a/gdb/features/arm/arm-fpa.c b/gdb/features/arm/arm-fpa.c
> deleted file mode 100644
> index 65a49f5f3f1..00000000000
> --- a/gdb/features/arm/arm-fpa.c
> +++ /dev/null
> @@ -1,23 +0,0 @@
> -/* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
> -  Original: arm-fpa.xml */
> -
> -#include "gdbsupport/tdesc.h"
> -
> -static int
> -create_feature_arm_arm_fpa (struct target_desc *result, long regnum)
> -{
> -  struct tdesc_feature *feature;
> -
> -  feature = tdesc_create_feature (result, "org.gnu.gdb.arm.fpa");
> -  regnum = 16;
> -  tdesc_create_reg (feature, "f0", regnum++, 1, NULL, 96, "arm_fpa_ext");
> -  tdesc_create_reg (feature, "f1", regnum++, 1, NULL, 96, "arm_fpa_ext");
> -  tdesc_create_reg (feature, "f2", regnum++, 1, NULL, 96, "arm_fpa_ext");
> -  tdesc_create_reg (feature, "f3", regnum++, 1, NULL, 96, "arm_fpa_ext");
> -  tdesc_create_reg (feature, "f4", regnum++, 1, NULL, 96, "arm_fpa_ext");
> -  tdesc_create_reg (feature, "f5", regnum++, 1, NULL, 96, "arm_fpa_ext");
> -  tdesc_create_reg (feature, "f6", regnum++, 1, NULL, 96, "arm_fpa_ext");
> -  tdesc_create_reg (feature, "f7", regnum++, 1, NULL, 96, "arm_fpa_ext");
> -  tdesc_create_reg (feature, "fps", regnum++, 1, NULL, 32, "int");
> -  return regnum;
> -}
> diff --git a/gdb/features/arm/arm-fpa.xml b/gdb/features/arm/arm-fpa.xml
> deleted file mode 100644
> index d533b25132f..00000000000
> --- a/gdb/features/arm/arm-fpa.xml
> +++ /dev/null
> @@ -1,23 +0,0 @@
> -<?xml version="1.0"?>
> -<!-- Copyright (C) 2007-2022 Free Software Foundation, Inc.
> -
> -     Copying and distribution of this file, with or without modification,
> -     are permitted in any medium without royalty provided the copyright
> -     notice and this notice are preserved.  -->
> -
> -<!DOCTYPE feature SYSTEM "gdb-target.dtd">
> -<feature name="org.gnu.gdb.arm.fpa">
> -  <!-- f0's regnum is set explicitly, because the FPA registers
> -       historically were placed between the PC and the CPSR in the "g"
> -       packet - in the middle of org.gnu.gdb.arm.core.  -->
> -  <reg name="f0" bitsize="96" type="arm_fpa_ext" regnum="16"/>
> -  <reg name="f1" bitsize="96" type="arm_fpa_ext"/>
> -  <reg name="f2" bitsize="96" type="arm_fpa_ext"/>
> -  <reg name="f3" bitsize="96" type="arm_fpa_ext"/>
> -  <reg name="f4" bitsize="96" type="arm_fpa_ext"/>
> -  <reg name="f5" bitsize="96" type="arm_fpa_ext"/>
> -  <reg name="f6" bitsize="96" type="arm_fpa_ext"/>
> -  <reg name="f7" bitsize="96" type="arm_fpa_ext"/>
> -
> -  <reg name="fps" bitsize="32"/>
> -</feature>
> diff --git a/gdb/features/arm/arm-m-profile-with-fpa.c b/gdb/features/arm/arm-m-profile-with-fpa.c
> deleted file mode 100644
> index 2b7c78597bb..00000000000
> --- a/gdb/features/arm/arm-m-profile-with-fpa.c
> +++ /dev/null
> @@ -1,39 +0,0 @@
> -/* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
> -  Original: arm-m-profile-with-fpa.xml */
> -
> -#include "gdbsupport/tdesc.h"
> -
> -static int
> -create_feature_arm_arm_m_profile_with_fpa (struct target_desc *result, long regnum)
> -{
> -  struct tdesc_feature *feature;
> -
> -  feature = tdesc_create_feature (result, "org.gnu.gdb.arm.m-profile");
> -  tdesc_create_reg (feature, "r0", regnum++, 1, NULL, 32, "int");
> -  tdesc_create_reg (feature, "r1", regnum++, 1, NULL, 32, "int");
> -  tdesc_create_reg (feature, "r2", regnum++, 1, NULL, 32, "int");
> -  tdesc_create_reg (feature, "r3", regnum++, 1, NULL, 32, "int");
> -  tdesc_create_reg (feature, "r4", regnum++, 1, NULL, 32, "int");
> -  tdesc_create_reg (feature, "r5", regnum++, 1, NULL, 32, "int");
> -  tdesc_create_reg (feature, "r6", regnum++, 1, NULL, 32, "int");
> -  tdesc_create_reg (feature, "r7", regnum++, 1, NULL, 32, "int");
> -  tdesc_create_reg (feature, "r8", regnum++, 1, NULL, 32, "int");
> -  tdesc_create_reg (feature, "r9", regnum++, 1, NULL, 32, "int");
> -  tdesc_create_reg (feature, "r10", regnum++, 1, NULL, 32, "int");
> -  tdesc_create_reg (feature, "r11", regnum++, 1, NULL, 32, "int");
> -  tdesc_create_reg (feature, "r12", regnum++, 1, NULL, 32, "int");
> -  tdesc_create_reg (feature, "sp", regnum++, 1, NULL, 32, "data_ptr");
> -  tdesc_create_reg (feature, "lr", regnum++, 1, NULL, 32, "int");
> -  tdesc_create_reg (feature, "pc", regnum++, 1, NULL, 32, "code_ptr");
> -  tdesc_create_reg (feature, "", regnum++, 1, NULL, 96, "arm_fpa_ext");
> -  tdesc_create_reg (feature, "", regnum++, 1, NULL, 96, "arm_fpa_ext");
> -  tdesc_create_reg (feature, "", regnum++, 1, NULL, 96, "arm_fpa_ext");
> -  tdesc_create_reg (feature, "", regnum++, 1, NULL, 96, "arm_fpa_ext");
> -  tdesc_create_reg (feature, "", regnum++, 1, NULL, 96, "arm_fpa_ext");
> -  tdesc_create_reg (feature, "", regnum++, 1, NULL, 96, "arm_fpa_ext");
> -  tdesc_create_reg (feature, "", regnum++, 1, NULL, 96, "arm_fpa_ext");
> -  tdesc_create_reg (feature, "", regnum++, 1, NULL, 96, "arm_fpa_ext");
> -  tdesc_create_reg (feature, "", regnum++, 1, NULL, 32, "int");
> -  tdesc_create_reg (feature, "xpsr", regnum++, 1, NULL, 32, "int");
> -  return regnum;
> -}
> diff --git a/gdb/features/arm/arm-m-profile-with-fpa.xml b/gdb/features/arm/arm-m-profile-with-fpa.xml
> deleted file mode 100644
> index 850ed42cbfd..00000000000
> --- a/gdb/features/arm/arm-m-profile-with-fpa.xml
> +++ /dev/null
> @@ -1,39 +0,0 @@
> -<?xml version="1.0"?>
> -<!-- Copyright (C) 2019-2022 Free Software Foundation, Inc.
> -
> -     Copying and distribution of this file, with or without modification,
> -     are permitted in any medium without royalty provided the copyright
> -     notice and this notice are preserved.  -->
> -
> -<!DOCTYPE feature SYSTEM "gdb-target.dtd">
> -<feature name="org.gnu.gdb.arm.m-profile">
> -  <reg name="r0" bitsize="32"/>
> -  <reg name="r1" bitsize="32"/>
> -  <reg name="r2" bitsize="32"/>
> -  <reg name="r3" bitsize="32"/>
> -  <reg name="r4" bitsize="32"/>
> -  <reg name="r5" bitsize="32"/>
> -  <reg name="r6" bitsize="32"/>
> -  <reg name="r7" bitsize="32"/>
> -  <reg name="r8" bitsize="32"/>
> -  <reg name="r9" bitsize="32"/>
> -  <reg name="r10" bitsize="32"/>
> -  <reg name="r11" bitsize="32"/>
> -  <reg name="r12" bitsize="32"/>
> -  <reg name="sp" bitsize="32" type="data_ptr"/>
> -  <reg name="lr" bitsize="32"/>
> -  <reg name="pc" bitsize="32" type="code_ptr"/>
> -
> -  <!-- Slack for unused FPA registers (f0-f7 + fps).  -->
> -  <reg name="" bitsize="96" type="arm_fpa_ext" regnum="16"/>
> -  <reg name="" bitsize="96" type="arm_fpa_ext"/>
> -  <reg name="" bitsize="96" type="arm_fpa_ext"/>
> -  <reg name="" bitsize="96" type="arm_fpa_ext"/>
> -  <reg name="" bitsize="96" type="arm_fpa_ext"/>
> -  <reg name="" bitsize="96" type="arm_fpa_ext"/>
> -  <reg name="" bitsize="96" type="arm_fpa_ext"/>
> -  <reg name="" bitsize="96" type="arm_fpa_ext"/>
> -  <reg name="" bitsize="32"/>
> -
> -  <reg name="xpsr" bitsize="32" regnum="25"/>
> -</feature>
> diff --git a/gdb/target-descriptions.c b/gdb/target-descriptions.c
> index 044b171ecd2..45a3df941c5 100644
> --- a/gdb/target-descriptions.c
> +++ b/gdb/target-descriptions.c
> @@ -132,10 +132,6 @@ make_gdb_type (struct gdbarch *gdbarch, struct tdesc_type *ttype)
>  	  m_type = arch_float_type (m_gdbarch, -1, "builtin_type_ieee_double",
>  				    floatformats_ieee_double);
>  	  return;
> -	case TDESC_TYPE_ARM_FPA_EXT:
> -	  m_type = arch_float_type (m_gdbarch, -1, "builtin_type_arm_ext",
> -				    floatformats_arm_ext);
> -	  return;
>  
>  	case TDESC_TYPE_I387_EXT:
>  	  m_type = arch_float_type (m_gdbarch, -1, "builtin_type_i387_ext",
> diff --git a/gdb/testsuite/gdb.base/long_long.exp b/gdb/testsuite/gdb.base/long_long.exp
> index 9c8dd16b7eb..bb4c1a1859e 100644
> --- a/gdb/testsuite/gdb.base/long_long.exp
> +++ b/gdb/testsuite/gdb.base/long_long.exp
> @@ -141,22 +141,10 @@ gdb_test_ptr "p/a val.oct" "" "" "0x77053977" "0xa72ee53977053977"
>  gdb_test "p/c val.oct" "'w'"
>  
>  if { $sizeof_double == 8 || $sizeof_long_double == 8 } {
> -    # ARM FPA floating point numbers are not strictly little endian or big
> -    # endian, but a hybrid.  They are in little endian format with the two
> -    # words swapped in big endian format.
>      # EABI targets default to natural-endian VFP format.
> -
> -    if { ([istarget "arm*-*-*"]) \
> -	 && !([istarget "*-*-*eabi*"] || \
> -	      [istarget "*-*-mingw32ce*"] || \
> -	      [istarget "*-*-openbsd*"]) } then {
> -	# assume the long long represents a floating point double in ARM format
> -	gdb_test "p/f val.oct" "2.1386676354387559e\\+265"
> -    } else {
> -	# assume the long long represents a floating point double in little
> -	# endian format
> -	gdb_test "p/f val.oct" "-5.9822653797615723e-120"
> -    }
> +    # Assume the long long represents a floating point double in little
> +    # endian format
> +    gdb_test "p/f val.oct" "-5.9822653797615723e-120"
>  } else {
>      gdb_test "p/f val.oct" "-2.42716126e-15"
>  }
> diff --git a/gdbserver/linux-arm-low.cc b/gdbserver/linux-arm-low.cc
> index ab6209a3abc..fb3f02088ca 100644
> --- a/gdbserver/linux-arm-low.cc
> +++ b/gdbserver/linux-arm-low.cc
> @@ -983,8 +983,7 @@ arm_read_description (void)
>  	return arm_linux_read_description (ARM_FP_TYPE_VFPV2);
>      }
>  
> -  /* The default configuration uses legacy FPA registers, probably
> -     simulated.  */
> +  /* No floating point registers.  */
>    return arm_linux_read_description (ARM_FP_TYPE_NONE);
>  }
>  
> @@ -1088,9 +1087,9 @@ static struct regset_info arm_regsets[] = {
>    { PTRACE_GETREGS, PTRACE_SETREGS, 0,
>      ARM_CORE_REGS_SIZE + ARM_INT_REGISTER_SIZE, GENERAL_REGS,
>      arm_fill_gregset, arm_store_gregset },
> -  { PTRACE_GETWMMXREGS, PTRACE_SETWMMXREGS, 0, IWMMXT_REGS_SIZE, EXTENDED_REGS,
> +  { PTRACE_GETWMMXREGS, PTRACE_SETWMMXREGS, 0, IWMMXT_REGS_SIZE, OPTIONAL_REGS,
>      arm_fill_wmmxregset, arm_store_wmmxregset },
> -  { PTRACE_GETVFPREGS, PTRACE_SETVFPREGS, 0, ARM_VFP3_REGS_SIZE, EXTENDED_REGS,
> +  { PTRACE_GETVFPREGS, PTRACE_SETVFPREGS, 0, ARM_VFP3_REGS_SIZE, OPTIONAL_REGS,
>      arm_fill_vfpregset, arm_store_vfpregset },
>    NULL_REGSET
>  };
> diff --git a/gdbsupport/tdesc.cc b/gdbsupport/tdesc.cc
> index 4d41d0b168a..0b0b765cb3d 100644
> --- a/gdbsupport/tdesc.cc
> +++ b/gdbsupport/tdesc.cc
> @@ -53,7 +53,6 @@ static tdesc_type_builtin tdesc_predefined_types[] =
>    { "ieee_half", TDESC_TYPE_IEEE_HALF },
>    { "ieee_single", TDESC_TYPE_IEEE_SINGLE },
>    { "ieee_double", TDESC_TYPE_IEEE_DOUBLE },
> -  { "arm_fpa_ext", TDESC_TYPE_ARM_FPA_EXT },
>    { "i387_ext", TDESC_TYPE_I387_EXT },
>    { "bfloat16", TDESC_TYPE_BFLOAT16 }
>  };
> diff --git a/gdbsupport/tdesc.h b/gdbsupport/tdesc.h
> index 403aa2c3d19..082819ada13 100644
> --- a/gdbsupport/tdesc.h
> +++ b/gdbsupport/tdesc.h
> @@ -171,7 +171,6 @@ enum tdesc_type_kind
>    TDESC_TYPE_IEEE_HALF,
>    TDESC_TYPE_IEEE_SINGLE,
>    TDESC_TYPE_IEEE_DOUBLE,
> -  TDESC_TYPE_ARM_FPA_EXT,
>    TDESC_TYPE_I387_EXT,
>    TDESC_TYPE_BFLOAT16,
  
Luis Machado Oct. 3, 2022, 8:27 a.m. UTC | #3
Hi,

On 10/2/22 14:39, Enze Li wrote:
> On Tue, Sep 20 2022 at 01:30:12 PM +0100, Luis Machado via Gdb-patches wrote:
> 
>> FPA has been deprecated for a while now. It was removed from GCC in 2012,
>> but somehow it managed to survive in GDB for a little while longer.
>>
>> It is time to let FPA rest in peace.
>>
>> While at it, make VFP the default floating point model for 32-bit Arm.
>>
>> It would be nice to get some *BSD testing as some changes touch that code
>> and I'm not properly setup to validate the changes for those OS'.
> 
> Hi Luis,
> 
> I have tested this patch on FreeBSD, NetBSD and OpenBSD and found no
> build errors.  All these tests are based on this commit[1].

That's great. Thanks for testing on those OS'. I'll push this one soon then.

Regards,
Luis

> 
> [1] 6519cd1a15fda2b67ae3e4ad8a2758615d3e0f9f
> 
> Thanks,
> Enze
> 
>> ---
>>   gdb/NEWS                                    |   4 +
>>   gdb/aarch64-linux-nat.c                     |   4 +-
>>   gdb/arch/arm.c                              |   5 -
>>   gdb/arch/arm.h                              |   9 -
>>   gdb/arm-bsd-tdep.c                          |  48 ----
>>   gdb/arm-linux-nat.c                         | 106 +-------
>>   gdb/arm-linux-tdep.c                        | 131 +--------
>>   gdb/arm-linux-tdep.h                        |  29 --
>>   gdb/arm-netbsd-nat.c                        |   4 +-
>>   gdb/arm-tdep.c                              | 286 +-------------------
>>   gdb/arm-tdep.h                              |   3 -
>>   gdb/doc/gdb.texinfo                         |  13 +-
>>   gdb/features/Makefile                       |   2 -
>>   gdb/features/arm/arm-fpa.c                  |  23 --
>>   gdb/features/arm/arm-fpa.xml                |  23 --
>>   gdb/features/arm/arm-m-profile-with-fpa.c   |  39 ---
>>   gdb/features/arm/arm-m-profile-with-fpa.xml |  39 ---
>>   gdb/target-descriptions.c                   |   4 -
>>   gdb/testsuite/gdb.base/long_long.exp        |  18 +-
>>   gdbserver/linux-arm-low.cc                  |   7 +-
>>   gdbsupport/tdesc.cc                         |   1 -
>>   gdbsupport/tdesc.h                          |   1 -
>>   22 files changed, 33 insertions(+), 766 deletions(-)
>>   delete mode 100644 gdb/features/arm/arm-fpa.c
>>   delete mode 100644 gdb/features/arm/arm-fpa.xml
>>   delete mode 100644 gdb/features/arm/arm-m-profile-with-fpa.c
>>   delete mode 100644 gdb/features/arm/arm-m-profile-with-fpa.xml
>>
>> diff --git a/gdb/NEWS b/gdb/NEWS
>> index 555ef2ddf77..fcd7b686e02 100644
>> --- a/gdb/NEWS
>> +++ b/gdb/NEWS
>> @@ -3,6 +3,10 @@
>>   
>>   *** Changes since GDB 12
>>   
>> +* Removed support for the 32-bit Arm FPA floating point format.  FPA is an
>> +  old floating point format that is no longer supported in GCC since at least
>> +  2012.
>> +
>>   * GDB now supports dumping memory tag data for AArch64 MTE.  It also supports
>>     reading memory tag data for AArch64 MTE from core files generated by
>>     the gcore command or the Linux kernel.
>> diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c
>> index eda79ec6d35..4d36cd47567 100644
>> --- a/gdb/aarch64-linux-nat.c
>> +++ b/gdb/aarch64-linux-nat.c
>> @@ -551,7 +551,7 @@ aarch32_fetch_registers (struct regcache *regcache, int regno)
>>         if (tdep->vfp_register_count > 0)
>>   	fetch_fpregs_from_thread (regcache);
>>       }
>> -  else if (regno < ARM_F0_REGNUM || regno == ARM_PS_REGNUM)
>> +  else if (regno <= ARM_PC_REGNUM || regno == ARM_PS_REGNUM)
>>       fetch_gregs_from_thread (regcache);
>>     else if (tdep->vfp_register_count > 0
>>   	   && regno >= ARM_D0_REGNUM
>> @@ -627,7 +627,7 @@ aarch32_store_registers (struct regcache *regcache, int regno)
>>         if (tdep->vfp_register_count > 0)
>>   	store_fpregs_to_thread (regcache);
>>       }
>> -  else if (regno < ARM_F0_REGNUM || regno == ARM_PS_REGNUM)
>> +  else if (regno <= ARM_PC_REGNUM || regno == ARM_PS_REGNUM)
>>       store_gregs_to_thread (regcache);
>>     else if (tdep->vfp_register_count > 0
>>   	   && regno >= ARM_D0_REGNUM
>> diff --git a/gdb/arch/arm.c b/gdb/arch/arm.c
>> index 14f0a7a7f6c..9771a60f30f 100644
>> --- a/gdb/arch/arm.c
>> +++ b/gdb/arch/arm.c
>> @@ -27,7 +27,6 @@
>>   #include "../features/arm/arm-vfpv3.c"
>>   #include "../features/arm/xscale-iwmmxt.c"
>>   #include "../features/arm/arm-m-profile.c"
>> -#include "../features/arm/arm-m-profile-with-fpa.c"
>>   #include "../features/arm/arm-m-profile-mve.c"
>>   #include "../features/arm/arm-m-system.c"
>>   
>> @@ -441,10 +440,6 @@ arm_create_mprofile_target_description (arm_m_profile_type m_type)
>>         regnum = create_feature_arm_arm_vfpv2 (tdesc, regnum);
>>         break;
>>   
>> -    case ARM_M_TYPE_WITH_FPA:
>> -      regnum = create_feature_arm_arm_m_profile_with_fpa (tdesc, regnum);
>> -      break;
>> -
>>       case ARM_M_TYPE_MVE:
>>         regnum = create_feature_arm_arm_m_profile (tdesc, regnum);
>>         regnum = create_feature_arm_arm_vfpv2 (tdesc, regnum);
>> diff --git a/gdb/arch/arm.h b/gdb/arch/arm.h
>> index 36757493406..74a6ba93bc7 100644
>> --- a/gdb/arch/arm.h
>> +++ b/gdb/arch/arm.h
>> @@ -44,11 +44,6 @@ enum gdb_regnum {
>>     ARM_SP_REGNUM = 13,		/* Contains address of top of stack */
>>     ARM_LR_REGNUM = 14,		/* address to return to from a function call */
>>     ARM_PC_REGNUM = 15,		/* Contains program counter */
>> -  /* F0..F7 are the fp registers for the (obsolete) FPA architecture.  */
>> -  ARM_F0_REGNUM = 16,		/* first floating point register */
>> -  ARM_F3_REGNUM = 19,		/* last floating point argument register */
>> -  ARM_F7_REGNUM = 23, 		/* last floating point register */
>> -  ARM_FPS_REGNUM = 24,		/* floating point status register */
>>     ARM_PS_REGNUM = 25,		/* Contains processor status */
>>     ARM_WR0_REGNUM,		/* WMMX data registers.  */
>>     ARM_WR15_REGNUM = ARM_WR0_REGNUM + 15,
>> @@ -67,7 +62,6 @@ enum gdb_regnum {
>>     ARM_FP_REGNUM = 11,		/* Frame register in ARM code, if used.  */
>>     THUMB_FP_REGNUM = 7,		/* Frame register in Thumb code, if used.  */
>>     ARM_LAST_ARG_REGNUM = ARM_A4_REGNUM,
>> -  ARM_LAST_FP_ARG_REGNUM = ARM_F3_REGNUM
>>   };
>>   
>>   /* Register count constants.  */
>> @@ -103,7 +97,6 @@ enum arm_fp_type {
>>   enum arm_m_profile_type {
>>      ARM_M_TYPE_M_PROFILE,
>>      ARM_M_TYPE_VFP_D16,
>> -   ARM_M_TYPE_WITH_FPA,
>>      ARM_M_TYPE_MVE,
>>      ARM_M_TYPE_SYSTEM,
>>      ARM_M_TYPE_INVALID
>> @@ -157,8 +150,6 @@ enum system_register_address : CORE_ADDR
>>   
>>   /* r0-r12,sp,lr,pc,cpsr.  */
>>   #define ARM_CORE_REGS_SIZE (17 * ARM_INT_REGISTER_SIZE)
>> -/* f0-f8,fps.  */
>> -#define ARM_FP_REGS_SIZE (8 * ARM_FP_REGISTER_SIZE + ARM_INT_REGISTER_SIZE)
>>   /* d0-d15,fpscr.  */
>>   #define ARM_VFP2_REGS_SIZE (16 * ARM_VFP_REGISTER_SIZE + ARM_INT_REGISTER_SIZE)
>>   /* d0-d31,fpscr.  */
>> diff --git a/gdb/arm-bsd-tdep.c b/gdb/arm-bsd-tdep.c
>> index 13d6e527d58..72421bb26d5 100644
>> --- a/gdb/arm-bsd-tdep.c
>> +++ b/gdb/arm-bsd-tdep.c
>> @@ -29,39 +29,6 @@
>>   /* Sizeof `struct reg' in <machine/reg.h>.  */
>>   #define ARMBSD_SIZEOF_GREGS	(17 * 4)
>>   
>> -/* Sizeof `struct fpreg' in <machine/reg.h.  */
>> -#define ARMBSD_SIZEOF_FPREGS	((1 + (8 * 3)) * 4)
>> -
>> -static int
>> -armbsd_fpreg_offset (int regnum)
>> -{
>> -  if (regnum == ARM_FPS_REGNUM)
>> -    return 0;
>> -
>> -  return 4 + (regnum - ARM_F0_REGNUM) * 12;
>> -}
>> -
>> -/* Supply register REGNUM from the buffer specified by FPREGS and LEN
>> -   in the floating-point register set REGSET to register cache
>> -   REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
>> -
>> -static void
>> -armbsd_supply_fpregset (const struct regset *regset,
>> -			struct regcache *regcache,
>> -			int regnum, const void *fpregs, size_t len)
>> -{
>> -  const gdb_byte *regs = (const gdb_byte *) fpregs;
>> -  int i;
>> -
>> -  gdb_assert (len >= ARMBSD_SIZEOF_FPREGS);
>> -
>> -  for (i = ARM_F0_REGNUM; i <= ARM_FPS_REGNUM; i++)
>> -    {
>> -      if (regnum == i || regnum == -1)
>> -	regcache->raw_supply (i, regs + armbsd_fpreg_offset (i));
>> -    }
>> -}
>> -
>>   /* Supply register REGNUM from the buffer specified by GREGS and LEN
>>      in the general-purpose register set REGSET to register cache
>>      REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
>> @@ -84,13 +51,6 @@ armbsd_supply_gregset (const struct regset *regset,
>>   
>>     if (regnum == ARM_PS_REGNUM || regnum == -1)
>>       regcache->raw_supply (i, regs + 16 * 4);
>> -
>> -  if (len >= ARMBSD_SIZEOF_GREGS + ARMBSD_SIZEOF_FPREGS)
>> -    {
>> -      regs += ARMBSD_SIZEOF_GREGS;
>> -      len -= ARMBSD_SIZEOF_GREGS;
>> -      armbsd_supply_fpregset (regset, regcache, regnum, regs, len);
>> -    }
>>   }
>>   
>>   /* ARM register sets.  */
>> @@ -103,12 +63,6 @@ static const struct regset armbsd_gregset =
>>     REGSET_VARIABLE_SIZE
>>   };
>>   
>> -static const struct regset armbsd_fpregset =
>> -{
>> -  NULL,
>> -  armbsd_supply_fpregset
>> -};
>> -
>>   /* Iterate over supported core file register note sections. */
>>   
>>   void
>> @@ -119,6 +73,4 @@ armbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
>>   {
>>     cb (".reg", ARMBSD_SIZEOF_GREGS, ARMBSD_SIZEOF_GREGS, &armbsd_gregset, NULL,
>>         cb_data);
>> -  cb (".reg2", ARMBSD_SIZEOF_FPREGS, ARMBSD_SIZEOF_FPREGS, &armbsd_fpregset,
>> -      NULL, cb_data);
>>   }
>> diff --git a/gdb/arm-linux-nat.c b/gdb/arm-linux-nat.c
>> index 0188c78fe7a..a6a5745fdf9 100644
>> --- a/gdb/arm-linux-nat.c
>> +++ b/gdb/arm-linux-nat.c
>> @@ -109,96 +109,6 @@ class arm_linux_nat_target final : public linux_nat_target
>>   
>>   static arm_linux_nat_target the_arm_linux_nat_target;
>>   
>> -/* Get the whole floating point state of the process and store it
>> -   into regcache.  */
>> -
>> -static void
>> -fetch_fpregs (struct regcache *regcache)
>> -{
>> -  int ret, regno, tid;
>> -  gdb_byte fp[ARM_LINUX_SIZEOF_NWFPE];
>> -
>> -  /* Get the thread id for the ptrace call.  */
>> -  tid = regcache->ptid ().lwp ();
>> -
>> -  /* Read the floating point state.  */
>> -  if (have_ptrace_getregset == TRIBOOL_TRUE)
>> -    {
>> -      struct iovec iov;
>> -
>> -      iov.iov_base = &fp;
>> -      iov.iov_len = ARM_LINUX_SIZEOF_NWFPE;
>> -
>> -      ret = ptrace (PTRACE_GETREGSET, tid, NT_FPREGSET, &iov);
>> -    }
>> -  else
>> -    ret = ptrace (PT_GETFPREGS, tid, 0, fp);
>> -
>> -  if (ret < 0)
>> -    perror_with_name (_("Unable to fetch the floating point registers"));
>> -
>> -  /* Fetch fpsr.  */
>> -  regcache->raw_supply (ARM_FPS_REGNUM, fp + NWFPE_FPSR_OFFSET);
>> -
>> -  /* Fetch the floating point registers.  */
>> -  for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
>> -    supply_nwfpe_register (regcache, regno, fp);
>> -}
>> -
>> -/* Save the whole floating point state of the process using
>> -   the contents from regcache.  */
>> -
>> -static void
>> -store_fpregs (const struct regcache *regcache)
>> -{
>> -  int ret, regno, tid;
>> -  gdb_byte fp[ARM_LINUX_SIZEOF_NWFPE];
>> -
>> -  /* Get the thread id for the ptrace call.  */
>> -  tid = regcache->ptid ().lwp ();
>> -
>> -  /* Read the floating point state.  */
>> -  if (have_ptrace_getregset == TRIBOOL_TRUE)
>> -    {
>> -      elf_fpregset_t fpregs;
>> -      struct iovec iov;
>> -
>> -      iov.iov_base = &fpregs;
>> -      iov.iov_len = sizeof (fpregs);
>> -
>> -      ret = ptrace (PTRACE_GETREGSET, tid, NT_FPREGSET, &iov);
>> -    }
>> -  else
>> -    ret = ptrace (PT_GETFPREGS, tid, 0, fp);
>> -
>> -  if (ret < 0)
>> -    perror_with_name (_("Unable to fetch the floating point registers"));
>> -
>> -  /* Store fpsr.  */
>> -  if (REG_VALID == regcache->get_register_status (ARM_FPS_REGNUM))
>> -    regcache->raw_collect (ARM_FPS_REGNUM, fp + NWFPE_FPSR_OFFSET);
>> -
>> -  /* Store the floating point registers.  */
>> -  for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
>> -    if (REG_VALID == regcache->get_register_status (regno))
>> -      collect_nwfpe_register (regcache, regno, fp);
>> -
>> -  if (have_ptrace_getregset == TRIBOOL_TRUE)
>> -    {
>> -      struct iovec iov;
>> -
>> -      iov.iov_base = &fp;
>> -      iov.iov_len = ARM_LINUX_SIZEOF_NWFPE;
>> -
>> -      ret = ptrace (PTRACE_SETREGSET, tid, NT_FPREGSET, &iov);
>> -    }
>> -  else
>> -    ret = ptrace (PTRACE_SETFPREGS, tid, 0, fp);
>> -
>> -  if (ret < 0)
>> -    perror_with_name (_("Unable to store floating point registers"));
>> -}
>> -
>>   /* Fetch all general registers of the process and store into
>>      regcache.  */
>>   
>> @@ -422,15 +332,11 @@ arm_linux_nat_target::fetch_registers (struct regcache *regcache, int regno)
>>   	fetch_wmmx_regs (regcache);
>>         if (tdep->vfp_register_count > 0)
>>   	fetch_vfp_regs (regcache);
>> -      if (tdep->have_fpa_registers)
>> -	fetch_fpregs (regcache);
>>       }
>>     else
>>       {
>> -      if (regno < ARM_F0_REGNUM || regno == ARM_PS_REGNUM)
>> +      if (regno <= ARM_PC_REGNUM || regno == ARM_PS_REGNUM)
>>   	fetch_regs (regcache);
>> -      else if (regno >= ARM_F0_REGNUM && regno <= ARM_FPS_REGNUM)
>> -	fetch_fpregs (regcache);
>>         else if (tdep->have_wmmx_registers
>>   	       && regno >= ARM_WR0_REGNUM && regno <= ARM_WCGR7_REGNUM)
>>   	fetch_wmmx_regs (regcache);
>> @@ -459,15 +365,11 @@ arm_linux_nat_target::store_registers (struct regcache *regcache, int regno)
>>   	store_wmmx_regs (regcache);
>>         if (tdep->vfp_register_count > 0)
>>   	store_vfp_regs (regcache);
>> -      if (tdep->have_fpa_registers)
>> -	store_fpregs (regcache);
>>       }
>>     else
>>       {
>> -      if (regno < ARM_F0_REGNUM || regno == ARM_PS_REGNUM)
>> +      if (regno <= ARM_PC_REGNUM || regno == ARM_PS_REGNUM)
>>   	store_regs (regcache);
>> -      else if ((regno >= ARM_F0_REGNUM) && (regno <= ARM_FPS_REGNUM))
>> -	store_fpregs (regcache);
>>         else if (tdep->have_wmmx_registers
>>   	       && regno >= ARM_WR0_REGNUM && regno <= ARM_WCGR7_REGNUM)
>>   	store_wmmx_regs (regcache);
>> @@ -499,7 +401,7 @@ void
>>   fill_fpregset (const struct regcache *regcache,
>>   	       gdb_fpregset_t *fpregsetp, int regno)
>>   {
>> -  arm_linux_collect_nwfpe (NULL, regcache, regno, fpregsetp, 0);
>> +  /* FPA is no longer supported.  */
>>   }
>>   
>>   /* Fill GDB's register array with the floating-point register values
>> @@ -508,7 +410,7 @@ fill_fpregset (const struct regcache *regcache,
>>   void
>>   supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregsetp)
>>   {
>> -  arm_linux_supply_nwfpe (NULL, regcache, -1, fpregsetp, 0);
>> +  /* FPA is no longer supported.  */
>>   }
>>   
>>   /* Fetch the thread-local storage pointer for libthread_db.  */
>> diff --git a/gdb/arm-linux-tdep.c b/gdb/arm-linux-tdep.c
>> index 1feb69fe6dd..d5ada33a05c 100644
>> --- a/gdb/arm-linux-tdep.c
>> +++ b/gdb/arm-linux-tdep.c
>> @@ -102,10 +102,8 @@ static const gdb_byte arm_linux_thumb2_le_breakpoint[] = { 0xf0, 0xf7, 0x00, 0xa
>>   
>>      For glibc, eglibc, and uclibc the following holds:  If the FP model is
>>      SoftVFP or VFP (which implies EABI) then the PC is at offset 9 in the
>> -   buffer.  This is also true for the SoftFPA model.  However, for the FPA
>> -   model the PC is at offset 21 in the buffer.  */
>> +   buffer.  */
>>   #define ARM_LINUX_JB_ELEMENT_SIZE	ARM_INT_REGISTER_SIZE
>> -#define ARM_LINUX_JB_PC_FPA		21
>>   #define ARM_LINUX_JB_PC_EABI		9
>>   
>>   /*
>> @@ -540,119 +538,6 @@ arm_linux_collect_gregset (const struct regset *regset,
>>   			   gregs + ARM_INT_REGISTER_SIZE * ARM_PC_REGNUM);
>>   }
>>   
>> -/* Support for register format used by the NWFPE FPA emulator.  */
>> -
>> -#define typeNone		0x00
>> -#define typeSingle		0x01
>> -#define typeDouble		0x02
>> -#define typeExtended		0x03
>> -
>> -void
>> -supply_nwfpe_register (struct regcache *regcache, int regno,
>> -		       const gdb_byte *regs)
>> -{
>> -  const gdb_byte *reg_data;
>> -  gdb_byte reg_tag;
>> -  gdb_byte buf[ARM_FP_REGISTER_SIZE];
>> -
>> -  reg_data = regs + (regno - ARM_F0_REGNUM) * ARM_FP_REGISTER_SIZE;
>> -  reg_tag = regs[(regno - ARM_F0_REGNUM) + NWFPE_TAGS_OFFSET];
>> -  memset (buf, 0, ARM_FP_REGISTER_SIZE);
>> -
>> -  switch (reg_tag)
>> -    {
>> -    case typeSingle:
>> -      memcpy (buf, reg_data, 4);
>> -      break;
>> -    case typeDouble:
>> -      memcpy (buf, reg_data + 4, 4);
>> -      memcpy (buf + 4, reg_data, 4);
>> -      break;
>> -    case typeExtended:
>> -      /* We want sign and exponent, then least significant bits,
>> -	 then most significant.  NWFPE does sign, most, least.  */
>> -      memcpy (buf, reg_data, 4);
>> -      memcpy (buf + 4, reg_data + 8, 4);
>> -      memcpy (buf + 8, reg_data + 4, 4);
>> -      break;
>> -    default:
>> -      break;
>> -    }
>> -
>> -  regcache->raw_supply (regno, buf);
>> -}
>> -
>> -void
>> -collect_nwfpe_register (const struct regcache *regcache, int regno,
>> -			gdb_byte *regs)
>> -{
>> -  gdb_byte *reg_data;
>> -  gdb_byte reg_tag;
>> -  gdb_byte buf[ARM_FP_REGISTER_SIZE];
>> -
>> -  regcache->raw_collect (regno, buf);
>> -
>> -  /* NOTE drow/2006-06-07: This code uses the tag already in the
>> -     register buffer.  I've preserved that when moving the code
>> -     from the native file to the target file.  But this doesn't
>> -     always make sense.  */
>> -
>> -  reg_data = regs + (regno - ARM_F0_REGNUM) * ARM_FP_REGISTER_SIZE;
>> -  reg_tag = regs[(regno - ARM_F0_REGNUM) + NWFPE_TAGS_OFFSET];
>> -
>> -  switch (reg_tag)
>> -    {
>> -    case typeSingle:
>> -      memcpy (reg_data, buf, 4);
>> -      break;
>> -    case typeDouble:
>> -      memcpy (reg_data, buf + 4, 4);
>> -      memcpy (reg_data + 4, buf, 4);
>> -      break;
>> -    case typeExtended:
>> -      memcpy (reg_data, buf, 4);
>> -      memcpy (reg_data + 4, buf + 8, 4);
>> -      memcpy (reg_data + 8, buf + 4, 4);
>> -      break;
>> -    default:
>> -      break;
>> -    }
>> -}
>> -
>> -void
>> -arm_linux_supply_nwfpe (const struct regset *regset,
>> -			struct regcache *regcache,
>> -			int regnum, const void *regs_buf, size_t len)
>> -{
>> -  const gdb_byte *regs = (const gdb_byte *) regs_buf;
>> -  int regno;
>> -
>> -  if (regnum == ARM_FPS_REGNUM || regnum == -1)
>> -    regcache->raw_supply (ARM_FPS_REGNUM,
>> -			 regs + NWFPE_FPSR_OFFSET);
>> -
>> -  for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
>> -    if (regnum == -1 || regnum == regno)
>> -      supply_nwfpe_register (regcache, regno, regs);
>> -}
>> -
>> -void
>> -arm_linux_collect_nwfpe (const struct regset *regset,
>> -			 const struct regcache *regcache,
>> -			 int regnum, void *regs_buf, size_t len)
>> -{
>> -  gdb_byte *regs = (gdb_byte *) regs_buf;
>> -  int regno;
>> -
>> -  for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
>> -    if (regnum == -1 || regnum == regno)
>> -      collect_nwfpe_register (regcache, regno, regs);
>> -
>> -  if (regnum == ARM_FPS_REGNUM || regnum == -1)
>> -    regcache->raw_collect (ARM_FPS_REGNUM,
>> -			   regs + ARM_INT_REGISTER_SIZE * ARM_FPS_REGNUM);
>> -}
>> -
>>   /* Support VFP register format.  */
>>   
>>   #define ARM_LINUX_SIZEOF_VFP (32 * 8 + 4)
>> @@ -694,11 +579,6 @@ static const struct regset arm_linux_gregset =
>>       NULL, arm_linux_supply_gregset, arm_linux_collect_gregset
>>     };
>>   
>> -static const struct regset arm_linux_fpregset =
>> -  {
>> -    NULL, arm_linux_supply_nwfpe, arm_linux_collect_nwfpe
>> -  };
>> -
>>   static const struct regset arm_linux_vfpregset =
>>     {
>>       NULL, arm_linux_supply_vfp, arm_linux_collect_vfp
>> @@ -720,9 +600,6 @@ arm_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
>>     if (tdep->vfp_register_count > 0)
>>       cb (".reg-arm-vfp", ARM_LINUX_SIZEOF_VFP, ARM_LINUX_SIZEOF_VFP,
>>   	&arm_linux_vfpregset, "VFP floating-point", cb_data);
>> -  else if (tdep->have_fpa_registers)
>> -    cb (".reg2", ARM_LINUX_SIZEOF_NWFPE, ARM_LINUX_SIZEOF_NWFPE,
>> -	&arm_linux_fpregset, "FPA floating-point", cb_data);
>>   }
>>   
>>   /* Determine target description from core file.  */
>> @@ -1744,14 +1621,10 @@ arm_linux_init_abi (struct gdbarch_info info,
>>     tdep->thumb2_breakpoint_size = sizeof (arm_linux_thumb2_le_breakpoint);
>>   
>>     if (tdep->fp_model == ARM_FLOAT_AUTO)
>> -    tdep->fp_model = ARM_FLOAT_FPA;
>> +    tdep->fp_model = ARM_FLOAT_SOFT_VFP;
>>   
>>     switch (tdep->fp_model)
>>       {
>> -    case ARM_FLOAT_FPA:
>> -      tdep->jb_pc = ARM_LINUX_JB_PC_FPA;
>> -      break;
>> -    case ARM_FLOAT_SOFT_FPA:
>>       case ARM_FLOAT_SOFT_VFP:
>>       case ARM_FLOAT_VFP:
>>         tdep->jb_pc = ARM_LINUX_JB_PC_EABI;
>> diff --git a/gdb/arm-linux-tdep.h b/gdb/arm-linux-tdep.h
>> index 6ed55acf9b0..cb92c3f6bbe 100644
>> --- a/gdb/arm-linux-tdep.h
>> +++ b/gdb/arm-linux-tdep.h
>> @@ -23,23 +23,6 @@
>>   struct regset;
>>   struct regcache;
>>   
>> -#define ARM_LINUX_SIZEOF_NWFPE (8 * ARM_FP_REGISTER_SIZE \
>> -				+ 2 * ARM_INT_REGISTER_SIZE \
>> -				+ 8 + ARM_INT_REGISTER_SIZE)
>> -
>> -/* Support for register format used by the NWFPE FPA emulator.  Each
>> -   register takes three words, where either the first one, two, or
>> -   three hold a single, double, or extended precision value (depending
>> -   on the corresponding tag).  The register set is eight registers,
>> -   followed by the fpsr and fpcr, followed by eight tag bytes, and a
>> -   final word flag which indicates whether NWFPE has been
>> -   initialized.  */
>> -
>> -#define NWFPE_FPSR_OFFSET (8 * ARM_FP_REGISTER_SIZE)
>> -#define NWFPE_FPCR_OFFSET (NWFPE_FPSR_OFFSET + ARM_INT_REGISTER_SIZE)
>> -#define NWFPE_TAGS_OFFSET (NWFPE_FPCR_OFFSET + ARM_INT_REGISTER_SIZE)
>> -#define NWFPE_INITFLAG_OFFSET (NWFPE_TAGS_OFFSET + 8)
>> -
>>   void arm_linux_supply_gregset (const struct regset *regset,
>>   			       struct regcache *regcache,
>>   			       int regnum, const void *gregs_buf, size_t len);
>> @@ -47,18 +30,6 @@ void arm_linux_collect_gregset (const struct regset *regset,
>>   				const struct regcache *regcache,
>>   				int regnum, void *gregs_buf, size_t len);
>>   
>> -void supply_nwfpe_register (struct regcache *regcache, int regno,
>> -			    const gdb_byte *regs);
>> -void collect_nwfpe_register (const struct regcache *regcache, int regno,
>> -			     gdb_byte *regs);
>> -
>> -void arm_linux_supply_nwfpe (const struct regset *regset,
>> -			     struct regcache *regcache,
>> -			     int regnum, const void *regs_buf, size_t len);
>> -void arm_linux_collect_nwfpe (const struct regset *regset,
>> -			      const struct regcache *regcache,
>> -			      int regnum, void *regs_buf, size_t len);
>> -
>>   /* ARM GNU/Linux HWCAP values.  These are in defined in
>>      <asm/elf.h> in current kernels.  */
>>   #define HWCAP_VFP       64
>> diff --git a/gdb/arm-netbsd-nat.c b/gdb/arm-netbsd-nat.c
>> index 251159154c9..d37a1951c21 100644
>> --- a/gdb/arm-netbsd-nat.c
>> +++ b/gdb/arm-netbsd-nat.c
>> @@ -135,7 +135,7 @@ arm_netbsd_nat_target::fetch_registers (struct regcache *regcache, int regno)
>>   {
>>     if (regno >= 0)
>>       {
>> -      if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
>> +      if (regno <= ARM_PC_REGNUM || regno >= ARM_PS_REGNUM)
>>   	fetch_register (regcache, regno);
>>         else
>>   	fetch_fp_register (regcache, regno);
>> @@ -326,7 +326,7 @@ arm_netbsd_nat_target::store_registers (struct regcache *regcache, int regno)
>>   {
>>     if (regno >= 0)
>>       {
>> -      if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
>> +      if (regno <= ARM_PC_REGNUM || regno >= ARM_PS_REGNUM)
>>   	store_register (regcache, regno);
>>         else
>>   	store_fp_register (regcache, regno);
>> diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
>> index ead9bbf46c5..b33a53612a6 100644
>> --- a/gdb/arm-tdep.c
>> +++ b/gdb/arm-tdep.c
>> @@ -134,8 +134,6 @@ static struct cmd_list_element *showarmcmdlist = NULL;
>>   static const char *const fp_model_strings[] =
>>   {
>>     "auto",
>> -  "softfpa",
>> -  "fpa",
>>     "softvfp",
>>     "vfp",
>>     NULL
>> @@ -226,9 +224,7 @@ static const char *const arm_register_names[] =
>>    "r4",  "r5",  "r6",  "r7",	/*  4  5  6  7 */
>>    "r8",  "r9",  "r10", "r11",	/*  8  9 10 11 */
>>    "r12", "sp",  "lr",  "pc",	/* 12 13 14 15 */
>> - "f0",  "f1",  "f2",  "f3",	/* 16 17 18 19 */
>> - "f4",  "f5",  "f6",  "f7",	/* 20 21 22 23 */
>> - "fps", "cpsr" };		/* 24 25       */
>> + "cpsr" };			/* 25 */
>>   
>>   /* Holds the current set of options to be passed to the disassembler.  */
>>   static char *arm_disassembler_options;
>> @@ -1877,7 +1873,7 @@ arm_analyze_prologue (struct gdbarch *gdbarch,
>>     enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
>>     int regno;
>>     CORE_ADDR offset, current_pc;
>> -  pv_t regs[ARM_FPS_REGNUM];
>> +  pv_t regs[ARM_PC_REGNUM];
>>     CORE_ADDR unrecognized_pc = 0;
>>     arm_gdbarch_tdep *tdep = gdbarch_tdep<arm_gdbarch_tdep> (gdbarch);
>>   
>> @@ -1891,7 +1887,7 @@ arm_analyze_prologue (struct gdbarch *gdbarch,
>>        and other operations that rely on a knowledge of the stack
>>        traceback.  */
>>   
>> -  for (regno = 0; regno < ARM_FPS_REGNUM; regno++)
>> +  for (regno = 0; regno < ARM_PC_REGNUM; regno++)
>>       regs[regno] = pv_register (regno, 0);
>>     pv_area stack (ARM_SP_REGNUM, gdbarch_addr_bit (gdbarch));
>>   
>> @@ -1982,51 +1978,6 @@ arm_analyze_prologue (struct gdbarch *gdbarch,
>>   	  uint32_t imm = arm_expand_immediate(insn & 0xfff);
>>   	  regs[ARM_SP_REGNUM] = pv_add_constant (regs[ARM_SP_REGNUM], -imm);
>>   	}
>> -      else if ((insn & 0xffff7fff) == 0xed6d0103	/* stfe f?,
>> -							   [sp, -#c]! */
>> -	       && tdep->have_fpa_registers)
>> -	{
>> -	  if (stack.store_would_trash (regs[ARM_SP_REGNUM]))
>> -	    break;
>> -
>> -	  regs[ARM_SP_REGNUM] = pv_add_constant (regs[ARM_SP_REGNUM], -12);
>> -	  regno = ARM_F0_REGNUM + ((insn >> 12) & 0x07);
>> -	  stack.store (regs[ARM_SP_REGNUM], 12, regs[regno]);
>> -	}
>> -      else if ((insn & 0xffbf0fff) == 0xec2d0200	/* sfmfd f0, 4,
>> -							   [sp!] */
>> -	       && tdep->have_fpa_registers)
>> -	{
>> -	  int n_saved_fp_regs;
>> -	  unsigned int fp_start_reg, fp_bound_reg;
>> -
>> -	  if (stack.store_would_trash (regs[ARM_SP_REGNUM]))
>> -	    break;
>> -
>> -	  if ((insn & 0x800) == 0x800)		/* N0 is set */
>> -	    {
>> -	      if ((insn & 0x40000) == 0x40000)	/* N1 is set */
>> -		n_saved_fp_regs = 3;
>> -	      else
>> -		n_saved_fp_regs = 1;
>> -	    }
>> -	  else
>> -	    {
>> -	      if ((insn & 0x40000) == 0x40000)	/* N1 is set */
>> -		n_saved_fp_regs = 2;
>> -	      else
>> -		n_saved_fp_regs = 4;
>> -	    }
>> -
>> -	  fp_start_reg = ARM_F0_REGNUM + ((insn >> 12) & 0x7);
>> -	  fp_bound_reg = fp_start_reg + n_saved_fp_regs;
>> -	  for (; fp_start_reg < fp_bound_reg; fp_start_reg++)
>> -	    {
>> -	      regs[ARM_SP_REGNUM] = pv_add_constant (regs[ARM_SP_REGNUM], -12);
>> -	      stack.store (regs[ARM_SP_REGNUM], 12,
>> -			   regs[fp_start_reg++]);
>> -	    }
>> -	}
>>         else if ((insn & 0xff000000) == 0xeb000000 && cache == NULL) /* bl */
>>   	{
>>   	  /* Allow some special function calls when skipping the
>> @@ -2103,7 +2054,7 @@ arm_analyze_prologue (struct gdbarch *gdbarch,
>>         cache->framereg = framereg;
>>         cache->framesize = framesize;
>>   
>> -      for (regno = 0; regno < ARM_FPS_REGNUM; regno++)
>> +      for (regno = 0; regno < ARM_PC_REGNUM; regno++)
>>   	if (stack.find_reg (gdbarch, regno, &offset))
>>   	  {
>>   	    cache->saved_regs[regno].set_addr (offset);
>> @@ -4666,58 +4617,6 @@ arm_frame_align (struct gdbarch *gdbarch, CORE_ADDR sp)
>>     return sp & ~ (CORE_ADDR) 7;
>>   }
>>   
>> -static void
>> -print_fpu_flags (struct ui_file *file, int flags)
>> -{
>> -  if (flags & (1 << 0))
>> -    gdb_puts ("IVO ", file);
>> -  if (flags & (1 << 1))
>> -    gdb_puts ("DVZ ", file);
>> -  if (flags & (1 << 2))
>> -    gdb_puts ("OFL ", file);
>> -  if (flags & (1 << 3))
>> -    gdb_puts ("UFL ", file);
>> -  if (flags & (1 << 4))
>> -    gdb_puts ("INX ", file);
>> -  gdb_putc ('\n', file);
>> -}
>> -
>> -/* Print interesting information about the floating point processor
>> -   (if present) or emulator.  */
>> -static void
>> -arm_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
>> -		      struct frame_info *frame, const char *args)
>> -{
>> -  unsigned long status = get_frame_register_unsigned (frame, ARM_FPS_REGNUM);
>> -  int type;
>> -
>> -  type = (status >> 24) & 127;
>> -  if (status & (1 << 31))
>> -    gdb_printf (file, _("Hardware FPU type %d\n"), type);
>> -  else
>> -    gdb_printf (file, _("Software FPU type %d\n"), type);
>> -  /* i18n: [floating point unit] mask */
>> -  gdb_puts (_("mask: "), file);
>> -  print_fpu_flags (file, status >> 16);
>> -  /* i18n: [floating point unit] flags */
>> -  gdb_puts (_("flags: "), file);
>> -  print_fpu_flags (file, status);
>> -}
>> -
>> -/* Construct the ARM extended floating point type.  */
>> -static struct type *
>> -arm_ext_type (struct gdbarch *gdbarch)
>> -{
>> -  arm_gdbarch_tdep *tdep = gdbarch_tdep<arm_gdbarch_tdep> (gdbarch);
>> -
>> -  if (!tdep->arm_ext_type)
>> -    tdep->arm_ext_type
>> -      = arch_float_type (gdbarch, -1, "builtin_type_arm_ext",
>> -			 floatformats_arm_ext);
>> -
>> -  return tdep->arm_ext_type;
>> -}
>> -
>>   static struct type *
>>   arm_neon_double_type (struct gdbarch *gdbarch)
>>   {
>> @@ -4902,14 +4801,7 @@ arm_register_type (struct gdbarch *gdbarch, int regnum)
>>   	return t;
>>       }
>>   
>> -  if (regnum >= ARM_F0_REGNUM && regnum < ARM_F0_REGNUM + NUM_FREGS)
>> -    {
>> -      if (!tdep->have_fpa_registers)
>> -	return builtin_type (gdbarch)->builtin_void;
>> -
>> -      return arm_ext_type (gdbarch);
>> -    }
>> -  else if (regnum == ARM_SP_REGNUM)
>> +  if (regnum == ARM_SP_REGNUM)
>>       return builtin_type (gdbarch)->builtin_data_ptr;
>>     else if (regnum == ARM_PC_REGNUM)
>>       return builtin_type (gdbarch)->builtin_func_ptr;
>> @@ -4931,17 +4823,6 @@ arm_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int reg)
>>     if (reg >= 0 && reg <= 15)
>>       return reg;
>>   
>> -  /* Legacy FPA encoding.  These were once used in a way which
>> -     overlapped with VFP register numbering, so their use is
>> -     discouraged, but GDB doesn't support the ARM toolchain
>> -     which used them for VFP.  */
>> -  if (reg >= 16 && reg <= 23)
>> -    return ARM_F0_REGNUM + reg - 16;
>> -
>> -  /* New assignments for the FPA registers.  */
>> -  if (reg >= 96 && reg <= 103)
>> -    return ARM_F0_REGNUM + reg - 96;
>> -
>>     /* WMMX register assignments.  */
>>     if (reg >= 104 && reg <= 111)
>>       return ARM_WCGR0_REGNUM + reg - 104;
>> @@ -5014,14 +4895,6 @@ arm_register_sim_regno (struct gdbarch *gdbarch, int regnum)
>>       return SIM_ARM_R0_REGNUM + reg;
>>     reg -= NUM_GREGS;
>>   
>> -  if (reg < NUM_FREGS)
>> -    return SIM_ARM_FP0_REGNUM + reg;
>> -  reg -= NUM_FREGS;
>> -
>> -  if (reg < NUM_SREGS)
>> -    return SIM_ARM_FPS_REGNUM + reg;
>> -  reg -= NUM_SREGS;
>> -
>>     internal_error (__FILE__, __LINE__, _("Bad REGNUM %d"), regnum);
>>   }
>>   
>> @@ -8686,20 +8559,6 @@ arm_extract_return_value (struct type *type, struct regcache *regs,
>>       {
>>         switch (tdep->fp_model)
>>   	{
>> -	case ARM_FLOAT_FPA:
>> -	  {
>> -	    /* The value is in register F0 in internal format.  We need to
>> -	       extract the raw value and then convert it to the desired
>> -	       internal type.  */
>> -	    bfd_byte tmpbuf[ARM_FP_REGISTER_SIZE];
>> -
>> -	    regs->cooked_read (ARM_F0_REGNUM, tmpbuf);
>> -	    target_float_convert (tmpbuf, arm_ext_type (gdbarch),
>> -				  valbuf, type);
>> -	  }
>> -	  break;
>> -
>> -	case ARM_FLOAT_SOFT_FPA:
>>   	case ARM_FLOAT_SOFT_VFP:
>>   	  /* ARM_FLOAT_VFP can arise if this is a variadic function so
>>   	     not using the VFP ABI code.  */
>> @@ -8896,18 +8755,10 @@ arm_store_return_value (struct type *type, struct regcache *regs,
>>   
>>     if (type->code () == TYPE_CODE_FLT)
>>       {
>> -      gdb_byte buf[ARM_FP_REGISTER_SIZE];
>>         arm_gdbarch_tdep *tdep = gdbarch_tdep<arm_gdbarch_tdep> (gdbarch);
>>   
>>         switch (tdep->fp_model)
>>   	{
>> -	case ARM_FLOAT_FPA:
>> -
>> -	  target_float_convert (valbuf, type, buf, arm_ext_type (gdbarch));
>> -	  regs->cooked_write (ARM_F0_REGNUM, buf);
>> -	  break;
>> -
>> -	case ARM_FLOAT_SOFT_FPA:
>>   	case ARM_FLOAT_SOFT_VFP:
>>   	  /* ARM_FLOAT_VFP can arise if this is a variadic function so
>>   	     not using the VFP ABI code.  */
>> @@ -9722,71 +9573,6 @@ arm_elf_osabi_sniffer (bfd *abfd)
>>     return osabi;
>>   }
>>   
>> -static int
>> -arm_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
>> -			 const struct reggroup *group)
>> -{
>> -  /* FPS register's type is INT, but belongs to float_reggroup.  Beside
>> -     this, FPS register belongs to save_regroup, restore_reggroup, and
>> -     all_reggroup, of course.  */
>> -  if (regnum == ARM_FPS_REGNUM)
>> -    return (group == float_reggroup
>> -	    || group == save_reggroup
>> -	    || group == restore_reggroup
>> -	    || group == all_reggroup);
>> -  else
>> -    return default_register_reggroup_p (gdbarch, regnum, group);
>> -}
>> -
>> -/* For backward-compatibility we allow two 'g' packet lengths with
>> -   the remote protocol depending on whether FPA registers are
>> -   supplied.  M-profile targets do not have FPA registers, but some
>> -   stubs already exist in the wild which use a 'g' packet which
>> -   supplies them albeit with dummy values.  The packet format which
>> -   includes FPA registers should be considered deprecated for
>> -   M-profile targets.  */
>> -
>> -static void
>> -arm_register_g_packet_guesses (struct gdbarch *gdbarch)
>> -{
>> -  arm_gdbarch_tdep *tdep = gdbarch_tdep<arm_gdbarch_tdep> (gdbarch);
>> -
>> -  if (tdep->is_m)
>> -    {
>> -      const target_desc *tdesc;
>> -
>> -      /* If we know from the executable this is an M-profile target,
>> -	 cater for remote targets whose register set layout is the
>> -	 same as the FPA layout.  */
>> -      tdesc = arm_read_mprofile_description (ARM_M_TYPE_WITH_FPA);
>> -      register_remote_g_packet_guess (gdbarch,
>> -				      ARM_CORE_REGS_SIZE + ARM_FP_REGS_SIZE,
>> -				      tdesc);
>> -
>> -      /* The regular M-profile layout.  */
>> -      tdesc = arm_read_mprofile_description (ARM_M_TYPE_M_PROFILE);
>> -      register_remote_g_packet_guess (gdbarch, ARM_CORE_REGS_SIZE,
>> -				      tdesc);
>> -
>> -      /* M-profile plus M4F VFP.  */
>> -      tdesc = arm_read_mprofile_description (ARM_M_TYPE_VFP_D16);
>> -      register_remote_g_packet_guess (gdbarch,
>> -				      ARM_CORE_REGS_SIZE + ARM_VFP2_REGS_SIZE,
>> -				      tdesc);
>> -      /* M-profile plus MVE.  */
>> -      tdesc = arm_read_mprofile_description (ARM_M_TYPE_MVE);
>> -      register_remote_g_packet_guess (gdbarch, ARM_CORE_REGS_SIZE
>> -				      + ARM_VFP2_REGS_SIZE
>> -				      + ARM_INT_REGISTER_SIZE, tdesc);
>> -
>> -      /* M-profile system (stack pointers).  */
>> -      tdesc = arm_read_mprofile_description (ARM_M_TYPE_SYSTEM);
>> -      register_remote_g_packet_guess (gdbarch, 2 * ARM_INT_REGISTER_SIZE, tdesc);
>> -    }
>> -
>> -  /* Otherwise we don't have a useful guess.  */
>> -}
>> -
>>   /* Implement the code_of_frame_writable gdbarch method.  */
>>   
>>   static int
>> @@ -9848,7 +9634,6 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
>>     bool have_s_pseudos = false, have_q_pseudos = false;
>>     bool have_wmmx_registers = false;
>>     bool have_neon = false;
>> -  bool have_fpa_registers = true;
>>     const struct target_desc *tdesc = info.target_desc;
>>     bool have_vfp = false;
>>     bool have_mve = false;
>> @@ -10015,21 +9800,13 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
>>   	    {
>>   	      switch (e_flags & (EF_ARM_SOFT_FLOAT | EF_ARM_VFP_FLOAT))
>>   		{
>> -		case 0:
>> -		  /* Leave it as "auto".  Strictly speaking this case
>> -		     means FPA, but almost nobody uses that now, and
>> -		     many toolchains fail to set the appropriate bits
>> -		     for the floating-point model they use.  */
>> -		  break;
>> -		case EF_ARM_SOFT_FLOAT:
>> -		  fp_model = ARM_FLOAT_SOFT_FPA;
>> +		case 0: /* Default to soft-float VFP.  */
>> +		case EF_ARM_SOFT_FLOAT | EF_ARM_VFP_FLOAT:
>> +		  fp_model = ARM_FLOAT_SOFT_VFP;
>>   		  break;
>>   		case EF_ARM_VFP_FLOAT:
>>   		  fp_model = ARM_FLOAT_VFP;
>>   		  break;
>> -		case EF_ARM_SOFT_FLOAT | EF_ARM_VFP_FLOAT:
>> -		  fp_model = ARM_FLOAT_SOFT_VFP;
>> -		  break;
>>   		}
>>   	    }
>>   
>> @@ -10122,20 +9899,6 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
>>   	    }
>>   	}
>>   
>> -      feature = tdesc_find_feature (tdesc,
>> -				    "org.gnu.gdb.arm.fpa");
>> -      if (feature != NULL)
>> -	{
>> -	  valid_p = 1;
>> -	  for (i = ARM_F0_REGNUM; i <= ARM_FPS_REGNUM; i++)
>> -	    valid_p &= tdesc_numbered_register (feature, tdesc_data.get (), i,
>> -						arm_register_names[i]);
>> -	  if (!valid_p)
>> -	    return NULL;
>> -	}
>> -      else
>> -	have_fpa_registers = false;
>> -
>>         feature = tdesc_find_feature (tdesc,
>>   				    "org.gnu.gdb.xscale.iwmmxt");
>>         if (feature != NULL)
>> @@ -10389,7 +10152,6 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
>>     tdep->fp_model = fp_model;
>>     tdep->is_m = is_m;
>>     tdep->have_sec_ext = have_sec_ext;
>> -  tdep->have_fpa_registers = have_fpa_registers;
>>     tdep->have_wmmx_registers = have_wmmx_registers;
>>     gdb_assert (vfp_register_count == 0
>>   	      || vfp_register_count == 16
>> @@ -10421,8 +10183,6 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
>>         tdep->m_profile_psp_s_regnum = m_profile_psp_s_regnum;
>>       }
>>   
>> -  arm_register_g_packet_guesses (gdbarch);
>> -
>>     /* Breakpoints.  */
>>     switch (info.byte_order_for_code)
>>       {
>> @@ -10508,12 +10268,6 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
>>     set_gdbarch_pc_regnum (gdbarch, ARM_PC_REGNUM);
>>     set_gdbarch_num_regs (gdbarch, register_count);
>>     set_gdbarch_register_type (gdbarch, arm_register_type);
>> -  set_gdbarch_register_reggroup_p (gdbarch, arm_register_reggroup_p);
>> -
>> -  /* This "info float" is FPA-specific.  Use the generic version if we
>> -     do not have FPA.  */
>> -  if (tdep->have_fpa_registers)
>> -    set_gdbarch_print_float_info (gdbarch, arm_print_float_info);
>>   
>>     /* Internal <-> external register number maps.  */
>>     set_gdbarch_dwarf2_reg_to_regnum (gdbarch, arm_dwarf_reg_to_regnum);
>> @@ -10565,29 +10319,13 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
>>     /* Watchpoints are not steppable.  */
>>     set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1);
>>   
>> -  /* We used to default to FPA for generic ARM, but almost nobody
>> -     uses that now, and we now provide a way for the user to force
>> -     the model.  So default to the most useful variant.  */
>> -  if (tdep->fp_model == ARM_FLOAT_AUTO)
>> -    tdep->fp_model = ARM_FLOAT_SOFT_FPA;
>> -
>>     if (tdep->jb_pc >= 0)
>>       set_gdbarch_get_longjmp_target (gdbarch, arm_get_longjmp_target);
>>   
>>     /* Floating point sizes and format.  */
>>     set_gdbarch_float_format (gdbarch, floatformats_ieee_single);
>> -  if (tdep->fp_model == ARM_FLOAT_SOFT_FPA || tdep->fp_model == ARM_FLOAT_FPA)
>> -    {
>> -      set_gdbarch_double_format
>> -	(gdbarch, floatformats_ieee_double_littlebyte_bigword);
>> -      set_gdbarch_long_double_format
>> -	(gdbarch, floatformats_ieee_double_littlebyte_bigword);
>> -    }
>> -  else
>> -    {
>> -      set_gdbarch_double_format (gdbarch, floatformats_ieee_double);
>> -      set_gdbarch_long_double_format (gdbarch, floatformats_ieee_double);
>> -    }
>> +  set_gdbarch_double_format (gdbarch, floatformats_ieee_double);
>> +  set_gdbarch_long_double_format (gdbarch, floatformats_ieee_double);
>>   
>>     /* Hook used to decorate frames with signed return addresses, only available
>>        for ARMv8.1-m PACBTI.  */
>> @@ -10678,8 +10416,6 @@ arm_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file)
>>   
>>     gdb_printf (file, _("arm_dump_tdep: fp_model = %i\n"),
>>   	      (int) tdep->fp_model);
>> -  gdb_printf (file, _("arm_dump_tdep: have_fpa_registers = %i\n"),
>> -	      (int) tdep->have_fpa_registers);
>>     gdb_printf (file, _("arm_dump_tdep: have_wmmx_registers = %i\n"),
>>   	      (int) tdep->have_wmmx_registers);
>>     gdb_printf (file, _("arm_dump_tdep: vfp_register_count = %i\n"),
>> @@ -10820,8 +10556,6 @@ _initialize_arm_tdep ()
>>   			_("Set the floating point type."),
>>   			_("Show the floating point type."),
>>   			_("auto - Determine the FP typefrom the OS-ABI.\n\
>> -softfpa - Software FP, mixed-endian doubles on little-endian ARMs.\n\
>> -fpa - FPA co-processor (GCC compiled).\n\
>>   softvfp - Software FP with pure-endian doubles.\n\
>>   vfp - VFP co-processor."),
>>   			set_fp_model_sfunc, show_fp_model,
>> diff --git a/gdb/arm-tdep.h b/gdb/arm-tdep.h
>> index 67dd1151da4..594961e52ec 100644
>> --- a/gdb/arm-tdep.h
>> +++ b/gdb/arm-tdep.h
>> @@ -62,8 +62,6 @@ extern bool arm_apcs_32;
>>   enum arm_float_model
>>   {
>>     ARM_FLOAT_AUTO,	/* Automatic detection.  Do not set in tdep.  */
>> -  ARM_FLOAT_SOFT_FPA,	/* Traditional soft-float (mixed-endian on LE ARM).  */
>> -  ARM_FLOAT_FPA,	/* FPA co-processor.  GCC calling convention.  */
>>     ARM_FLOAT_SOFT_VFP,	/* Soft-float with pure-endian doubles.  */
>>     ARM_FLOAT_VFP,	/* Full VFP calling convention.  */
>>     ARM_FLOAT_LAST	/* Keep at end.  */
>> @@ -95,7 +93,6 @@ struct arm_gdbarch_tdep : gdbarch_tdep_base
>>   
>>     enum arm_float_model fp_model {}; /* Floating point calling conventions.  */
>>   
>> -  bool have_fpa_registers = false;	/* Does the target report the FPA registers?  */
>>     bool have_wmmx_registers = false;	/* Does the target report the WMMX registers?  */
>>     /* The number of VFP registers reported by the target.  It is zero
>>        if VFP registers are not supported.  */
>> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
>> index 238a49b027d..2111a584b88 100644
>> --- a/gdb/doc/gdb.texinfo
>> +++ b/gdb/doc/gdb.texinfo
>> @@ -25309,11 +25309,6 @@ argument @var{fputype} can be one of these:
>>   @table @code
>>   @item auto
>>   Determine the FPU type by querying the OS ABI.
>> -@item softfpa
>> -Software FPU, with mixed-endian doubles on little-endian ARM
>> -processors.
>> -@item fpa
>> -GCC-compiled FPA co-processor.
>>   @item softvfp
>>   Software FPU with pure-endian doubles.
>>   @item vfp
>> @@ -46919,9 +46914,6 @@ Double precision IEEE floating point.
>>   @item bfloat16
>>   The 16-bit @dfn{brain floating point} format used e.g.@: by x86 and ARM.
>>   
>> -@item arm_fpa_ext
>> -The 12-byte extended precision format used by ARM FPA registers.
>> -
>>   @item i387_ext
>>   The 10-byte extended precision format used by x87 registers.
>>   
>> @@ -47106,8 +47098,9 @@ feature is replaced by @samp{org.gnu.gdb.arm.m-profile}.  It should contain
>>   registers @samp{r0} through @samp{r13}, @samp{sp}, @samp{lr}, @samp{pc},
>>   and @samp{xpsr}.
>>   
>> -The @samp{org.gnu.gdb.arm.fpa} feature is optional.  If present, it
>> -should contain registers @samp{f0} through @samp{f7} and @samp{fps}.
>> +The @samp{org.gnu.gdb.arm.fpa} feature is no longer supported.  It
>> +used to contain registers @samp{f0} through @samp{f7} and @samp{fps}, for the
>> +legacy FPA feature.
>>   
>>   The @samp{org.gnu.gdb.arm.m-profile-mve} feature is optional.  If present, it
>>   must contain register @samp{vpr}.
>> diff --git a/gdb/features/Makefile b/gdb/features/Makefile
>> index 061cb2ed032..3d0ed4edafa 100644
>> --- a/gdb/features/Makefile
>> +++ b/gdb/features/Makefile
>> @@ -204,11 +204,9 @@ FEATURE_XMLFILES = aarch64-core.xml \
>>   	arc/v2-core.xml \
>>   	arc/v2-aux.xml \
>>   	arm/arm-core.xml \
>> -	arm/arm-fpa.xml \
>>   	arm/arm-m-profile.xml \
>>   	arm/arm-m-profile-mve.xml \
>>   	arm/arm-m-system.xml \
>> -	arm/arm-m-profile-with-fpa.xml \
>>   	arm/arm-tls.xml \
>>   	arm/arm-vfpv2.xml \
>>   	arm/arm-vfpv3.xml \
>> diff --git a/gdb/features/arm/arm-fpa.c b/gdb/features/arm/arm-fpa.c
>> deleted file mode 100644
>> index 65a49f5f3f1..00000000000
>> --- a/gdb/features/arm/arm-fpa.c
>> +++ /dev/null
>> @@ -1,23 +0,0 @@
>> -/* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
>> -  Original: arm-fpa.xml */
>> -
>> -#include "gdbsupport/tdesc.h"
>> -
>> -static int
>> -create_feature_arm_arm_fpa (struct target_desc *result, long regnum)
>> -{
>> -  struct tdesc_feature *feature;
>> -
>> -  feature = tdesc_create_feature (result, "org.gnu.gdb.arm.fpa");
>> -  regnum = 16;
>> -  tdesc_create_reg (feature, "f0", regnum++, 1, NULL, 96, "arm_fpa_ext");
>> -  tdesc_create_reg (feature, "f1", regnum++, 1, NULL, 96, "arm_fpa_ext");
>> -  tdesc_create_reg (feature, "f2", regnum++, 1, NULL, 96, "arm_fpa_ext");
>> -  tdesc_create_reg (feature, "f3", regnum++, 1, NULL, 96, "arm_fpa_ext");
>> -  tdesc_create_reg (feature, "f4", regnum++, 1, NULL, 96, "arm_fpa_ext");
>> -  tdesc_create_reg (feature, "f5", regnum++, 1, NULL, 96, "arm_fpa_ext");
>> -  tdesc_create_reg (feature, "f6", regnum++, 1, NULL, 96, "arm_fpa_ext");
>> -  tdesc_create_reg (feature, "f7", regnum++, 1, NULL, 96, "arm_fpa_ext");
>> -  tdesc_create_reg (feature, "fps", regnum++, 1, NULL, 32, "int");
>> -  return regnum;
>> -}
>> diff --git a/gdb/features/arm/arm-fpa.xml b/gdb/features/arm/arm-fpa.xml
>> deleted file mode 100644
>> index d533b25132f..00000000000
>> --- a/gdb/features/arm/arm-fpa.xml
>> +++ /dev/null
>> @@ -1,23 +0,0 @@
>> -<?xml version="1.0"?>
>> -<!-- Copyright (C) 2007-2022 Free Software Foundation, Inc.
>> -
>> -     Copying and distribution of this file, with or without modification,
>> -     are permitted in any medium without royalty provided the copyright
>> -     notice and this notice are preserved.  -->
>> -
>> -<!DOCTYPE feature SYSTEM "gdb-target.dtd">
>> -<feature name="org.gnu.gdb.arm.fpa">
>> -  <!-- f0's regnum is set explicitly, because the FPA registers
>> -       historically were placed between the PC and the CPSR in the "g"
>> -       packet - in the middle of org.gnu.gdb.arm.core.  -->
>> -  <reg name="f0" bitsize="96" type="arm_fpa_ext" regnum="16"/>
>> -  <reg name="f1" bitsize="96" type="arm_fpa_ext"/>
>> -  <reg name="f2" bitsize="96" type="arm_fpa_ext"/>
>> -  <reg name="f3" bitsize="96" type="arm_fpa_ext"/>
>> -  <reg name="f4" bitsize="96" type="arm_fpa_ext"/>
>> -  <reg name="f5" bitsize="96" type="arm_fpa_ext"/>
>> -  <reg name="f6" bitsize="96" type="arm_fpa_ext"/>
>> -  <reg name="f7" bitsize="96" type="arm_fpa_ext"/>
>> -
>> -  <reg name="fps" bitsize="32"/>
>> -</feature>
>> diff --git a/gdb/features/arm/arm-m-profile-with-fpa.c b/gdb/features/arm/arm-m-profile-with-fpa.c
>> deleted file mode 100644
>> index 2b7c78597bb..00000000000
>> --- a/gdb/features/arm/arm-m-profile-with-fpa.c
>> +++ /dev/null
>> @@ -1,39 +0,0 @@
>> -/* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
>> -  Original: arm-m-profile-with-fpa.xml */
>> -
>> -#include "gdbsupport/tdesc.h"
>> -
>> -static int
>> -create_feature_arm_arm_m_profile_with_fpa (struct target_desc *result, long regnum)
>> -{
>> -  struct tdesc_feature *feature;
>> -
>> -  feature = tdesc_create_feature (result, "org.gnu.gdb.arm.m-profile");
>> -  tdesc_create_reg (feature, "r0", regnum++, 1, NULL, 32, "int");
>> -  tdesc_create_reg (feature, "r1", regnum++, 1, NULL, 32, "int");
>> -  tdesc_create_reg (feature, "r2", regnum++, 1, NULL, 32, "int");
>> -  tdesc_create_reg (feature, "r3", regnum++, 1, NULL, 32, "int");
>> -  tdesc_create_reg (feature, "r4", regnum++, 1, NULL, 32, "int");
>> -  tdesc_create_reg (feature, "r5", regnum++, 1, NULL, 32, "int");
>> -  tdesc_create_reg (feature, "r6", regnum++, 1, NULL, 32, "int");
>> -  tdesc_create_reg (feature, "r7", regnum++, 1, NULL, 32, "int");
>> -  tdesc_create_reg (feature, "r8", regnum++, 1, NULL, 32, "int");
>> -  tdesc_create_reg (feature, "r9", regnum++, 1, NULL, 32, "int");
>> -  tdesc_create_reg (feature, "r10", regnum++, 1, NULL, 32, "int");
>> -  tdesc_create_reg (feature, "r11", regnum++, 1, NULL, 32, "int");
>> -  tdesc_create_reg (feature, "r12", regnum++, 1, NULL, 32, "int");
>> -  tdesc_create_reg (feature, "sp", regnum++, 1, NULL, 32, "data_ptr");
>> -  tdesc_create_reg (feature, "lr", regnum++, 1, NULL, 32, "int");
>> -  tdesc_create_reg (feature, "pc", regnum++, 1, NULL, 32, "code_ptr");
>> -  tdesc_create_reg (feature, "", regnum++, 1, NULL, 96, "arm_fpa_ext");
>> -  tdesc_create_reg (feature, "", regnum++, 1, NULL, 96, "arm_fpa_ext");
>> -  tdesc_create_reg (feature, "", regnum++, 1, NULL, 96, "arm_fpa_ext");
>> -  tdesc_create_reg (feature, "", regnum++, 1, NULL, 96, "arm_fpa_ext");
>> -  tdesc_create_reg (feature, "", regnum++, 1, NULL, 96, "arm_fpa_ext");
>> -  tdesc_create_reg (feature, "", regnum++, 1, NULL, 96, "arm_fpa_ext");
>> -  tdesc_create_reg (feature, "", regnum++, 1, NULL, 96, "arm_fpa_ext");
>> -  tdesc_create_reg (feature, "", regnum++, 1, NULL, 96, "arm_fpa_ext");
>> -  tdesc_create_reg (feature, "", regnum++, 1, NULL, 32, "int");
>> -  tdesc_create_reg (feature, "xpsr", regnum++, 1, NULL, 32, "int");
>> -  return regnum;
>> -}
>> diff --git a/gdb/features/arm/arm-m-profile-with-fpa.xml b/gdb/features/arm/arm-m-profile-with-fpa.xml
>> deleted file mode 100644
>> index 850ed42cbfd..00000000000
>> --- a/gdb/features/arm/arm-m-profile-with-fpa.xml
>> +++ /dev/null
>> @@ -1,39 +0,0 @@
>> -<?xml version="1.0"?>
>> -<!-- Copyright (C) 2019-2022 Free Software Foundation, Inc.
>> -
>> -     Copying and distribution of this file, with or without modification,
>> -     are permitted in any medium without royalty provided the copyright
>> -     notice and this notice are preserved.  -->
>> -
>> -<!DOCTYPE feature SYSTEM "gdb-target.dtd">
>> -<feature name="org.gnu.gdb.arm.m-profile">
>> -  <reg name="r0" bitsize="32"/>
>> -  <reg name="r1" bitsize="32"/>
>> -  <reg name="r2" bitsize="32"/>
>> -  <reg name="r3" bitsize="32"/>
>> -  <reg name="r4" bitsize="32"/>
>> -  <reg name="r5" bitsize="32"/>
>> -  <reg name="r6" bitsize="32"/>
>> -  <reg name="r7" bitsize="32"/>
>> -  <reg name="r8" bitsize="32"/>
>> -  <reg name="r9" bitsize="32"/>
>> -  <reg name="r10" bitsize="32"/>
>> -  <reg name="r11" bitsize="32"/>
>> -  <reg name="r12" bitsize="32"/>
>> -  <reg name="sp" bitsize="32" type="data_ptr"/>
>> -  <reg name="lr" bitsize="32"/>
>> -  <reg name="pc" bitsize="32" type="code_ptr"/>
>> -
>> -  <!-- Slack for unused FPA registers (f0-f7 + fps).  -->
>> -  <reg name="" bitsize="96" type="arm_fpa_ext" regnum="16"/>
>> -  <reg name="" bitsize="96" type="arm_fpa_ext"/>
>> -  <reg name="" bitsize="96" type="arm_fpa_ext"/>
>> -  <reg name="" bitsize="96" type="arm_fpa_ext"/>
>> -  <reg name="" bitsize="96" type="arm_fpa_ext"/>
>> -  <reg name="" bitsize="96" type="arm_fpa_ext"/>
>> -  <reg name="" bitsize="96" type="arm_fpa_ext"/>
>> -  <reg name="" bitsize="96" type="arm_fpa_ext"/>
>> -  <reg name="" bitsize="32"/>
>> -
>> -  <reg name="xpsr" bitsize="32" regnum="25"/>
>> -</feature>
>> diff --git a/gdb/target-descriptions.c b/gdb/target-descriptions.c
>> index 044b171ecd2..45a3df941c5 100644
>> --- a/gdb/target-descriptions.c
>> +++ b/gdb/target-descriptions.c
>> @@ -132,10 +132,6 @@ make_gdb_type (struct gdbarch *gdbarch, struct tdesc_type *ttype)
>>   	  m_type = arch_float_type (m_gdbarch, -1, "builtin_type_ieee_double",
>>   				    floatformats_ieee_double);
>>   	  return;
>> -	case TDESC_TYPE_ARM_FPA_EXT:
>> -	  m_type = arch_float_type (m_gdbarch, -1, "builtin_type_arm_ext",
>> -				    floatformats_arm_ext);
>> -	  return;
>>   
>>   	case TDESC_TYPE_I387_EXT:
>>   	  m_type = arch_float_type (m_gdbarch, -1, "builtin_type_i387_ext",
>> diff --git a/gdb/testsuite/gdb.base/long_long.exp b/gdb/testsuite/gdb.base/long_long.exp
>> index 9c8dd16b7eb..bb4c1a1859e 100644
>> --- a/gdb/testsuite/gdb.base/long_long.exp
>> +++ b/gdb/testsuite/gdb.base/long_long.exp
>> @@ -141,22 +141,10 @@ gdb_test_ptr "p/a val.oct" "" "" "0x77053977" "0xa72ee53977053977"
>>   gdb_test "p/c val.oct" "'w'"
>>   
>>   if { $sizeof_double == 8 || $sizeof_long_double == 8 } {
>> -    # ARM FPA floating point numbers are not strictly little endian or big
>> -    # endian, but a hybrid.  They are in little endian format with the two
>> -    # words swapped in big endian format.
>>       # EABI targets default to natural-endian VFP format.
>> -
>> -    if { ([istarget "arm*-*-*"]) \
>> -	 && !([istarget "*-*-*eabi*"] || \
>> -	      [istarget "*-*-mingw32ce*"] || \
>> -	      [istarget "*-*-openbsd*"]) } then {
>> -	# assume the long long represents a floating point double in ARM format
>> -	gdb_test "p/f val.oct" "2.1386676354387559e\\+265"
>> -    } else {
>> -	# assume the long long represents a floating point double in little
>> -	# endian format
>> -	gdb_test "p/f val.oct" "-5.9822653797615723e-120"
>> -    }
>> +    # Assume the long long represents a floating point double in little
>> +    # endian format
>> +    gdb_test "p/f val.oct" "-5.9822653797615723e-120"
>>   } else {
>>       gdb_test "p/f val.oct" "-2.42716126e-15"
>>   }
>> diff --git a/gdbserver/linux-arm-low.cc b/gdbserver/linux-arm-low.cc
>> index ab6209a3abc..fb3f02088ca 100644
>> --- a/gdbserver/linux-arm-low.cc
>> +++ b/gdbserver/linux-arm-low.cc
>> @@ -983,8 +983,7 @@ arm_read_description (void)
>>   	return arm_linux_read_description (ARM_FP_TYPE_VFPV2);
>>       }
>>   
>> -  /* The default configuration uses legacy FPA registers, probably
>> -     simulated.  */
>> +  /* No floating point registers.  */
>>     return arm_linux_read_description (ARM_FP_TYPE_NONE);
>>   }
>>   
>> @@ -1088,9 +1087,9 @@ static struct regset_info arm_regsets[] = {
>>     { PTRACE_GETREGS, PTRACE_SETREGS, 0,
>>       ARM_CORE_REGS_SIZE + ARM_INT_REGISTER_SIZE, GENERAL_REGS,
>>       arm_fill_gregset, arm_store_gregset },
>> -  { PTRACE_GETWMMXREGS, PTRACE_SETWMMXREGS, 0, IWMMXT_REGS_SIZE, EXTENDED_REGS,
>> +  { PTRACE_GETWMMXREGS, PTRACE_SETWMMXREGS, 0, IWMMXT_REGS_SIZE, OPTIONAL_REGS,
>>       arm_fill_wmmxregset, arm_store_wmmxregset },
>> -  { PTRACE_GETVFPREGS, PTRACE_SETVFPREGS, 0, ARM_VFP3_REGS_SIZE, EXTENDED_REGS,
>> +  { PTRACE_GETVFPREGS, PTRACE_SETVFPREGS, 0, ARM_VFP3_REGS_SIZE, OPTIONAL_REGS,
>>       arm_fill_vfpregset, arm_store_vfpregset },
>>     NULL_REGSET
>>   };
>> diff --git a/gdbsupport/tdesc.cc b/gdbsupport/tdesc.cc
>> index 4d41d0b168a..0b0b765cb3d 100644
>> --- a/gdbsupport/tdesc.cc
>> +++ b/gdbsupport/tdesc.cc
>> @@ -53,7 +53,6 @@ static tdesc_type_builtin tdesc_predefined_types[] =
>>     { "ieee_half", TDESC_TYPE_IEEE_HALF },
>>     { "ieee_single", TDESC_TYPE_IEEE_SINGLE },
>>     { "ieee_double", TDESC_TYPE_IEEE_DOUBLE },
>> -  { "arm_fpa_ext", TDESC_TYPE_ARM_FPA_EXT },
>>     { "i387_ext", TDESC_TYPE_I387_EXT },
>>     { "bfloat16", TDESC_TYPE_BFLOAT16 }
>>   };
>> diff --git a/gdbsupport/tdesc.h b/gdbsupport/tdesc.h
>> index 403aa2c3d19..082819ada13 100644
>> --- a/gdbsupport/tdesc.h
>> +++ b/gdbsupport/tdesc.h
>> @@ -171,7 +171,6 @@ enum tdesc_type_kind
>>     TDESC_TYPE_IEEE_HALF,
>>     TDESC_TYPE_IEEE_SINGLE,
>>     TDESC_TYPE_IEEE_DOUBLE,
>> -  TDESC_TYPE_ARM_FPA_EXT,
>>     TDESC_TYPE_I387_EXT,
>>     TDESC_TYPE_BFLOAT16,
  
John Baldwin Oct. 3, 2022, 5:33 p.m. UTC | #4
On 9/20/22 5:30 AM, Luis Machado wrote:
> FPA has been deprecated for a while now. It was removed from GCC in 2012,
> but somehow it managed to survive in GDB for a little while longer.
> 
> It is time to let FPA rest in peace.
> 
> While at it, make VFP the default floating point model for 32-bit Arm.
> 
> It would be nice to get some *BSD testing as some changes touch that code
> and I'm not properly setup to validate the changes for those OS'.

Sorry I missed this earlier.  FreeBSD/arm doesn't use the arm-bsd-tdep.* bits
at all and won't be affected by these changes.  The other BSD changes do look
fine to me FWIW (and thanks to Enze for testing NetBSD and OpenBSD).
  
Pedro Alves Oct. 3, 2022, 7:16 p.m. UTC | #5
On 2022-09-20 1:30 p.m., Luis Machado via Gdb-patches wrote:

> diff --git a/gdb/arch/arm.h b/gdb/arch/arm.h
> index 36757493406..74a6ba93bc7 100644
> --- a/gdb/arch/arm.h
> +++ b/gdb/arch/arm.h
> @@ -44,11 +44,6 @@ enum gdb_regnum {
>    ARM_SP_REGNUM = 13,		/* Contains address of top of stack */
>    ARM_LR_REGNUM = 14,		/* address to return to from a function call */
>    ARM_PC_REGNUM = 15,		/* Contains program counter */
> -  /* F0..F7 are the fp registers for the (obsolete) FPA architecture.  */

Shouldn't we leave behind a comment explaining why there's a hole between 15 and 25?

IIRC the numbers can't be changed since we need to handle the case when the target
doesn't send an xml tdesc, so it'd be good to help future readers understand why
there's a hole.


> -  ARM_F0_REGNUM = 16,		/* first floating point register */
> -  ARM_F3_REGNUM = 19,		/* last floating point argument register */
> -  ARM_F7_REGNUM = 23, 		/* last floating point register */
> -  ARM_FPS_REGNUM = 24,		/* floating point status register */
>    ARM_PS_REGNUM = 25,		/* Contains processor status */
>    ARM_WR0_REGNUM,		/* WMMX data registers.  */
>    ARM_WR15_REGNUM = ARM_WR0_REGNUM + 15,
> @@ -67,7 +62,6 @@ enum gdb_regnum {
>    ARM_FP_REGNUM = 11,		/* Frame register in ARM code, if used.  */
>    THUMB_FP_REGNUM = 7,		/* Frame register in Thumb code, if used.  */
>    ARM_LAST_ARG_REGNUM = ARM_A4_REGNUM,
> -  ARM_LAST_FP_ARG_REGNUM = ARM_F3_REGNUM
>  };
>  


> diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
> index ead9bbf46c5..b33a53612a6 100644
> --- a/gdb/arm-tdep.c
> +++ b/gdb/arm-tdep.c
> @@ -134,8 +134,6 @@ static struct cmd_list_element *showarmcmdlist = NULL;
>  static const char *const fp_model_strings[] =
>  {
>    "auto",
> -  "softfpa",
> -  "fpa",
>    "softvfp",
>    "vfp",
>    NULL
> @@ -226,9 +224,7 @@ static const char *const arm_register_names[] =
>   "r4",  "r5",  "r6",  "r7",	/*  4  5  6  7 */
>   "r8",  "r9",  "r10", "r11",	/*  8  9 10 11 */
>   "r12", "sp",  "lr",  "pc",	/* 12 13 14 15 */
> - "f0",  "f1",  "f2",  "f3",	/* 16 17 18 19 */
> - "f4",  "f5",  "f6",  "f7",	/* 20 21 22 23 */
> - "fps", "cpsr" };		/* 24 25       */
> + "cpsr" };			/* 25 */
>  

Don't the array indexes here need to match the register numbers?  The "cpsr" string
above is no longer at index 25 after this change.


> -/* For backward-compatibility we allow two 'g' packet lengths with
> -   the remote protocol depending on whether FPA registers are
> -   supplied.  M-profile targets do not have FPA registers, but some
> -   stubs already exist in the wild which use a 'g' packet which
> -   supplies them albeit with dummy values.  

So this patch is also removing support for these M-profile targets covered by
that last sentence.  Are we OK with that?


> -   The packet format which
> -   includes FPA registers should be considered deprecated for
> -   M-profile targets.  */
> -
> -static void
> -arm_register_g_packet_guesses (struct gdbarch *gdbarch)
> -{
> -  arm_gdbarch_tdep *tdep = gdbarch_tdep<arm_gdbarch_tdep> (gdbarch);
> -
> -  if (tdep->is_m)
> -    {
> -      const target_desc *tdesc;
> -
> -      /* If we know from the executable this is an M-profile target,
> -	 cater for remote targets whose register set layout is the
> -	 same as the FPA layout.  */
> -      tdesc = arm_read_mprofile_description (ARM_M_TYPE_WITH_FPA);
> -      register_remote_g_packet_guess (gdbarch,
> -				      ARM_CORE_REGS_SIZE + ARM_FP_REGS_SIZE,
> -				      tdesc);
> -
> -      /* The regular M-profile layout.  */
> -      tdesc = arm_read_mprofile_description (ARM_M_TYPE_M_PROFILE);
> -      register_remote_g_packet_guess (gdbarch, ARM_CORE_REGS_SIZE,
> -				      tdesc);
> -
> -      /* M-profile plus M4F VFP.  */
> -      tdesc = arm_read_mprofile_description (ARM_M_TYPE_VFP_D16);
> -      register_remote_g_packet_guess (gdbarch,
> -				      ARM_CORE_REGS_SIZE + ARM_VFP2_REGS_SIZE,
> -				      tdesc);
> -      /* M-profile plus MVE.  */
> -      tdesc = arm_read_mprofile_description (ARM_M_TYPE_MVE);
> -      register_remote_g_packet_guess (gdbarch, ARM_CORE_REGS_SIZE
> -				      + ARM_VFP2_REGS_SIZE
> -				      + ARM_INT_REGISTER_SIZE, tdesc);
> -
> -      /* M-profile system (stack pointers).  */
> -      tdesc = arm_read_mprofile_description (ARM_M_TYPE_SYSTEM);
> -      register_remote_g_packet_guess (gdbarch, 2 * ARM_INT_REGISTER_SIZE, tdesc);

And what about all these other non-FPA guesses?  Do you really mean to drop them?

> -    }
> -
> -  /* Otherwise we don't have a useful guess.  */
> -}
> -
>  /* Implement the code_of_frame_writable gdbarch method.  */
>  
>  static int
  
Luis Machado Oct. 4, 2022, 8:43 a.m. UTC | #6
On 10/3/22 20:16, Pedro Alves wrote:
> On 2022-09-20 1:30 p.m., Luis Machado via Gdb-patches wrote:
> 
>> diff --git a/gdb/arch/arm.h b/gdb/arch/arm.h
>> index 36757493406..74a6ba93bc7 100644
>> --- a/gdb/arch/arm.h
>> +++ b/gdb/arch/arm.h
>> @@ -44,11 +44,6 @@ enum gdb_regnum {
>>     ARM_SP_REGNUM = 13,		/* Contains address of top of stack */
>>     ARM_LR_REGNUM = 14,		/* address to return to from a function call */
>>     ARM_PC_REGNUM = 15,		/* Contains program counter */
>> -  /* F0..F7 are the fp registers for the (obsolete) FPA architecture.  */
> 
> Shouldn't we leave behind a comment explaining why there's a hole between 15 and 25?

I pondered about this a bit more, and I think we should close the gap and bring CPSR down to
16, its "natural" position. It is what linux uses for user_regs as well, in gdb/arch/arm-linux.h:

/* The index to access CSPR in user_regs defined in GLIBC.  */
#define ARM_CPSR_GREGNUM 16

> 
> IIRC the numbers can't be changed since we need to handle the case when the target
> doesn't send an xml tdesc, so it'd be good to help future readers understand why
> there's a hole.

That's correct. Though a 32-bit Arm target that doesn't support XML descriptions these days is not very
common. I haven't seen one in a while.

I'm willing to declare old 32-bit Arm targets that don't send XML target descriptions back as unsupported.

To that effect, I suppose we should add a note to make it more explicit.

More below.

> 
> 
>> -  ARM_F0_REGNUM = 16,		/* first floating point register */
>> -  ARM_F3_REGNUM = 19,		/* last floating point argument register */
>> -  ARM_F7_REGNUM = 23, 		/* last floating point register */
>> -  ARM_FPS_REGNUM = 24,		/* floating point status register */
>>     ARM_PS_REGNUM = 25,		/* Contains processor status */
>>     ARM_WR0_REGNUM,		/* WMMX data registers.  */
>>     ARM_WR15_REGNUM = ARM_WR0_REGNUM + 15,
>> @@ -67,7 +62,6 @@ enum gdb_regnum {
>>     ARM_FP_REGNUM = 11,		/* Frame register in ARM code, if used.  */
>>     THUMB_FP_REGNUM = 7,		/* Frame register in Thumb code, if used.  */
>>     ARM_LAST_ARG_REGNUM = ARM_A4_REGNUM,
>> -  ARM_LAST_FP_ARG_REGNUM = ARM_F3_REGNUM
>>   };
>>   
> 
> 
>> diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
>> index ead9bbf46c5..b33a53612a6 100644
>> --- a/gdb/arm-tdep.c
>> +++ b/gdb/arm-tdep.c
>> @@ -134,8 +134,6 @@ static struct cmd_list_element *showarmcmdlist = NULL;
>>   static const char *const fp_model_strings[] =
>>   {
>>     "auto",
>> -  "softfpa",
>> -  "fpa",
>>     "softvfp",
>>     "vfp",
>>     NULL
>> @@ -226,9 +224,7 @@ static const char *const arm_register_names[] =
>>    "r4",  "r5",  "r6",  "r7",	/*  4  5  6  7 */
>>    "r8",  "r9",  "r10", "r11",	/*  8  9 10 11 */
>>    "r12", "sp",  "lr",  "pc",	/* 12 13 14 15 */
>> - "f0",  "f1",  "f2",  "f3",	/* 16 17 18 19 */
>> - "f4",  "f5",  "f6",  "f7",	/* 20 21 22 23 */
>> - "fps", "cpsr" };		/* 24 25       */
>> + "cpsr" };			/* 25 */
>>   
> 
> Don't the array indexes here need to match the register numbers?  The "cpsr" string
> above is no longer at index 25 after this change.

That's right. This needs to be adjusted. We don't use this array to name cpsr though. We do it
explicitly as:

       if (is_m)
         valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
                                             ARM_PS_REGNUM, "xpsr");
       else
         valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
                                             ARM_PS_REGNUM, "cpsr");

We may still try to return its name. I've fixed this locally. Thanks for spotting it.

> 
> 
>> -/* For backward-compatibility we allow two 'g' packet lengths with
>> -   the remote protocol depending on whether FPA registers are
>> -   supplied.  M-profile targets do not have FPA registers, but some
>> -   stubs already exist in the wild which use a 'g' packet which
>> -   supplies them albeit with dummy values.
> 
> So this patch is also removing support for these M-profile targets covered by
> that last sentence.  Are we OK with that?
> 
> 

I haven't seen any of these targets "in the wild" or received reports of broken
sessions. Most of these were debugging stubs and probe software, but they have since
migrated to the XML scheme or fell in disuse. It is a maintenance burden for the port, and
there is no easy way to test it, as it is mostly a guess if it is working properly.

With that said, I'm OK with deprecating the g packet guesses for 32-bit Arm.

>> -   The packet format which
>> -   includes FPA registers should be considered deprecated for
>> -   M-profile targets.  */
>> -
>> -static void
>> -arm_register_g_packet_guesses (struct gdbarch *gdbarch)
>> -{
>> -  arm_gdbarch_tdep *tdep = gdbarch_tdep<arm_gdbarch_tdep> (gdbarch);
>> -
>> -  if (tdep->is_m)
>> -    {
>> -      const target_desc *tdesc;
>> -
>> -      /* If we know from the executable this is an M-profile target,
>> -	 cater for remote targets whose register set layout is the
>> -	 same as the FPA layout.  */
>> -      tdesc = arm_read_mprofile_description (ARM_M_TYPE_WITH_FPA);
>> -      register_remote_g_packet_guess (gdbarch,
>> -				      ARM_CORE_REGS_SIZE + ARM_FP_REGS_SIZE,
>> -				      tdesc);
>> -
>> -      /* The regular M-profile layout.  */
>> -      tdesc = arm_read_mprofile_description (ARM_M_TYPE_M_PROFILE);
>> -      register_remote_g_packet_guess (gdbarch, ARM_CORE_REGS_SIZE,
>> -				      tdesc);
>> -
>> -      /* M-profile plus M4F VFP.  */
>> -      tdesc = arm_read_mprofile_description (ARM_M_TYPE_VFP_D16);
>> -      register_remote_g_packet_guess (gdbarch,
>> -				      ARM_CORE_REGS_SIZE + ARM_VFP2_REGS_SIZE,
>> -				      tdesc);
>> -      /* M-profile plus MVE.  */
>> -      tdesc = arm_read_mprofile_description (ARM_M_TYPE_MVE);
>> -      register_remote_g_packet_guess (gdbarch, ARM_CORE_REGS_SIZE
>> -				      + ARM_VFP2_REGS_SIZE
>> -				      + ARM_INT_REGISTER_SIZE, tdesc);
>> -
>> -      /* M-profile system (stack pointers).  */
>> -      tdesc = arm_read_mprofile_description (ARM_M_TYPE_SYSTEM);
>> -      register_remote_g_packet_guess (gdbarch, 2 * ARM_INT_REGISTER_SIZE, tdesc);
> 
> And what about all these other non-FPA guesses?  Do you really mean to drop them?
> 

More recently we've added two new guesses for MVE and M-profile system registers, but it doesn't
make sense to do so, as these features are advertised as XML already. So in my opinion, we should
drop the g packet guesses completely and rely solely on XML descriptions.

>> -    }
>> -
>> -  /* Otherwise we don't have a useful guess.  */
>> -}
>> -
>>   /* Implement the code_of_frame_writable gdbarch method.  */
>>   
>>   static int
>
  
John Baldwin Oct. 4, 2022, 5:08 p.m. UTC | #7
On 10/4/22 1:43 AM, Luis Machado via Gdb-patches wrote:
> On 10/3/22 20:16, Pedro Alves wrote:
>> On 2022-09-20 1:30 p.m., Luis Machado via Gdb-patches wrote:
>>
>>> diff --git a/gdb/arch/arm.h b/gdb/arch/arm.h
>>> index 36757493406..74a6ba93bc7 100644
>>> --- a/gdb/arch/arm.h
>>> +++ b/gdb/arch/arm.h
>>> @@ -44,11 +44,6 @@ enum gdb_regnum {
>>>      ARM_SP_REGNUM = 13,		/* Contains address of top of stack */
>>>      ARM_LR_REGNUM = 14,		/* address to return to from a function call */
>>>      ARM_PC_REGNUM = 15,		/* Contains program counter */
>>> -  /* F0..F7 are the fp registers for the (obsolete) FPA architecture.  */
>>
>> Shouldn't we leave behind a comment explaining why there's a hole between 15 and 25?
> 
> I pondered about this a bit more, and I think we should close the gap and bring CPSR down to
> 16, its "natural" position. It is what linux uses for user_regs as well, in gdb/arch/arm-linux.h:
> 
> /* The index to access CSPR in user_regs defined in GLIBC.  */
> #define ARM_CPSR_GREGNUM 16
> 
>>
>> IIRC the numbers can't be changed since we need to handle the case when the target
>> doesn't send an xml tdesc, so it'd be good to help future readers understand why
>> there's a hole.
> 
> That's correct. Though a 32-bit Arm target that doesn't support XML descriptions these days is not very
> common. I haven't seen one in a while.
> 
> I'm willing to declare old 32-bit Arm targets that don't send XML target descriptions back as unsupported.
> 
> To that effect, I suppose we should add a note to make it more explicit.
> 
> More below.

FWIW, the GDB stub in FreeBSD's kernel does not use XML target descriptions
for any architectures, but it also only tends to do GPRs and not any floating
point.  For 32-bit ARM it does not report any register values higher than
number 15 (PC), so it would not be affected by changing this.

Do you know if LLDB supports floating-point registers on 32-bit arm as well?
The register numbers in the 'g' packet are effectively part of the protocol
shared between the two, so might be worth coording with lldb folks as well if
they support FPA?
  
Luis Machado Oct. 4, 2022, 5:43 p.m. UTC | #8
On 10/4/22 18:08, John Baldwin wrote:
> On 10/4/22 1:43 AM, Luis Machado via Gdb-patches wrote:
>> On 10/3/22 20:16, Pedro Alves wrote:
>>> On 2022-09-20 1:30 p.m., Luis Machado via Gdb-patches wrote:
>>>
>>>> diff --git a/gdb/arch/arm.h b/gdb/arch/arm.h
>>>> index 36757493406..74a6ba93bc7 100644
>>>> --- a/gdb/arch/arm.h
>>>> +++ b/gdb/arch/arm.h
>>>> @@ -44,11 +44,6 @@ enum gdb_regnum {
>>>>      ARM_SP_REGNUM = 13,        /* Contains address of top of stack */
>>>>      ARM_LR_REGNUM = 14,        /* address to return to from a function call */
>>>>      ARM_PC_REGNUM = 15,        /* Contains program counter */
>>>> -  /* F0..F7 are the fp registers for the (obsolete) FPA architecture.  */
>>>
>>> Shouldn't we leave behind a comment explaining why there's a hole between 15 and 25?
>>
>> I pondered about this a bit more, and I think we should close the gap and bring CPSR down to
>> 16, its "natural" position. It is what linux uses for user_regs as well, in gdb/arch/arm-linux.h:
>>
>> /* The index to access CSPR in user_regs defined in GLIBC.  */
>> #define ARM_CPSR_GREGNUM 16
>>
>>>
>>> IIRC the numbers can't be changed since we need to handle the case when the target
>>> doesn't send an xml tdesc, so it'd be good to help future readers understand why
>>> there's a hole.
>>
>> That's correct. Though a 32-bit Arm target that doesn't support XML descriptions these days is not very
>> common. I haven't seen one in a while.
>>
>> I'm willing to declare old 32-bit Arm targets that don't send XML target descriptions back as unsupported.
>>
>> To that effect, I suppose we should add a note to make it more explicit.
>>
>> More below.
> 
> FWIW, the GDB stub in FreeBSD's kernel does not use XML target descriptions
> for any architectures, but it also only tends to do GPRs and not any floating
> point.  For 32-bit ARM it does not report any register values higher than
> number 15 (PC), so it would not be affected by changing this.

Does it care about CPSR and/or XPSR? Could you please give it a try to see if the defaults would suit it just fine?

> 
> Do you know if LLDB supports floating-point registers on 32-bit arm as well?
> The register numbers in the 'g' packet are effectively part of the protocol
> shared between the two, so might be worth coording with lldb folks as well if
> they support FPA?
> 

It does seem to support FP registers, but not FPA.

For example, from https://github.com/llvm-mirror/lldb/blob/master/examples/python/armv7_cortex_m_target_defintion.py:

armv7_register_infos = [
{ 'name':'r0'   , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint  , 'format':eFormatAddressInfo, 'alt-name':'arg1' },
{ 'name':'r1'   , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint  , 'format':eFormatAddressInfo, 'alt-name':'arg2' },
{ 'name':'r2'   , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint  , 'format':eFormatAddressInfo, 'alt-name':'arg3' },
{ 'name':'r3'   , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint  , 'format':eFormatAddressInfo, 'alt-name':'arg4' },
{ 'name':'r4'   , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint  , 'format':eFormatAddressInfo   },
{ 'name':'r5'   , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint  , 'format':eFormatAddressInfo   },
{ 'name':'r6'   , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint  , 'format':eFormatAddressInfo   },
{ 'name':'r7'   , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint  , 'format':eFormatAddressInfo, 'alt-name':'fp'  },
{ 'name':'r8'   , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint  , 'format':eFormatAddressInfo   },
{ 'name':'r9'   , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint  , 'format':eFormatAddressInfo   },
{ 'name':'r10'  , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint  , 'format':eFormatAddressInfo   },
{ 'name':'r11'  , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint  , 'format':eFormatAddressInfo   },
{ 'name':'r12'  , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint  , 'format':eFormatAddressInfo   },
{ 'name':'sp'   , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint  , 'format':eFormatAddressInfo, 'alt-name':'r13'  },
{ 'name':'lr'   , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint  , 'format':eFormatAddressInfo, 'alt-name':'r14'  },
{ 'name':'pc'   , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint  , 'format':eFormatAddressInfo, 'alt-name':'r15'  },
{ 'name':'xpsr' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint  , 'format':eFormatAddressInfo, 'alt-name':'cpsr' },
];

Also, for the SEGGER J-Link:

<!DOCTYPE feature SYSTEM "gdb-target.dtd">
<target version="1.0">
   <architecture>arm</architecture>
   <feature name="org.gnu.gdb.arm.m-profile">
     <reg name="r0" bitsize="32" regnum="0" type="uint32" group="general"/>
     <reg name="r1" bitsize="32" regnum="1" type="uint32" group="general"/>
     <reg name="r2" bitsize="32" regnum="2" type="uint32" group="general"/>
     <reg name="r3" bitsize="32" regnum="3" type="uint32" group="general"/>
     <reg name="r4" bitsize="32" regnum="4" type="uint32" group="general"/>
     <reg name="r5" bitsize="32" regnum="5" type="uint32" group="general"/>
     <reg name="r6" bitsize="32" regnum="6" type="uint32" group="general"/>
     <reg name="r7" bitsize="32" regnum="7" type="uint32" group="general"/>
     <reg name="r8" bitsize="32" regnum="8" type="uint32" group="general"/>
     <reg name="r9" bitsize="32" regnum="9" type="uint32" group="general"/>
     <reg name="r10" bitsize="32" regnum="10" type="uint32" group="general"/>
     <reg name="r11" bitsize="32" regnum="11" type="uint32" group="general"/>
     <reg name="r12" bitsize="32" regnum="12" type="uint32" group="general"/>
     <reg name="sp" bitsize="32" regnum="13" type="data_ptr" group="general"/>
     <reg name="lr" bitsize="32" regnum="14" type="uint32" group="general"/>
     <reg name="pc" bitsize="32" regnum="15" type="code_ptr" group="general"/>
     <reg name="xpsr" bitsize="32" regnum="25" type="uint32" group="general"/>
   </feature>
   <feature name="org.gnu.gdb.arm.m-system">
     <reg name="msp" bitsize="32" regnum="26" type="uint32" group="general"/>
     <reg name="psp" bitsize="32" regnum="27" type="uint32" group="general"/>
     <reg name="primask" bitsize="32" regnum="28" type="uint32" group="general"/>
     <reg name="basepri" bitsize="32" regnum="29" type="uint32" group="general"/>
     <reg name="faultmask" bitsize="32" regnum="30" type="uint32" group="general"/>
     <reg name="control" bitsize="32" regnum="31" type="uint32" group="general"/>
   </feature>
   <feature name="org.gnu.gdb.arm.m-float">
     <reg name="fpscr" bitsize="32" regnum="32" type="uint32" group="float"/>
     <reg name="s0" bitsize="32" regnum="33" type="float" group="float"/>
     <reg name="s1" bitsize="32" regnum="34" type="float" group="float"/>
     <reg name="s2" bitsize="32" regnum="35" type="float" group="float"/>
     <reg name="s3" bitsize="32" regnum="36" type="float" group="float"/>
     <reg name="s4" bitsize="32" regnum="37" type="float" group="float"/>
     <reg name="s5" bitsize="32" regnum="38" type="float" group="float"/>
     <reg name="s6" bitsize="32" regnum="39" type="float" group="float"/>
     <reg name="s7" bitsize="32" regnum="40" type="float" group="float"/>
     <reg name="s8" bitsize="32" regnum="41" type="float" group="float"/>
     <reg name="s9" bitsize="32" regnum="42" type="float" group="float"/>
     <reg name="s10" bitsize="32" regnum="43" type="float" group="float"/>
     <reg name="s11" bitsize="32" regnum="44" type="float" group="float"/>
     <reg name="s12" bitsize="32" regnum="45" type="float" group="float"/>
     <reg name="s13" bitsize="32" regnum="46" type="float" group="float"/>
     <reg name="s14" bitsize="32" regnum="47" type="float" group="float"/>
     <reg name="s15" bitsize="32" regnum="48" type="float" group="float"/>
     <reg name="s16" bitsize="32" regnum="49" type="float" group="float"/>
     <reg name="s17" bitsize="32" regnum="50" type="float" group="float"/>
     <reg name="s18" bitsize="32" regnum="51" type="float" group="float"/>
     <reg name="s19" bitsize="32" regnum="52" type="float" group="float"/>
     <reg name="s20" bitsize="32" regnum="53" type="float" group="float"/>
     <reg name="s21" bitsize="32" regnum="54" type="float" group="float"/>
     <reg name="s22" bitsize="32" regnum="55" type="float" group="float"/>
     <reg name="s23" bitsize="32" regnum="56" type="float" group="float"/>
     <reg name="s24" bitsize="32" regnum="57" type="float" group="float"/>
     <reg name="s25" bitsize="32" regnum="58" type="float" group="float"/>
     <reg name="s26" bitsize="32" regnum="59" type="float" group="float"/>
     <reg name="s27" bitsize="32" regnum="60" type="float" group="float"/>
     <reg name="s28" bitsize="32" regnum="61" type="float" group="float"/>
     <reg name="s29" bitsize="32" regnum="62" type="float" group="float"/>
     <reg name="s30" bitsize="32" regnum="63" type="float" group="float"/>
     <reg name="s31" bitsize="32" regnum="64" type="float" group="float"/>
     <reg name="d0" bitsize="64" regnum="65" type="ieee_double" group="float"/>
     <reg name="d1" bitsize="64" regnum="66" type="ieee_double" group="float"/>
     <reg name="d2" bitsize="64" regnum="67" type="ieee_double" group="float"/>
     <reg name="d3" bitsize="64" regnum="68" type="ieee_double" group="float"/>
     <reg name="d4" bitsize="64" regnum="69" type="ieee_double" group="float"/>
     <reg name="d5" bitsize="64" regnum="70" type="ieee_double" group="float"/>
     <reg name="d6" bitsize="64" regnum="71" type="ieee_double" group="float"/>
     <reg name="d7" bitsize="64" regnum="72" type="ieee_double" group="float"/>
     <reg name="d8" bitsize="64" regnum="73" type="ieee_double" group="float"/>
     <reg name="d9" bitsize="64" regnum="74" type="ieee_double" group="float"/>
     <reg name="d10" bitsize="64" regnum="75" type="ieee_double" group="float"/>
     <reg name="d11" bitsize="64" regnum="76" type="ieee_double" group="float"/>
     <reg name="d12" bitsize="64" regnum="77" type="ieee_double" group="float"/>
     <reg name="d13" bitsize="64" regnum="78" type="ieee_double" group="float"/>
     <reg name="d14" bitsize="64" regnum="79" type="ieee_double" group="float"/>
     <reg name="d15" bitsize="64" regnum="80" type="ieee_double" group="float"/>
   </feature>
</target>

David, does LLDB actively maintain register descriptions for 32-bit Arm?
  
John Baldwin Oct. 4, 2022, 9:36 p.m. UTC | #9
On 10/4/22 10:43 AM, Luis Machado wrote:
> On 10/4/22 18:08, John Baldwin wrote:
>> On 10/4/22 1:43 AM, Luis Machado via Gdb-patches wrote:
>>> On 10/3/22 20:16, Pedro Alves wrote:
>>>> On 2022-09-20 1:30 p.m., Luis Machado via Gdb-patches wrote:
>>>>
>>>>> diff --git a/gdb/arch/arm.h b/gdb/arch/arm.h
>>>>> index 36757493406..74a6ba93bc7 100644
>>>>> --- a/gdb/arch/arm.h
>>>>> +++ b/gdb/arch/arm.h
>>>>> @@ -44,11 +44,6 @@ enum gdb_regnum {
>>>>>       ARM_SP_REGNUM = 13,        /* Contains address of top of stack */
>>>>>       ARM_LR_REGNUM = 14,        /* address to return to from a function call */
>>>>>       ARM_PC_REGNUM = 15,        /* Contains program counter */
>>>>> -  /* F0..F7 are the fp registers for the (obsolete) FPA architecture.  */
>>>>
>>>> Shouldn't we leave behind a comment explaining why there's a hole between 15 and 25?
>>>
>>> I pondered about this a bit more, and I think we should close the gap and bring CPSR down to
>>> 16, its "natural" position. It is what linux uses for user_regs as well, in gdb/arch/arm-linux.h:
>>>
>>> /* The index to access CSPR in user_regs defined in GLIBC.  */
>>> #define ARM_CPSR_GREGNUM 16
>>>
>>>>
>>>> IIRC the numbers can't be changed since we need to handle the case when the target
>>>> doesn't send an xml tdesc, so it'd be good to help future readers understand why
>>>> there's a hole.
>>>
>>> That's correct. Though a 32-bit Arm target that doesn't support XML descriptions these days is not very
>>> common. I haven't seen one in a while.
>>>
>>> I'm willing to declare old 32-bit Arm targets that don't send XML target descriptions back as unsupported.
>>>
>>> To that effect, I suppose we should add a note to make it more explicit.
>>>
>>> More below.
>>
>> FWIW, the GDB stub in FreeBSD's kernel does not use XML target descriptions
>> for any architectures, but it also only tends to do GPRs and not any floating
>> point.  For 32-bit ARM it does not report any register values higher than
>> number 15 (PC), so it would not be affected by changing this.
> 
> Does it care about CPSR and/or XPSR? Could you please give it a try to see if the defaults would suit it just fine?

Hmm, I misread and it does care about CPSR for the current thread.  The
relevant code is here (From https://cgit.freebsd.org/src/tree/sys/arm/arm/gdb_machdep.c):

void *
gdb_cpu_getreg(int regnum, size_t *regsz)
{

	*regsz = gdb_cpu_regsz(regnum);

	if (kdb_thread == curthread) {
		if (regnum < 13)
			return (&kdb_frame->tf_r0 + regnum);
		if (regnum == 13)
			return (&kdb_frame->tf_svc_sp);
		if (regnum == 14)
			return (&kdb_frame->tf_svc_lr);
		if (regnum == 15)
			return (&kdb_frame->tf_pc);
		if (regnum == 25)
			return (&kdb_frame->tf_spsr);
	}

	switch (regnum) {
	case 4:  return (&kdb_thrctx->pcb_regs.sf_r4);
	case 5:  return (&kdb_thrctx->pcb_regs.sf_r5);
	case 6:  return (&kdb_thrctx->pcb_regs.sf_r6);
	case 7:  return (&kdb_thrctx->pcb_regs.sf_r7);
	case 8:  return (&kdb_thrctx->pcb_regs.sf_r8);
	case 9:  return (&kdb_thrctx->pcb_regs.sf_r9);
	case 10:  return (&kdb_thrctx->pcb_regs.sf_r10);
	case 11:  return (&kdb_thrctx->pcb_regs.sf_r11);
	case 12:  return (&kdb_thrctx->pcb_regs.sf_r12);
	case 13:  stacktest = kdb_thrctx->pcb_regs.sf_sp + 5 * 4;
		  return (&stacktest);
	case 15:
		  /*
		   * On context switch, the PC is not put in the PCB, but
		   * we can retrieve it from the stack.
		   */
		  if (kdb_thrctx->pcb_regs.sf_sp > KERNBASE) {
			  kdb_thrctx->pcb_regs.sf_pc = *(register_t *)
			      (kdb_thrctx->pcb_regs.sf_sp + 4 * 4);
			  return (&kdb_thrctx->pcb_regs.sf_pc);
		  }
	}

	return (NULL);
}

The 'kdb_thread == curthread' case is when a thread enters the debugger due
to a crash or breakpoint, etc.  We do return CPSR for that thread, but we do
not return it for other threads.  It looks like we do also know the FPA register
size so that we return enough "xx" bytes in the 'g' reply to mark the FP
registers as unavailable so that we can return the value of CPSR in the 'g'
reply.

 From https://cgit.freebsd.org/src/tree/sys/arm/include/gdb_machdep.h:

#define	GDB_NREGS	26
#define	GDB_REG_SP	13
#define	GDB_REG_LR	14
#define	GDB_REG_PC	15

static __inline size_t
gdb_cpu_regsz(int regnum)
{
	/*
	 * GDB expects the FPA registers f0-f7, each 96 bits wide, to be placed
	 * in between the PC and CSPR in response to a "g" packet.
	 */
	return (regnum >= 16 && regnum <= 23 ? 12 : sizeof(int));
}

NetBSD's kernel seems to have similar knowledge:

http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/arch/arm/include/db_machdep.h?rev=1.28&content-type=text/x-cvsweb-markup&only_with_tag=MAIN

(The kgdb bits near the bottom)

Linux's kernel also seems to maybe hardcode this knowledge as well:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm/kernel/kgdb.c#n21
  
Luis Machado Oct. 5, 2022, 8:26 a.m. UTC | #10
On 10/4/22 22:36, John Baldwin wrote:
> On 10/4/22 10:43 AM, Luis Machado wrote:
>> On 10/4/22 18:08, John Baldwin wrote:
>>> On 10/4/22 1:43 AM, Luis Machado via Gdb-patches wrote:
>>>> On 10/3/22 20:16, Pedro Alves wrote:
>>>>> On 2022-09-20 1:30 p.m., Luis Machado via Gdb-patches wrote:
>>>>>
>>>>>> diff --git a/gdb/arch/arm.h b/gdb/arch/arm.h
>>>>>> index 36757493406..74a6ba93bc7 100644
>>>>>> --- a/gdb/arch/arm.h
>>>>>> +++ b/gdb/arch/arm.h
>>>>>> @@ -44,11 +44,6 @@ enum gdb_regnum {
>>>>>>       ARM_SP_REGNUM = 13,        /* Contains address of top of stack */
>>>>>>       ARM_LR_REGNUM = 14,        /* address to return to from a function call */
>>>>>>       ARM_PC_REGNUM = 15,        /* Contains program counter */
>>>>>> -  /* F0..F7 are the fp registers for the (obsolete) FPA architecture.  */
>>>>>
>>>>> Shouldn't we leave behind a comment explaining why there's a hole between 15 and 25?
>>>>
>>>> I pondered about this a bit more, and I think we should close the gap and bring CPSR down to
>>>> 16, its "natural" position. It is what linux uses for user_regs as well, in gdb/arch/arm-linux.h:
>>>>
>>>> /* The index to access CSPR in user_regs defined in GLIBC.  */
>>>> #define ARM_CPSR_GREGNUM 16
>>>>
>>>>>
>>>>> IIRC the numbers can't be changed since we need to handle the case when the target
>>>>> doesn't send an xml tdesc, so it'd be good to help future readers understand why
>>>>> there's a hole.
>>>>
>>>> That's correct. Though a 32-bit Arm target that doesn't support XML descriptions these days is not very
>>>> common. I haven't seen one in a while.
>>>>
>>>> I'm willing to declare old 32-bit Arm targets that don't send XML target descriptions back as unsupported.
>>>>
>>>> To that effect, I suppose we should add a note to make it more explicit.
>>>>
>>>> More below.
>>>
>>> FWIW, the GDB stub in FreeBSD's kernel does not use XML target descriptions
>>> for any architectures, but it also only tends to do GPRs and not any floating
>>> point.  For 32-bit ARM it does not report any register values higher than
>>> number 15 (PC), so it would not be affected by changing this.
>>
>> Does it care about CPSR and/or XPSR? Could you please give it a try to see if the defaults would suit it just fine?
> 
> Hmm, I misread and it does care about CPSR for the current thread.  The
> relevant code is here (From https://cgit.freebsd.org/src/tree/sys/arm/arm/gdb_machdep.c):
> 
> void *
> gdb_cpu_getreg(int regnum, size_t *regsz)
> {
> 
>      *regsz = gdb_cpu_regsz(regnum);
> 
>      if (kdb_thread == curthread) {
>          if (regnum < 13)
>              return (&kdb_frame->tf_r0 + regnum);
>          if (regnum == 13)
>              return (&kdb_frame->tf_svc_sp);
>          if (regnum == 14)
>              return (&kdb_frame->tf_svc_lr);
>          if (regnum == 15)
>              return (&kdb_frame->tf_pc);
>          if (regnum == 25)
>              return (&kdb_frame->tf_spsr);
>      }
> 
>      switch (regnum) {
>      case 4:  return (&kdb_thrctx->pcb_regs.sf_r4);
>      case 5:  return (&kdb_thrctx->pcb_regs.sf_r5);
>      case 6:  return (&kdb_thrctx->pcb_regs.sf_r6);
>      case 7:  return (&kdb_thrctx->pcb_regs.sf_r7);
>      case 8:  return (&kdb_thrctx->pcb_regs.sf_r8);
>      case 9:  return (&kdb_thrctx->pcb_regs.sf_r9);
>      case 10:  return (&kdb_thrctx->pcb_regs.sf_r10);
>      case 11:  return (&kdb_thrctx->pcb_regs.sf_r11);
>      case 12:  return (&kdb_thrctx->pcb_regs.sf_r12);
>      case 13:  stacktest = kdb_thrctx->pcb_regs.sf_sp + 5 * 4;
>            return (&stacktest);
>      case 15:
>            /*
>             * On context switch, the PC is not put in the PCB, but
>             * we can retrieve it from the stack.
>             */
>            if (kdb_thrctx->pcb_regs.sf_sp > KERNBASE) {
>                kdb_thrctx->pcb_regs.sf_pc = *(register_t *)
>                    (kdb_thrctx->pcb_regs.sf_sp + 4 * 4);
>                return (&kdb_thrctx->pcb_regs.sf_pc);
>            }
>      }
> 
>      return (NULL);
> }
> 
> The 'kdb_thread == curthread' case is when a thread enters the debugger due
> to a crash or breakpoint, etc.  We do return CPSR for that thread, but we do
> not return it for other threads.  It looks like we do also know the FPA register
> size so that we return enough "xx" bytes in the 'g' reply to mark the FP
> registers as unavailable so that we can return the value of CPSR in the 'g'
> reply.
> 
>  From https://cgit.freebsd.org/src/tree/sys/arm/include/gdb_machdep.h:
> 
> #define    GDB_NREGS    26
> #define    GDB_REG_SP    13
> #define    GDB_REG_LR    14
> #define    GDB_REG_PC    15
> 
> static __inline size_t
> gdb_cpu_regsz(int regnum)
> {
>      /*
>       * GDB expects the FPA registers f0-f7, each 96 bits wide, to be placed
>       * in between the PC and CSPR in response to a "g" packet.
>       */
>      return (regnum >= 16 && regnum <= 23 ? 12 : sizeof(int));
> }
> 
> NetBSD's kernel seems to have similar knowledge:
> 
> http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/arch/arm/include/db_machdep.h?rev=1.28&content-type=text/x-cvsweb-markup&only_with_tag=MAIN
> 
> (The kgdb bits near the bottom)
> 
> Linux's kernel also seems to maybe hardcode this knowledge as well:
> 
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm/kernel/kgdb.c#n21
> 

Yeah, that's what I was worried about. Register discoveries without XML are not great, and more recently debugging stubs have been
exposing more system registers. Having to consider FPA (which was *removed* 10 years ago from GCC, but fell in disuse before then) is not
acceptable at this point.

If those debugging stubs want to skip XML, I think it would be reasonable for them to at least update the expected 'g' packet to contain just
the basic registers, with CPSR as 16.

That might need some coordination. I can coordinate this from the Linux Kernel's side, but I never dealt with the BSD kernels.
  
David Spickett Oct. 5, 2022, 8:36 a.m. UTC | #11
> David, does LLDB actively maintain register descriptions for 32-bit Arm?

LLDB has 4 mechanisms for describing registers:

  *   XML register info (lldb-server doesn't generate this itself for 32-bit Arm but lldb will read it if given)
  *   qRegisterInfo packet, which tells you the offset of a given register index in the G packet amongst other things (this is an lldb specific packet iirc)
  *   A script like the one you linked to
  *   A fallback set of register defs hardcoded. This only has registers for AArch64, x86 and x86_64 and only includes general purpose registers.

As for FPA support all we have is the DWARF numbers. Pretty safe to say no support.
  
John Baldwin Oct. 5, 2022, 4:48 p.m. UTC | #12
On 10/5/22 1:26 AM, Luis Machado wrote:
> On 10/4/22 22:36, John Baldwin wrote:
>> On 10/4/22 10:43 AM, Luis Machado wrote:
>>> On 10/4/22 18:08, John Baldwin wrote:
>>>> On 10/4/22 1:43 AM, Luis Machado via Gdb-patches wrote:
>>>>> On 10/3/22 20:16, Pedro Alves wrote:
>>>>>> On 2022-09-20 1:30 p.m., Luis Machado via Gdb-patches wrote:
>>>>>>
>>>>>>> diff --git a/gdb/arch/arm.h b/gdb/arch/arm.h
>>>>>>> index 36757493406..74a6ba93bc7 100644
>>>>>>> --- a/gdb/arch/arm.h
>>>>>>> +++ b/gdb/arch/arm.h
>>>>>>> @@ -44,11 +44,6 @@ enum gdb_regnum {
>>>>>>>        ARM_SP_REGNUM = 13,        /* Contains address of top of stack */
>>>>>>>        ARM_LR_REGNUM = 14,        /* address to return to from a function call */
>>>>>>>        ARM_PC_REGNUM = 15,        /* Contains program counter */
>>>>>>> -  /* F0..F7 are the fp registers for the (obsolete) FPA architecture.  */
>>>>>>
>>>>>> Shouldn't we leave behind a comment explaining why there's a hole between 15 and 25?
>>>>>
>>>>> I pondered about this a bit more, and I think we should close the gap and bring CPSR down to
>>>>> 16, its "natural" position. It is what linux uses for user_regs as well, in gdb/arch/arm-linux.h:
>>>>>
>>>>> /* The index to access CSPR in user_regs defined in GLIBC.  */
>>>>> #define ARM_CPSR_GREGNUM 16
>>>>>
>>>>>>
>>>>>> IIRC the numbers can't be changed since we need to handle the case when the target
>>>>>> doesn't send an xml tdesc, so it'd be good to help future readers understand why
>>>>>> there's a hole.
>>>>>
>>>>> That's correct. Though a 32-bit Arm target that doesn't support XML descriptions these days is not very
>>>>> common. I haven't seen one in a while.
>>>>>
>>>>> I'm willing to declare old 32-bit Arm targets that don't send XML target descriptions back as unsupported.
>>>>>
>>>>> To that effect, I suppose we should add a note to make it more explicit.
>>>>>
>>>>> More below.
>>>>
>>>> FWIW, the GDB stub in FreeBSD's kernel does not use XML target descriptions
>>>> for any architectures, but it also only tends to do GPRs and not any floating
>>>> point.  For 32-bit ARM it does not report any register values higher than
>>>> number 15 (PC), so it would not be affected by changing this.
>>>
>>> Does it care about CPSR and/or XPSR? Could you please give it a try to see if the defaults would suit it just fine?
>>
>> Hmm, I misread and it does care about CPSR for the current thread.  The
>> relevant code is here (From https://cgit.freebsd.org/src/tree/sys/arm/arm/gdb_machdep.c):
>>
>> void *
>> gdb_cpu_getreg(int regnum, size_t *regsz)
>> {
>>
>>       *regsz = gdb_cpu_regsz(regnum);
>>
>>       if (kdb_thread == curthread) {
>>           if (regnum < 13)
>>               return (&kdb_frame->tf_r0 + regnum);
>>           if (regnum == 13)
>>               return (&kdb_frame->tf_svc_sp);
>>           if (regnum == 14)
>>               return (&kdb_frame->tf_svc_lr);
>>           if (regnum == 15)
>>               return (&kdb_frame->tf_pc);
>>           if (regnum == 25)
>>               return (&kdb_frame->tf_spsr);
>>       }
>>
>>       switch (regnum) {
>>       case 4:  return (&kdb_thrctx->pcb_regs.sf_r4);
>>       case 5:  return (&kdb_thrctx->pcb_regs.sf_r5);
>>       case 6:  return (&kdb_thrctx->pcb_regs.sf_r6);
>>       case 7:  return (&kdb_thrctx->pcb_regs.sf_r7);
>>       case 8:  return (&kdb_thrctx->pcb_regs.sf_r8);
>>       case 9:  return (&kdb_thrctx->pcb_regs.sf_r9);
>>       case 10:  return (&kdb_thrctx->pcb_regs.sf_r10);
>>       case 11:  return (&kdb_thrctx->pcb_regs.sf_r11);
>>       case 12:  return (&kdb_thrctx->pcb_regs.sf_r12);
>>       case 13:  stacktest = kdb_thrctx->pcb_regs.sf_sp + 5 * 4;
>>             return (&stacktest);
>>       case 15:
>>             /*
>>              * On context switch, the PC is not put in the PCB, but
>>              * we can retrieve it from the stack.
>>              */
>>             if (kdb_thrctx->pcb_regs.sf_sp > KERNBASE) {
>>                 kdb_thrctx->pcb_regs.sf_pc = *(register_t *)
>>                     (kdb_thrctx->pcb_regs.sf_sp + 4 * 4);
>>                 return (&kdb_thrctx->pcb_regs.sf_pc);
>>             }
>>       }
>>
>>       return (NULL);
>> }
>>
>> The 'kdb_thread == curthread' case is when a thread enters the debugger due
>> to a crash or breakpoint, etc.  We do return CPSR for that thread, but we do
>> not return it for other threads.  It looks like we do also know the FPA register
>> size so that we return enough "xx" bytes in the 'g' reply to mark the FP
>> registers as unavailable so that we can return the value of CPSR in the 'g'
>> reply.
>>
>>   From https://cgit.freebsd.org/src/tree/sys/arm/include/gdb_machdep.h:
>>
>> #define    GDB_NREGS    26
>> #define    GDB_REG_SP    13
>> #define    GDB_REG_LR    14
>> #define    GDB_REG_PC    15
>>
>> static __inline size_t
>> gdb_cpu_regsz(int regnum)
>> {
>>       /*
>>        * GDB expects the FPA registers f0-f7, each 96 bits wide, to be placed
>>        * in between the PC and CSPR in response to a "g" packet.
>>        */
>>       return (regnum >= 16 && regnum <= 23 ? 12 : sizeof(int));
>> }
>>
>> NetBSD's kernel seems to have similar knowledge:
>>
>> http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/arch/arm/include/db_machdep.h?rev=1.28&content-type=text/x-cvsweb-markup&only_with_tag=MAIN
>>
>> (The kgdb bits near the bottom)
>>
>> Linux's kernel also seems to maybe hardcode this knowledge as well:
>>
>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm/kernel/kgdb.c#n21
>>
> 
> Yeah, that's what I was worried about. Register discoveries without XML are not great, and more recently debugging stubs have been
> exposing more system registers. Having to consider FPA (which was *removed* 10 years ago from GCC, but fell in disuse before then) is not
> acceptable at this point.
> 
> If those debugging stubs want to skip XML, I think it would be reasonable for them to at least update the expected 'g' packet to contain just
> the basic registers, with CPSR as 16.
> 
> That might need some coordination. I can coordinate this from the Linux Kernel's side, but I never dealt with the BSD kernels.

I can certainly deal with updating FreeBSD.  I can try to find someone over in NetBSD
land.  Honestly, the simplest approach might be to start exporting XML from the
kernel.  However, an even simpler workaround for now might be having a knob that
can be set for older debugger binaries that still places CPSR at the old register
number vs the newer one.
  
Richard Earnshaw Oct. 5, 2022, 4:57 p.m. UTC | #13
On 05/10/2022 17:48, John Baldwin wrote:
> On 10/5/22 1:26 AM, Luis Machado wrote:
>> On 10/4/22 22:36, John Baldwin wrote:
>>> On 10/4/22 10:43 AM, Luis Machado wrote:
>>>> On 10/4/22 18:08, John Baldwin wrote:
>>>>> On 10/4/22 1:43 AM, Luis Machado via Gdb-patches wrote:
>>>>>> On 10/3/22 20:16, Pedro Alves wrote:
>>>>>>> On 2022-09-20 1:30 p.m., Luis Machado via Gdb-patches wrote:
>>>>>>>
>>>>>>>> diff --git a/gdb/arch/arm.h b/gdb/arch/arm.h
>>>>>>>> index 36757493406..74a6ba93bc7 100644
>>>>>>>> --- a/gdb/arch/arm.h
>>>>>>>> +++ b/gdb/arch/arm.h
>>>>>>>> @@ -44,11 +44,6 @@ enum gdb_regnum {
>>>>>>>>        ARM_SP_REGNUM = 13,        /* Contains address of top of 
>>>>>>>> stack */
>>>>>>>>        ARM_LR_REGNUM = 14,        /* address to return to from a 
>>>>>>>> function call */
>>>>>>>>        ARM_PC_REGNUM = 15,        /* Contains program counter */
>>>>>>>> -  /* F0..F7 are the fp registers for the (obsolete) FPA 
>>>>>>>> architecture.  */
>>>>>>>
>>>>>>> Shouldn't we leave behind a comment explaining why there's a hole 
>>>>>>> between 15 and 25?
>>>>>>
>>>>>> I pondered about this a bit more, and I think we should close the 
>>>>>> gap and bring CPSR down to
>>>>>> 16, its "natural" position. It is what linux uses for user_regs as 
>>>>>> well, in gdb/arch/arm-linux.h:
>>>>>>
>>>>>> /* The index to access CSPR in user_regs defined in GLIBC.  */
>>>>>> #define ARM_CPSR_GREGNUM 16
>>>>>>
>>>>>>>
>>>>>>> IIRC the numbers can't be changed since we need to handle the 
>>>>>>> case when the target
>>>>>>> doesn't send an xml tdesc, so it'd be good to help future readers 
>>>>>>> understand why
>>>>>>> there's a hole.
>>>>>>
>>>>>> That's correct. Though a 32-bit Arm target that doesn't support 
>>>>>> XML descriptions these days is not very
>>>>>> common. I haven't seen one in a while.
>>>>>>
>>>>>> I'm willing to declare old 32-bit Arm targets that don't send XML 
>>>>>> target descriptions back as unsupported.
>>>>>>
>>>>>> To that effect, I suppose we should add a note to make it more 
>>>>>> explicit.
>>>>>>
>>>>>> More below.
>>>>>
>>>>> FWIW, the GDB stub in FreeBSD's kernel does not use XML target 
>>>>> descriptions
>>>>> for any architectures, but it also only tends to do GPRs and not 
>>>>> any floating
>>>>> point.  For 32-bit ARM it does not report any register values 
>>>>> higher than
>>>>> number 15 (PC), so it would not be affected by changing this.
>>>>
>>>> Does it care about CPSR and/or XPSR? Could you please give it a try 
>>>> to see if the defaults would suit it just fine?
>>>
>>> Hmm, I misread and it does care about CPSR for the current thread.  The
>>> relevant code is here (From 
>>> https://cgit.freebsd.org/src/tree/sys/arm/arm/gdb_machdep.c):
>>>
>>> void *
>>> gdb_cpu_getreg(int regnum, size_t *regsz)
>>> {
>>>
>>>       *regsz = gdb_cpu_regsz(regnum);
>>>
>>>       if (kdb_thread == curthread) {
>>>           if (regnum < 13)
>>>               return (&kdb_frame->tf_r0 + regnum);
>>>           if (regnum == 13)
>>>               return (&kdb_frame->tf_svc_sp);
>>>           if (regnum == 14)
>>>               return (&kdb_frame->tf_svc_lr);
>>>           if (regnum == 15)
>>>               return (&kdb_frame->tf_pc);
>>>           if (regnum == 25)
>>>               return (&kdb_frame->tf_spsr);
>>>       }
>>>
>>>       switch (regnum) {
>>>       case 4:  return (&kdb_thrctx->pcb_regs.sf_r4);
>>>       case 5:  return (&kdb_thrctx->pcb_regs.sf_r5);
>>>       case 6:  return (&kdb_thrctx->pcb_regs.sf_r6);
>>>       case 7:  return (&kdb_thrctx->pcb_regs.sf_r7);
>>>       case 8:  return (&kdb_thrctx->pcb_regs.sf_r8);
>>>       case 9:  return (&kdb_thrctx->pcb_regs.sf_r9);
>>>       case 10:  return (&kdb_thrctx->pcb_regs.sf_r10);
>>>       case 11:  return (&kdb_thrctx->pcb_regs.sf_r11);
>>>       case 12:  return (&kdb_thrctx->pcb_regs.sf_r12);
>>>       case 13:  stacktest = kdb_thrctx->pcb_regs.sf_sp + 5 * 4;
>>>             return (&stacktest);
>>>       case 15:
>>>             /*
>>>              * On context switch, the PC is not put in the PCB, but
>>>              * we can retrieve it from the stack.
>>>              */
>>>             if (kdb_thrctx->pcb_regs.sf_sp > KERNBASE) {
>>>                 kdb_thrctx->pcb_regs.sf_pc = *(register_t *)
>>>                     (kdb_thrctx->pcb_regs.sf_sp + 4 * 4);
>>>                 return (&kdb_thrctx->pcb_regs.sf_pc);
>>>             }
>>>       }
>>>
>>>       return (NULL);
>>> }
>>>
>>> The 'kdb_thread == curthread' case is when a thread enters the 
>>> debugger due
>>> to a crash or breakpoint, etc.  We do return CPSR for that thread, 
>>> but we do
>>> not return it for other threads.  It looks like we do also know the 
>>> FPA register
>>> size so that we return enough "xx" bytes in the 'g' reply to mark the FP
>>> registers as unavailable so that we can return the value of CPSR in 
>>> the 'g'
>>> reply.
>>>
>>>   From https://cgit.freebsd.org/src/tree/sys/arm/include/gdb_machdep.h:
>>>
>>> #define    GDB_NREGS    26
>>> #define    GDB_REG_SP    13
>>> #define    GDB_REG_LR    14
>>> #define    GDB_REG_PC    15
>>>
>>> static __inline size_t
>>> gdb_cpu_regsz(int regnum)
>>> {
>>>       /*
>>>        * GDB expects the FPA registers f0-f7, each 96 bits wide, to 
>>> be placed
>>>        * in between the PC and CSPR in response to a "g" packet.
>>>        */
>>>       return (regnum >= 16 && regnum <= 23 ? 12 : sizeof(int));
>>> }
>>>
>>> NetBSD's kernel seems to have similar knowledge:
>>>
>>> http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/arch/arm/include/db_machdep.h?rev=1.28&content-type=text/x-cvsweb-markup&only_with_tag=MAIN 
>>>
>>>
>>> (The kgdb bits near the bottom)
>>>
>>> Linux's kernel also seems to maybe hardcode this knowledge as well:
>>>
>>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm/kernel/kgdb.c#n21 
>>>
>>>
>>
>> Yeah, that's what I was worried about. Register discoveries without 
>> XML are not great, and more recently debugging stubs have been
>> exposing more system registers. Having to consider FPA (which was 
>> *removed* 10 years ago from GCC, but fell in disuse before then) is not
>> acceptable at this point.
>>
>> If those debugging stubs want to skip XML, I think it would be 
>> reasonable for them to at least update the expected 'g' packet to 
>> contain just
>> the basic registers, with CPSR as 16.
>>
>> That might need some coordination. I can coordinate this from the 
>> Linux Kernel's side, but I never dealt with the BSD kernels.
> 
> I can certainly deal with updating FreeBSD.  I can try to find someone 
> over in NetBSD
> land.  Honestly, the simplest approach might be to start exporting XML 
> from the
> kernel.  However, an even simpler workaround for now might be having a 
> knob that
> can be set for older debugger binaries that still places CPSR at the old 
> register
> number vs the newer one.
> 

IMO, exporting an XML description of the register set(s) available is 
certainly the right way forward.  In fact, I'd strongly suggest we leave 
the existing packet formats as-is for now and add support for XML to the 
relevant kernels.  At some point then gdb (and LLDB) can simply stop 
working with older kernel versions that don't do it the 'right' way.

R.
  
Luis Machado Oct. 6, 2022, 1:02 p.m. UTC | #14
On 10/5/22 17:57, Richard Earnshaw wrote:
> 
> 
> On 05/10/2022 17:48, John Baldwin wrote:
>> On 10/5/22 1:26 AM, Luis Machado wrote:
>>> On 10/4/22 22:36, John Baldwin wrote:
>>>> On 10/4/22 10:43 AM, Luis Machado wrote:
>>>>> On 10/4/22 18:08, John Baldwin wrote:
>>>>>> On 10/4/22 1:43 AM, Luis Machado via Gdb-patches wrote:
>>>>>>> On 10/3/22 20:16, Pedro Alves wrote:
>>>>>>>> On 2022-09-20 1:30 p.m., Luis Machado via Gdb-patches wrote:
>>>>>>>>
>>>>>>>>> diff --git a/gdb/arch/arm.h b/gdb/arch/arm.h
>>>>>>>>> index 36757493406..74a6ba93bc7 100644
>>>>>>>>> --- a/gdb/arch/arm.h
>>>>>>>>> +++ b/gdb/arch/arm.h
>>>>>>>>> @@ -44,11 +44,6 @@ enum gdb_regnum {
>>>>>>>>>        ARM_SP_REGNUM = 13,        /* Contains address of top of stack */
>>>>>>>>>        ARM_LR_REGNUM = 14,        /* address to return to from a function call */
>>>>>>>>>        ARM_PC_REGNUM = 15,        /* Contains program counter */
>>>>>>>>> -  /* F0..F7 are the fp registers for the (obsolete) FPA architecture.  */
>>>>>>>>
>>>>>>>> Shouldn't we leave behind a comment explaining why there's a hole between 15 and 25?
>>>>>>>
>>>>>>> I pondered about this a bit more, and I think we should close the gap and bring CPSR down to
>>>>>>> 16, its "natural" position. It is what linux uses for user_regs as well, in gdb/arch/arm-linux.h:
>>>>>>>
>>>>>>> /* The index to access CSPR in user_regs defined in GLIBC.  */
>>>>>>> #define ARM_CPSR_GREGNUM 16
>>>>>>>
>>>>>>>>
>>>>>>>> IIRC the numbers can't be changed since we need to handle the case when the target
>>>>>>>> doesn't send an xml tdesc, so it'd be good to help future readers understand why
>>>>>>>> there's a hole.
>>>>>>>
>>>>>>> That's correct. Though a 32-bit Arm target that doesn't support XML descriptions these days is not very
>>>>>>> common. I haven't seen one in a while.
>>>>>>>
>>>>>>> I'm willing to declare old 32-bit Arm targets that don't send XML target descriptions back as unsupported.
>>>>>>>
>>>>>>> To that effect, I suppose we should add a note to make it more explicit.
>>>>>>>
>>>>>>> More below.
>>>>>>
>>>>>> FWIW, the GDB stub in FreeBSD's kernel does not use XML target descriptions
>>>>>> for any architectures, but it also only tends to do GPRs and not any floating
>>>>>> point.  For 32-bit ARM it does not report any register values higher than
>>>>>> number 15 (PC), so it would not be affected by changing this.
>>>>>
>>>>> Does it care about CPSR and/or XPSR? Could you please give it a try to see if the defaults would suit it just fine?
>>>>
>>>> Hmm, I misread and it does care about CPSR for the current thread.  The
>>>> relevant code is here (From https://cgit.freebsd.org/src/tree/sys/arm/arm/gdb_machdep.c):
>>>>
>>>> void *
>>>> gdb_cpu_getreg(int regnum, size_t *regsz)
>>>> {
>>>>
>>>>       *regsz = gdb_cpu_regsz(regnum);
>>>>
>>>>       if (kdb_thread == curthread) {
>>>>           if (regnum < 13)
>>>>               return (&kdb_frame->tf_r0 + regnum);
>>>>           if (regnum == 13)
>>>>               return (&kdb_frame->tf_svc_sp);
>>>>           if (regnum == 14)
>>>>               return (&kdb_frame->tf_svc_lr);
>>>>           if (regnum == 15)
>>>>               return (&kdb_frame->tf_pc);
>>>>           if (regnum == 25)
>>>>               return (&kdb_frame->tf_spsr);
>>>>       }
>>>>
>>>>       switch (regnum) {
>>>>       case 4:  return (&kdb_thrctx->pcb_regs.sf_r4);
>>>>       case 5:  return (&kdb_thrctx->pcb_regs.sf_r5);
>>>>       case 6:  return (&kdb_thrctx->pcb_regs.sf_r6);
>>>>       case 7:  return (&kdb_thrctx->pcb_regs.sf_r7);
>>>>       case 8:  return (&kdb_thrctx->pcb_regs.sf_r8);
>>>>       case 9:  return (&kdb_thrctx->pcb_regs.sf_r9);
>>>>       case 10:  return (&kdb_thrctx->pcb_regs.sf_r10);
>>>>       case 11:  return (&kdb_thrctx->pcb_regs.sf_r11);
>>>>       case 12:  return (&kdb_thrctx->pcb_regs.sf_r12);
>>>>       case 13:  stacktest = kdb_thrctx->pcb_regs.sf_sp + 5 * 4;
>>>>             return (&stacktest);
>>>>       case 15:
>>>>             /*
>>>>              * On context switch, the PC is not put in the PCB, but
>>>>              * we can retrieve it from the stack.
>>>>              */
>>>>             if (kdb_thrctx->pcb_regs.sf_sp > KERNBASE) {
>>>>                 kdb_thrctx->pcb_regs.sf_pc = *(register_t *)
>>>>                     (kdb_thrctx->pcb_regs.sf_sp + 4 * 4);
>>>>                 return (&kdb_thrctx->pcb_regs.sf_pc);
>>>>             }
>>>>       }
>>>>
>>>>       return (NULL);
>>>> }
>>>>
>>>> The 'kdb_thread == curthread' case is when a thread enters the debugger due
>>>> to a crash or breakpoint, etc.  We do return CPSR for that thread, but we do
>>>> not return it for other threads.  It looks like we do also know the FPA register
>>>> size so that we return enough "xx" bytes in the 'g' reply to mark the FP
>>>> registers as unavailable so that we can return the value of CPSR in the 'g'
>>>> reply.
>>>>
>>>>   From https://cgit.freebsd.org/src/tree/sys/arm/include/gdb_machdep.h:
>>>>
>>>> #define    GDB_NREGS    26
>>>> #define    GDB_REG_SP    13
>>>> #define    GDB_REG_LR    14
>>>> #define    GDB_REG_PC    15
>>>>
>>>> static __inline size_t
>>>> gdb_cpu_regsz(int regnum)
>>>> {
>>>>       /*
>>>>        * GDB expects the FPA registers f0-f7, each 96 bits wide, to be placed
>>>>        * in between the PC and CSPR in response to a "g" packet.
>>>>        */
>>>>       return (regnum >= 16 && regnum <= 23 ? 12 : sizeof(int));
>>>> }
>>>>
>>>> NetBSD's kernel seems to have similar knowledge:
>>>>
>>>> http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/arch/arm/include/db_machdep.h?rev=1.28&content-type=text/x-cvsweb-markup&only_with_tag=MAIN
>>>>
>>>> (The kgdb bits near the bottom)
>>>>
>>>> Linux's kernel also seems to maybe hardcode this knowledge as well:
>>>>
>>>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm/kernel/kgdb.c#n21
>>>>
>>>
>>> Yeah, that's what I was worried about. Register discoveries without XML are not great, and more recently debugging stubs have been
>>> exposing more system registers. Having to consider FPA (which was *removed* 10 years ago from GCC, but fell in disuse before then) is not
>>> acceptable at this point.
>>>
>>> If those debugging stubs want to skip XML, I think it would be reasonable for them to at least update the expected 'g' packet to contain just
>>> the basic registers, with CPSR as 16.
>>>
>>> That might need some coordination. I can coordinate this from the Linux Kernel's side, but I never dealt with the BSD kernels.
>>
>> I can certainly deal with updating FreeBSD.  I can try to find someone over in NetBSD
>> land.  Honestly, the simplest approach might be to start exporting XML from the
>> kernel.  However, an even simpler workaround for now might be having a knob that
>> can be set for older debugger binaries that still places CPSR at the old register
>> number vs the newer one.
>>
> 
> IMO, exporting an XML description of the register set(s) available is certainly the right way forward.  In fact, I'd strongly suggest we leave the existing packet formats as-is for now and add support for XML to the relevant kernels.  At some point then gdb (and LLDB) can simply stop working with older kernel versions that don't do it the 'right' way.
> 
> R.

FTR, I started a thread here for the Linux kernel: https://lore.kernel.org/linux-arm-kernel/5b0d81f2-00ed-cf3c-8869-420326595e0a@arm.com/T/#u

I did a bit of background research on the register layout, and it seems to have been put together around late 1992, including the fp registers.

When GDB switched to XML descriptions, the same format was kept. Eventually other debugging stubs copied whatever GDB was doing, even if the fp
registers were no longer being used.

The Linux kgdb states this in one comment:

/*
  * From Kevin Hilman:
  *
  * gdb is expecting the following registers layout.
  *
  * r0-r15: 1 long word each
  * f0-f7:  unused, 3 long words each !!
  * fps:    unused, 1 long word
  * cpsr:   1 long word
  *
  * Even though f0-f7 and fps are not used, they need to be
  * present in the registers sent for correct processing in
  * the host-side gdb.
  *
  * In particular, it is crucial that CPSR is in the right place,
  * otherwise gdb will not be able to correctly interpret stepping over
  * conditional branches.
  */

Keeping the compatibility code for now, maybe with a nice warning stating this is deprecated, is the easiest IMO. It should give kgdb's
some time to adapt.

The switch would allow us to remove the g guess code now, but it would be slightly more annoying for people to use it if they want the
non-default case. But still a possibility.
  
Pedro Alves Oct. 10, 2022, 2:56 p.m. UTC | #15
Hi,

On 2022-10-04 9:43 a.m., Luis Machado wrote:
> 
> 
>>> -   The packet format which
>>> -   includes FPA registers should be considered deprecated for
>>> -   M-profile targets.  */
>>> -
>>> -static void
>>> -arm_register_g_packet_guesses (struct gdbarch *gdbarch)
>>> -{
>>> -  arm_gdbarch_tdep *tdep = gdbarch_tdep<arm_gdbarch_tdep> (gdbarch);
>>> -
>>> -  if (tdep->is_m)
>>> -    {
>>> -      const target_desc *tdesc;
>>> -
>>> -      /* If we know from the executable this is an M-profile target,
>>> -     cater for remote targets whose register set layout is the
>>> -     same as the FPA layout.  */
>>> -      tdesc = arm_read_mprofile_description (ARM_M_TYPE_WITH_FPA);
>>> -      register_remote_g_packet_guess (gdbarch,
>>> -                      ARM_CORE_REGS_SIZE + ARM_FP_REGS_SIZE,
>>> -                      tdesc);
>>> -
>>> -      /* The regular M-profile layout.  */
>>> -      tdesc = arm_read_mprofile_description (ARM_M_TYPE_M_PROFILE);
>>> -      register_remote_g_packet_guess (gdbarch, ARM_CORE_REGS_SIZE,
>>> -                      tdesc);
>>> -
>>> -      /* M-profile plus M4F VFP.  */
>>> -      tdesc = arm_read_mprofile_description (ARM_M_TYPE_VFP_D16);
>>> -      register_remote_g_packet_guess (gdbarch,
>>> -                      ARM_CORE_REGS_SIZE + ARM_VFP2_REGS_SIZE,
>>> -                      tdesc);
>>> -      /* M-profile plus MVE.  */
>>> -      tdesc = arm_read_mprofile_description (ARM_M_TYPE_MVE);
>>> -      register_remote_g_packet_guess (gdbarch, ARM_CORE_REGS_SIZE
>>> -                      + ARM_VFP2_REGS_SIZE
>>> -                      + ARM_INT_REGISTER_SIZE, tdesc);
>>> -
>>> -      /* M-profile system (stack pointers).  */
>>> -      tdesc = arm_read_mprofile_description (ARM_M_TYPE_SYSTEM);
>>> -      register_remote_g_packet_guess (gdbarch, 2 * ARM_INT_REGISTER_SIZE, tdesc);
>>
>> And what about all these other non-FPA guesses?  Do you really mean to drop them?
>>
> 
> More recently we've added two new guesses for MVE and M-profile system registers, but it doesn't
> make sense to do so, as these features are advertised as XML already. 

What was the justification for adding them back then, then?

> So in my opinion, we should
> drop the g packet guesses completely and rely solely on XML descriptions.

Then I think that it should be proposed in a separate patch, as it has nothing to
do with dropping FPA support.

Off hand, I don't really see what you win much removing the guesses.  The code that it allows
removing isn't something that would block any redesign or big cleanup in gdb, as gdb needs to know
how to create built-in tdescs for core files, anyhow (even if not these particular tdescs),
and the tdesc generation code is even shared with gdbserver.
  
Pedro Alves Oct. 10, 2022, 2:58 p.m. UTC | #16
On 2022-10-05 9:26 a.m., Luis Machado wrote:

> Yeah, that's what I was worried about. Register discoveries without XML are not great, and more recently debugging stubs have been
> exposing more system registers. Having to consider FPA (which was *removed* 10 years ago from GCC, but fell in disuse before then) is not
> acceptable at this point.
> 
> If those debugging stubs want to skip XML, I think it would be reasonable for them to at least update the expected 'g' packet to contain just
> the basic registers, with CPSR as 16.
> 
> That might need some coordination. I can coordinate this from the Linux Kernel's side, but I never dealt with the BSD kernels.

I'm not seeing much point in this:

#1 - If the remote side supplies XML, then the register number doesn't really matter, GDB auto-maps the numbers.

#2 - If the remote side doesn't supply XML, then you're just setting up for a world of coordination pain for no benefit.

In GDB, to keep things working, we just have to keep the FPA register number hole in place.  That's hardly causing
any maintenance burden, IMO.  We just have to have comments in place explaining why we have them.
  
Luis Machado Oct. 13, 2022, 7:18 a.m. UTC | #17
On 10/10/22 15:56, Pedro Alves wrote:
> Hi,
> 
> On 2022-10-04 9:43 a.m., Luis Machado wrote:
>>
>>
>>>> -???The?packet?format?which
>>>> -???includes?FPA?registers?should?be?considered?deprecated?for
>>>> -???M-profile?targets.??*/
>>>> -
>>>> -static?void
>>>> -arm_register_g_packet_guesses?(struct?gdbarch?*gdbarch)
>>>> -{
>>>> -??arm_gdbarch_tdep?*tdep?=?gdbarch_tdep<arm_gdbarch_tdep>?(gdbarch);
>>>> -
>>>> -??if?(tdep->is_m)
>>>> -????{
>>>> -??????const?target_desc?*tdesc;
>>>> -
>>>> -??????/*?If?we?know?from?the?executable?this?is?an?M-profile?target,
>>>> -?????cater?for?remote?targets?whose?register?set?layout?is?the
>>>> -?????same?as?the?FPA?layout.??*/
>>>> -??????tdesc?=?arm_read_mprofile_description?(ARM_M_TYPE_WITH_FPA);
>>>> -??????register_remote_g_packet_guess?(gdbarch,
>>>> -??????????????????????ARM_CORE_REGS_SIZE?+?ARM_FP_REGS_SIZE,
>>>> -??????????????????????tdesc);
>>>> -
>>>> -??????/*?The?regular?M-profile?layout.??*/
>>>> -??????tdesc?=?arm_read_mprofile_description?(ARM_M_TYPE_M_PROFILE);
>>>> -??????register_remote_g_packet_guess?(gdbarch,?ARM_CORE_REGS_SIZE,
>>>> -??????????????????????tdesc);
>>>> -
>>>> -??????/*?M-profile?plus?M4F?VFP.??*/
>>>> -??????tdesc?=?arm_read_mprofile_description?(ARM_M_TYPE_VFP_D16);
>>>> -??????register_remote_g_packet_guess?(gdbarch,
>>>> -??????????????????????ARM_CORE_REGS_SIZE?+?ARM_VFP2_REGS_SIZE,
>>>> -??????????????????????tdesc);
>>>> -??????/*?M-profile?plus?MVE.??*/
>>>> -??????tdesc?=?arm_read_mprofile_description?(ARM_M_TYPE_MVE);
>>>> -??????register_remote_g_packet_guess?(gdbarch,?ARM_CORE_REGS_SIZE
>>>> -??????????????????????+?ARM_VFP2_REGS_SIZE
>>>> -??????????????????????+?ARM_INT_REGISTER_SIZE,?tdesc);
>>>> -
>>>> -??????/*?M-profile?system?(stack?pointers).??*/
>>>> -??????tdesc?=?arm_read_mprofile_description?(ARM_M_TYPE_SYSTEM);
>>>> -??????register_remote_g_packet_guess?(gdbarch,?2?*?ARM_INT_REGISTER_SIZE,?tdesc);
>>>
>>> And?what?about?all?these?other?non-FPA?guesses???Do?you?really?mean?to?drop?them?
>>>
>>
>> More?recently?we've?added?two?new?guesses?for?MVE?and?M-profile?system?registers,?but?it?doesn't
>> make?sense?to?do?so,?as?these?features?are?advertised?as?XML?already.
> 
> What was the justification for adding them back then, then?
> 

It was meant to support other register sets under a situation where no XML is sent back. Though valid, my feeling is that
it was done mostly as copy/pasting what was already being done for the GPR's/FPA. The documentation isn't exactly clear
on whether one should do it or not. Only a few targets use these guesses (Arm, Mips and Microblaze).

I should probably add something to that effect in the future.

>> So?in?my?opinion,?we?should
>> drop?the?g?packet?guesses?completely?and?rely?solely?on?XML?descriptions.
> 
> Then I think that it should be proposed in a separate patch, as it has nothing to
> do with dropping FPA support.

Makes sense. I don't think we should be adding any other guesses for newer features/regsets.
> 
> Off hand, I don't really see what you win much removing the guesses.  The code that it allows
> removing isn't something that would block any redesign or big cleanup in gdb, as gdb needs to know
> how to create built-in tdescs for core files, anyhow (even if not these particular tdescs),
> and the tdesc generation code is even shared with gdbserver.

Well, based on recent discussions, we're not going to drop this, as Linux/BSD kgdb is still relying on it.

Removing the guesses doesn't buy us much on its own, but there is opportunity to get targets to move
to XML descriptions, which is something easier to work with, more flexible and less error-prone. So it looks
like a step in the right direction.
  
Luis Machado Oct. 13, 2022, 7:23 a.m. UTC | #18
On 10/10/22 15:58, Pedro Alves wrote:
> On 2022-10-05 9:26 a.m., Luis Machado wrote:
> 
>> Yeah, that's what I was worried about. Register discoveries without XML are not great, and more recently debugging stubs have been
>> exposing more system registers. Having to consider FPA (which was *removed* 10 years ago from GCC, but fell in disuse before then) is not
>> acceptable at this point.
>>
>> If those debugging stubs want to skip XML, I think it would be reasonable for them to at least update the expected 'g' packet to contain just
>> the basic registers, with CPSR as 16.
>>
>> That might need some coordination. I can coordinate this from the Linux Kernel's side, but I never dealt with the BSD kernels.
> 
> I'm not seeing much point in this:
> 
> #1 - If the remote side supplies XML, then the register number doesn't really matter, GDB auto-maps the numbers.
> 
> #2 - If the remote side doesn't supply XML, then you're just setting up for a world of coordination pain for no benefit.
> 
> In GDB, to keep things working, we just have to keep the FPA register number hole in place.  That's hardly causing
> any maintenance burden, IMO.  We just have to have comments in place explaining why we have them.

Based on a recent thread with the Arm Linux Kernel maintainer, he finds it reasonable to make kgdb
return XML data and to keep a compatibility layer (the g guesses) going for a reasonable amount of
time, after which we can retire the guesses and drop the code.

It is not clear when we'll drop the compatibility layer, but at least we can get some traction towards
making targets use XML and maybe add some deprecation warning to the g packet guesses. If we keep the code as-is,
there is no incentive to update targets using old mechanisms.

GDB talks about FPA as if it were something that existed not long ago, while in fact it was deprecated even before GDB
started using XML descriptions. But the registers were kept that way and GDB was never updated (supposedly because it needed
to be compatible with some other tool at the time), leading to other tools copying what GDB was exposing, even though they didn't
support FPA at all.

One such example is the Linux Kernel, which added these registers because GDB required them.

So in this case GDB has the potential to influence other tools, and we should strive to keep things clean and updated as much as
possible. This is an attempt at that.
  
Pedro Alves Oct. 13, 2022, 8:29 a.m. UTC | #19
On 2022-10-13 8:23 a.m., Luis Machado wrote:
> On 10/10/22 15:58, Pedro Alves wrote:
>> On 2022-10-05 9:26 a.m., Luis Machado wrote:
>>
>>> Yeah, that's what I was worried about. Register discoveries without XML are not great, and more recently debugging stubs have been
>>> exposing more system registers. Having to consider FPA (which was *removed* 10 years ago from GCC, but fell in disuse before then) is not
>>> acceptable at this point.
>>>
>>> If those debugging stubs want to skip XML, I think it would be reasonable for them to at least update the expected 'g' packet to contain just
>>> the basic registers, with CPSR as 16.
>>>
>>> That might need some coordination. I can coordinate this from the Linux Kernel's side, but I never dealt with the BSD kernels.
>>
>> I'm not seeing much point in this:
>>
>> #1 - If the remote side supplies XML, then the register number doesn't really matter, GDB auto-maps the numbers.
>>
>> #2 - If the remote side doesn't supply XML, then you're just setting up for a world of coordination pain for no benefit.
>>
>> In GDB, to keep things working, we just have to keep the FPA register number hole in place.? That's hardly causing
>> any maintenance burden, IMO.? We just have to have comments in place explaining why we have them.
> 
> Based on a recent thread with the Arm Linux Kernel maintainer, he finds it reasonable to make kgdb
> return XML data and to keep a compatibility layer (the g guesses) going for a reasonable amount of
> time, after which we can retire the guesses and drop the code.

Good.  Of course, the Linux kernel isn't going to be the only remote server or stub out there.

> 
> It is not clear when we'll drop the compatibility layer, but at least we can get some traction towards
> making targets use XML and maybe add some deprecation warning to the g packet guesses. If we keep the code as-is,
> there is no incentive to update targets using old mechanisms.

Deprecation warnings makes sense to me.  Much more user-friendly than flat out removing the guesses without a warning
period, and/or changing the non-XML g/G packet layout.

The (unwritten) policy for as long as I'm worked on GDB has always been that you don't change the hardcoded g/G packet
layout, ever.  You can only grow it.  Or use XML.  

While we can push new versions of tools to switch to XML, the older versions will still be out there.  Stubs can
be embedded in devices that aren't going to update easily or at all.  Is it a good idea to to cause them pain?  IMHO, no.

Note, for the FPA removal, you should send an email to gdb@ as well, see here for the obsoleting procedure:

  https://sourceware.org/gdb/wiki/Internals%20Obsoleting-code

> 
> GDB talks about FPA as if it were something that existed not long ago, while in fact it was deprecated even before GDB
> started using XML descriptions. But the registers were kept that way and GDB was never updated (supposedly because it needed
> to be compatible with some other tool at the time), leading to other tools copying what GDB was exposing, even though they didn't
> support FPA at all.

The question is only about the hole in the g/G registers layout. where the FPA registers used to be, and the register numbers
for registers that follow.  Nobody is arguing for keeping the FPA support at all, I think.

Just like we have in gdb/features/arm/arm-core.xml:

....
  <reg name="pc" bitsize="32" type="code_ptr"/>

  <!-- The CPSR is register 25, rather than register 16, because
       the FPA registers historically were placed between the PC
       and the CPSR in the "g" packet.  -->
  <reg name="cpsr" bitsize="32" regnum="25"/>
</feature>


That's all we'd need to do in gdb itself too.  Hardly a maintenance burden, IMO, and hardly worth it to break backwards
compatibility with random embedded stubs that are hard or impossible to update, IMO.

> 
> One such example is the Linux Kernel, which added these registers because GDB required them.
> 
> So in this case GDB has the potential to influence other tools, and we should strive to keep things clean and updated as much as
> possible. This is an attempt at that.
> 

Sure.
  
Pedro Alves Oct. 13, 2022, 8:44 a.m. UTC | #20
On 2022-10-13 8:18 a.m., Luis Machado wrote:
> On 10/10/22 15:56, Pedro Alves wrote:

>>> More?recently?we've?added?two?new?guesses?for?MVE?and?M-profile?system?registers,?but?it?doesn't
>>> make?sense?to?do?so,?as?these?features?are?advertised?as?XML?already.
>>
>> What was the justification for adding them back then, then?
>>
> 
> It was meant to support other register sets under a situation where no XML is sent back. 

Well, that's the reason for all the guesses existing.  The question was more about -- why were _those_
particular guesses needed / added?  Maybe because such stubs already existed in the wild, and
people were using some downstream patched version of GDB to work with them?

> Though valid, my feeling is that
> it was done mostly as copy/pasting what was already being done for the GPR's/FPA. The documentation isn't exactly clear
> on whether one should do it or not. Only a few targets use these guesses (Arm, Mips and Microblaze).

It's strictly a backwards compatibility feature.  It's explained in the comment:

/* For backward-compatibility we allow two 'g' packet lengths with
   the remote protocol depending on whether FPA registers are
   supplied.  M-profile targets do not have FPA registers, but some
   stubs already exist in the wild which use a 'g' packet which
   supplies them albeit with dummy values.  The packet format which
   includes FPA registers should be considered deprecated for
   M-profile targets.  */

static void
arm_register_g_packet_guesses (struct gdbarch *gdbarch)
{

Is there something that could be improved in that comment to make it clearer?

> Removing the guesses doesn't buy us much on its own, but there is opportunity to get targets to move
> to XML descriptions, which is something easier to work with, more flexible and less error-prone. So it looks
> like a step in the right direction.

The thing is that the old/existing stubs that don't send an XML don't need the flexibility.  They just need
to continue working as they do today.  Removing the guesses and changing the default g/G packet layout
causes pain to _users_ foremost.  IMO, removing backwards compatibility just for the sake of it doesn't
really help anyone.

For new registers/features, XML is how to get the flexibility.  So I think the angle should be that
we, as maintainers, should not accept adding support for more/new registers without XML tdescs.
  
Luis Machado Oct. 13, 2022, 9:15 a.m. UTC | #21
On 10/13/22 09:44, Pedro Alves wrote:
> On 2022-10-13 8:18 a.m., Luis Machado wrote:
>> On 10/10/22 15:56, Pedro Alves wrote:
> 
>>>> More?recently?we've?added?two?new?guesses?for?MVE?and?M-profile?system?registers,?but?it?doesn't
>>>> make?sense?to?do?so,?as?these?features?are?advertised?as?XML?already.
>>>
>>> What was the justification for adding them back then, then?
>>>
>>
>> It was meant to support other register sets under a situation where no XML is sent back.
> 
> Well, that's the reason for all the guesses existing.  The question was more about -- why were _those_
> particular guesses needed / added?  Maybe because such stubs already existed in the wild, and
> people were using some downstream patched version of GDB to work with them?
> 

They weren't needed at all. mve is reported through XML by gdbserver and qemu. The system registers are only currently
supported by STLink, and that also uses XML.

>> Though valid, my feeling is that
>> it was done mostly as copy/pasting what was already being done for the GPR's/FPA. The documentation isn't exactly clear
>> on whether one should do it or not. Only a few targets use these guesses (Arm, Mips and Microblaze).
> 
> It's strictly a backwards compatibility feature.  It's explained in the comment:
> 

Right, but since this is an old port and the background is fairly convoluted, it might be easy to miss if you
don't know some of its history. I consider the mve/system bits of the guesses dead code. Though we could argue now someone may come up with
a stub that uses mve and the system registers without XML, and that we will need to support that going forward.

I don't think that's realistic though. I hope you'll agree.

> /* For backward-compatibility we allow two 'g' packet lengths with
>     the remote protocol depending on whether FPA registers are
>     supplied.  M-profile targets do not have FPA registers, but some
>     stubs already exist in the wild which use a 'g' packet which
>     supplies them albeit with dummy values.  The packet format which
>     includes FPA registers should be considered deprecated for
>     M-profile targets.  */
> 
> static void
> arm_register_g_packet_guesses (struct gdbarch *gdbarch)
> {
> 
> Is there something that could be improved in that comment to make it clearer?

Yes, we should put a big warning stating we should no longer update this code, until it can be dropped without
upsetting other software.

> 
>> Removing the guesses doesn't buy us much on its own, but there is opportunity to get targets to move
>> to XML descriptions, which is something easier to work with, more flexible and less error-prone. So it looks
>> like a step in the right direction.
> 
> The thing is that the old/existing stubs that don't send an XML don't need the flexibility.  They just need
> to continue working as they do today.  Removing the guesses and changing the default g/G packet layout
> causes pain to _users_ foremost.  IMO, removing backwards compatibility just for the sake of it doesn't
> really help anyone.

Although that's true, it is also true that a recent-enough GDB could be used to debug those very old targets after
the compatibility layer is dropped in the future.

> 
> For new registers/features, XML is how to get the flexibility.  So I think the angle should be that
> we, as maintainers, should not accept adding support for more/new registers without XML tdescs.
Yes, and that's already the case.
  
Luis Machado Oct. 13, 2022, 9:40 a.m. UTC | #22
On 10/13/22 09:29, Pedro Alves wrote:
> 
> 
> On 2022-10-13 8:23 a.m., Luis Machado wrote:
>> On 10/10/22 15:58, Pedro Alves wrote:
>>> On 2022-10-05 9:26 a.m., Luis Machado wrote:
>>>
>>>> Yeah, that's what I was worried about. Register discoveries without XML are not great, and more recently debugging stubs have been
>>>> exposing more system registers. Having to consider FPA (which was *removed* 10 years ago from GCC, but fell in disuse before then) is not
>>>> acceptable at this point.
>>>>
>>>> If those debugging stubs want to skip XML, I think it would be reasonable for them to at least update the expected 'g' packet to contain just
>>>> the basic registers, with CPSR as 16.
>>>>
>>>> That might need some coordination. I can coordinate this from the Linux Kernel's side, but I never dealt with the BSD kernels.
>>>
>>> I'm not seeing much point in this:
>>>
>>> #1 - If the remote side supplies XML, then the register number doesn't really matter, GDB auto-maps the numbers.
>>>
>>> #2 - If the remote side doesn't supply XML, then you're just setting up for a world of coordination pain for no benefit.
>>>
>>> In GDB, to keep things working, we just have to keep the FPA register number hole in place.? That's hardly causing
>>> any maintenance burden, IMO.? We just have to have comments in place explaining why we have them.
>>
>> Based on a recent thread with the Arm Linux Kernel maintainer, he finds it reasonable to make kgdb
>> return XML data and to keep a compatibility layer (the g guesses) going for a reasonable amount of
>> time, after which we can retire the guesses and drop the code.
> 
> Good.  Of course, the Linux kernel isn't going to be the only remote server or stub out there.
> 

No, but most of the probes have been updated to use XML over the years. Yes, there is an unknown list of old
probes and hardware out there potentially not using XML. I haven't seen any such issues reported against the
GDB bugzilla though, which is good either way.

>>
>> It is not clear when we'll drop the compatibility layer, but at least we can get some traction towards
>> making targets use XML and maybe add some deprecation warning to the g packet guesses. If we keep the code as-is,
>> there is no incentive to update targets using old mechanisms.
> 
> Deprecation warnings makes sense to me.  Much more user-friendly than flat out removing the guesses without a warning
> period, and/or changing the non-XML g/G packet layout.
> 
> The (unwritten) policy for as long as I'm worked on GDB has always been that you don't change the hardcoded g/G packet
> layout, ever.  You can only grow it.  Or use XML.

Sure. But no longer required for XML-based data.

> 
> While we can push new versions of tools to switch to XML, the older versions will still be out there.  Stubs can
> be embedded in devices that aren't going to update easily or at all.  Is it a good idea to to cause them pain?  IMHO, no.
> 
> Note, for the FPA removal, you should send an email to gdb@ as well, see here for the obsoleting procedure:
> 
>    https://sourceware.org/gdb/wiki/Internals%20Obsoleting-code
> 

Do you want that procedure followed completely, including the week waiting? I also seem to recall a different policy, where we
deprecate something for a particular release and then remove on the next one.

In any case, I've added a NEWS entry. I hardly think anybody would care about FPA. It might even be a bit nostalgic.

>>
>> GDB talks about FPA as if it were something that existed not long ago, while in fact it was deprecated even before GDB
>> started using XML descriptions. But the registers were kept that way and GDB was never updated (supposedly because it needed
>> to be compatible with some other tool at the time), leading to other tools copying what GDB was exposing, even though they didn't
>> support FPA at all.
> 
> The question is only about the hole in the g/G registers layout. where the FPA registers used to be, and the register numbers
> for registers that follow.  Nobody is arguing for keeping the FPA support at all, I think.
> 
> Just like we have in gdb/features/arm/arm-core.xml:
> 
> ....
>    <reg name="pc" bitsize="32" type="code_ptr"/>
> 
>    <!-- The CPSR is register 25, rather than register 16, because
>         the FPA registers historically were placed between the PC
>         and the CPSR in the "g" packet.  -->
>    <reg name="cpsr" bitsize="32" regnum="25"/>
> </feature>
> 

Right. That hardcoding in the XML is also not necessary anymore, and could be removed to prevent any further confusion for whoever
is reading things.

We could handle it more gracefully internally, as opposed to propagating incorrect assumptions to other tools.

> 
> That's all we'd need to do in gdb itself too.  Hardly a maintenance burden, IMO, and hardly worth it to break backwards
> compatibility with random embedded stubs that are hard or impossible to update, IMO.
> 

Those are little maintenance burdens that are not bad in isolation, but they do add up for the port maintenance overall.



>>
>> One such example is the Linux Kernel, which added these registers because GDB required them.
>>
>> So in this case GDB has the potential to influence other tools, and we should strive to keep things clean and updated as much as
>> possible. This is an attempt at that.
>>
> 
> Sure
  
Luis Machado Oct. 25, 2022, 1:54 p.m. UTC | #23
On 10/13/22 10:40, Luis Machado via Gdb-patches wrote:
> On 10/13/22 09:29, Pedro Alves wrote:
>>
>>
>> On 2022-10-13 8:23 a.m., Luis Machado wrote:
>>> On 10/10/22 15:58, Pedro Alves wrote:
>>>> On 2022-10-05 9:26 a.m., Luis Machado wrote:
>>>>
>>>>> Yeah, that's what I was worried about. Register discoveries without XML are not great, and more recently debugging stubs have been
>>>>> exposing more system registers. Having to consider FPA (which was *removed* 10 years ago from GCC, but fell in disuse before then) is not
>>>>> acceptable at this point.
>>>>>
>>>>> If those debugging stubs want to skip XML, I think it would be reasonable for them to at least update the expected 'g' packet to contain just
>>>>> the basic registers, with CPSR as 16.
>>>>>
>>>>> That might need some coordination. I can coordinate this from the Linux Kernel's side, but I never dealt with the BSD kernels.
>>>>
>>>> I'm not seeing much point in this:
>>>>
>>>> #1 - If the remote side supplies XML, then the register number doesn't really matter, GDB auto-maps the numbers.
>>>>
>>>> #2 - If the remote side doesn't supply XML, then you're just setting up for a world of coordination pain for no benefit.
>>>>
>>>> In GDB, to keep things working, we just have to keep the FPA register number hole in place.  That's hardly causing
>>>> any maintenance burden, IMO.  We just have to have comments in place explaining why we have them.
>>>
>>> Based on a recent thread with the Arm Linux Kernel maintainer, he finds it reasonable to make kgdb
>>> return XML data and to keep a compatibility layer (the g guesses) going for a reasonable amount of
>>> time, after which we can retire the guesses and drop the code.
>>
>> Good.  Of course, the Linux kernel isn't going to be the only remote server or stub out there.
>>
> 
> No, but most of the probes have been updated to use XML over the years. Yes, there is an unknown list of old
> probes and hardware out there potentially not using XML. I haven't seen any such issues reported against the
> GDB bugzilla though, which is good either way.
> 
>>>
>>> It is not clear when we'll drop the compatibility layer, but at least we can get some traction towards
>>> making targets use XML and maybe add some deprecation warning to the g packet guesses. If we keep the code as-is,
>>> there is no incentive to update targets using old mechanisms.
>>
>> Deprecation warnings makes sense to me.  Much more user-friendly than flat out removing the guesses without a warning
>> period, and/or changing the non-XML g/G packet layout.
>>
>> The (unwritten) policy for as long as I'm worked on GDB has always been that you don't change the hardcoded g/G packet
>> layout, ever.  You can only grow it.  Or use XML.
> 
> Sure. But no longer required for XML-based data.
> 
>>
>> While we can push new versions of tools to switch to XML, the older versions will still be out there.  Stubs can
>> be embedded in devices that aren't going to update easily or at all.  Is it a good idea to to cause them pain?  IMHO, no.
>>
>> Note, for the FPA removal, you should send an email to gdb@ as well, see here for the obsoleting procedure:
>>
>>    https://sourceware.org/gdb/wiki/Internals%20Obsoleting-code
>>
> 
> Do you want that procedure followed completely, including the week waiting? I also seem to recall a different policy, where we
> deprecate something for a particular release and then remove on the next one.

Before I refresh this patch, did you have thoughts on the above?
  
Simon Marchi Nov. 14, 2022, 2:30 p.m. UTC | #24
> Do you want that procedure followed completely, including the week waiting? I also seem to recall a different policy, where we
> deprecate something for a particular release and then remove on the next one.

Given how obsolete FPA is, I would be fine with removing it in this
release.  It would be good practice to send an announcement on
gdb-announce, like the wiki says.  We don't do it often, but if we did
it often, perhaps we'd be less scared of doing it, it would become more
a routine thing.

I agree with Pedro that this patch should ideally not change the
register layout for when not using XML.  However, it's also fine to have
a plan to stop supporting non-XML-using targets eventually, if that's
what we want.

Simon
  

Patch

diff --git a/gdb/NEWS b/gdb/NEWS
index 555ef2ddf77..fcd7b686e02 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -3,6 +3,10 @@ 
 
 *** Changes since GDB 12
 
+* Removed support for the 32-bit Arm FPA floating point format.  FPA is an
+  old floating point format that is no longer supported in GCC since at least
+  2012.
+
 * GDB now supports dumping memory tag data for AArch64 MTE.  It also supports
   reading memory tag data for AArch64 MTE from core files generated by
   the gcore command or the Linux kernel.
diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c
index eda79ec6d35..4d36cd47567 100644
--- a/gdb/aarch64-linux-nat.c
+++ b/gdb/aarch64-linux-nat.c
@@ -551,7 +551,7 @@  aarch32_fetch_registers (struct regcache *regcache, int regno)
       if (tdep->vfp_register_count > 0)
 	fetch_fpregs_from_thread (regcache);
     }
-  else if (regno < ARM_F0_REGNUM || regno == ARM_PS_REGNUM)
+  else if (regno <= ARM_PC_REGNUM || regno == ARM_PS_REGNUM)
     fetch_gregs_from_thread (regcache);
   else if (tdep->vfp_register_count > 0
 	   && regno >= ARM_D0_REGNUM
@@ -627,7 +627,7 @@  aarch32_store_registers (struct regcache *regcache, int regno)
       if (tdep->vfp_register_count > 0)
 	store_fpregs_to_thread (regcache);
     }
-  else if (regno < ARM_F0_REGNUM || regno == ARM_PS_REGNUM)
+  else if (regno <= ARM_PC_REGNUM || regno == ARM_PS_REGNUM)
     store_gregs_to_thread (regcache);
   else if (tdep->vfp_register_count > 0
 	   && regno >= ARM_D0_REGNUM
diff --git a/gdb/arch/arm.c b/gdb/arch/arm.c
index 14f0a7a7f6c..9771a60f30f 100644
--- a/gdb/arch/arm.c
+++ b/gdb/arch/arm.c
@@ -27,7 +27,6 @@ 
 #include "../features/arm/arm-vfpv3.c"
 #include "../features/arm/xscale-iwmmxt.c"
 #include "../features/arm/arm-m-profile.c"
-#include "../features/arm/arm-m-profile-with-fpa.c"
 #include "../features/arm/arm-m-profile-mve.c"
 #include "../features/arm/arm-m-system.c"
 
@@ -441,10 +440,6 @@  arm_create_mprofile_target_description (arm_m_profile_type m_type)
       regnum = create_feature_arm_arm_vfpv2 (tdesc, regnum);
       break;
 
-    case ARM_M_TYPE_WITH_FPA:
-      regnum = create_feature_arm_arm_m_profile_with_fpa (tdesc, regnum);
-      break;
-
     case ARM_M_TYPE_MVE:
       regnum = create_feature_arm_arm_m_profile (tdesc, regnum);
       regnum = create_feature_arm_arm_vfpv2 (tdesc, regnum);
diff --git a/gdb/arch/arm.h b/gdb/arch/arm.h
index 36757493406..74a6ba93bc7 100644
--- a/gdb/arch/arm.h
+++ b/gdb/arch/arm.h
@@ -44,11 +44,6 @@  enum gdb_regnum {
   ARM_SP_REGNUM = 13,		/* Contains address of top of stack */
   ARM_LR_REGNUM = 14,		/* address to return to from a function call */
   ARM_PC_REGNUM = 15,		/* Contains program counter */
-  /* F0..F7 are the fp registers for the (obsolete) FPA architecture.  */
-  ARM_F0_REGNUM = 16,		/* first floating point register */
-  ARM_F3_REGNUM = 19,		/* last floating point argument register */
-  ARM_F7_REGNUM = 23, 		/* last floating point register */
-  ARM_FPS_REGNUM = 24,		/* floating point status register */
   ARM_PS_REGNUM = 25,		/* Contains processor status */
   ARM_WR0_REGNUM,		/* WMMX data registers.  */
   ARM_WR15_REGNUM = ARM_WR0_REGNUM + 15,
@@ -67,7 +62,6 @@  enum gdb_regnum {
   ARM_FP_REGNUM = 11,		/* Frame register in ARM code, if used.  */
   THUMB_FP_REGNUM = 7,		/* Frame register in Thumb code, if used.  */
   ARM_LAST_ARG_REGNUM = ARM_A4_REGNUM,
-  ARM_LAST_FP_ARG_REGNUM = ARM_F3_REGNUM
 };
 
 /* Register count constants.  */
@@ -103,7 +97,6 @@  enum arm_fp_type {
 enum arm_m_profile_type {
    ARM_M_TYPE_M_PROFILE,
    ARM_M_TYPE_VFP_D16,
-   ARM_M_TYPE_WITH_FPA,
    ARM_M_TYPE_MVE,
    ARM_M_TYPE_SYSTEM,
    ARM_M_TYPE_INVALID
@@ -157,8 +150,6 @@  enum system_register_address : CORE_ADDR
 
 /* r0-r12,sp,lr,pc,cpsr.  */
 #define ARM_CORE_REGS_SIZE (17 * ARM_INT_REGISTER_SIZE)
-/* f0-f8,fps.  */
-#define ARM_FP_REGS_SIZE (8 * ARM_FP_REGISTER_SIZE + ARM_INT_REGISTER_SIZE)
 /* d0-d15,fpscr.  */
 #define ARM_VFP2_REGS_SIZE (16 * ARM_VFP_REGISTER_SIZE + ARM_INT_REGISTER_SIZE)
 /* d0-d31,fpscr.  */
diff --git a/gdb/arm-bsd-tdep.c b/gdb/arm-bsd-tdep.c
index 13d6e527d58..72421bb26d5 100644
--- a/gdb/arm-bsd-tdep.c
+++ b/gdb/arm-bsd-tdep.c
@@ -29,39 +29,6 @@ 
 /* Sizeof `struct reg' in <machine/reg.h>.  */
 #define ARMBSD_SIZEOF_GREGS	(17 * 4)
 
-/* Sizeof `struct fpreg' in <machine/reg.h.  */
-#define ARMBSD_SIZEOF_FPREGS	((1 + (8 * 3)) * 4)
-
-static int
-armbsd_fpreg_offset (int regnum)
-{
-  if (regnum == ARM_FPS_REGNUM)
-    return 0;
-
-  return 4 + (regnum - ARM_F0_REGNUM) * 12;
-}
-
-/* Supply register REGNUM from the buffer specified by FPREGS and LEN
-   in the floating-point register set REGSET to register cache
-   REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
-
-static void
-armbsd_supply_fpregset (const struct regset *regset,
-			struct regcache *regcache,
-			int regnum, const void *fpregs, size_t len)
-{
-  const gdb_byte *regs = (const gdb_byte *) fpregs;
-  int i;
-
-  gdb_assert (len >= ARMBSD_SIZEOF_FPREGS);
-
-  for (i = ARM_F0_REGNUM; i <= ARM_FPS_REGNUM; i++)
-    {
-      if (regnum == i || regnum == -1)
-	regcache->raw_supply (i, regs + armbsd_fpreg_offset (i));
-    }
-}
-
 /* Supply register REGNUM from the buffer specified by GREGS and LEN
    in the general-purpose register set REGSET to register cache
    REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
@@ -84,13 +51,6 @@  armbsd_supply_gregset (const struct regset *regset,
 
   if (regnum == ARM_PS_REGNUM || regnum == -1)
     regcache->raw_supply (i, regs + 16 * 4);
-
-  if (len >= ARMBSD_SIZEOF_GREGS + ARMBSD_SIZEOF_FPREGS)
-    {
-      regs += ARMBSD_SIZEOF_GREGS;
-      len -= ARMBSD_SIZEOF_GREGS;
-      armbsd_supply_fpregset (regset, regcache, regnum, regs, len);
-    }
 }
 
 /* ARM register sets.  */
@@ -103,12 +63,6 @@  static const struct regset armbsd_gregset =
   REGSET_VARIABLE_SIZE
 };
 
-static const struct regset armbsd_fpregset =
-{
-  NULL,
-  armbsd_supply_fpregset
-};
-
 /* Iterate over supported core file register note sections. */
 
 void
@@ -119,6 +73,4 @@  armbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
 {
   cb (".reg", ARMBSD_SIZEOF_GREGS, ARMBSD_SIZEOF_GREGS, &armbsd_gregset, NULL,
       cb_data);
-  cb (".reg2", ARMBSD_SIZEOF_FPREGS, ARMBSD_SIZEOF_FPREGS, &armbsd_fpregset,
-      NULL, cb_data);
 }
diff --git a/gdb/arm-linux-nat.c b/gdb/arm-linux-nat.c
index 0188c78fe7a..a6a5745fdf9 100644
--- a/gdb/arm-linux-nat.c
+++ b/gdb/arm-linux-nat.c
@@ -109,96 +109,6 @@  class arm_linux_nat_target final : public linux_nat_target
 
 static arm_linux_nat_target the_arm_linux_nat_target;
 
-/* Get the whole floating point state of the process and store it
-   into regcache.  */
-
-static void
-fetch_fpregs (struct regcache *regcache)
-{
-  int ret, regno, tid;
-  gdb_byte fp[ARM_LINUX_SIZEOF_NWFPE];
-
-  /* Get the thread id for the ptrace call.  */
-  tid = regcache->ptid ().lwp ();
-
-  /* Read the floating point state.  */
-  if (have_ptrace_getregset == TRIBOOL_TRUE)
-    {
-      struct iovec iov;
-
-      iov.iov_base = &fp;
-      iov.iov_len = ARM_LINUX_SIZEOF_NWFPE;
-
-      ret = ptrace (PTRACE_GETREGSET, tid, NT_FPREGSET, &iov);
-    }
-  else
-    ret = ptrace (PT_GETFPREGS, tid, 0, fp);
-
-  if (ret < 0)
-    perror_with_name (_("Unable to fetch the floating point registers"));
-
-  /* Fetch fpsr.  */
-  regcache->raw_supply (ARM_FPS_REGNUM, fp + NWFPE_FPSR_OFFSET);
-
-  /* Fetch the floating point registers.  */
-  for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
-    supply_nwfpe_register (regcache, regno, fp);
-}
-
-/* Save the whole floating point state of the process using
-   the contents from regcache.  */
-
-static void
-store_fpregs (const struct regcache *regcache)
-{
-  int ret, regno, tid;
-  gdb_byte fp[ARM_LINUX_SIZEOF_NWFPE];
-
-  /* Get the thread id for the ptrace call.  */
-  tid = regcache->ptid ().lwp ();
-
-  /* Read the floating point state.  */
-  if (have_ptrace_getregset == TRIBOOL_TRUE)
-    {
-      elf_fpregset_t fpregs;
-      struct iovec iov;
-
-      iov.iov_base = &fpregs;
-      iov.iov_len = sizeof (fpregs);
-
-      ret = ptrace (PTRACE_GETREGSET, tid, NT_FPREGSET, &iov);
-    }
-  else
-    ret = ptrace (PT_GETFPREGS, tid, 0, fp);
-
-  if (ret < 0)
-    perror_with_name (_("Unable to fetch the floating point registers"));
-
-  /* Store fpsr.  */
-  if (REG_VALID == regcache->get_register_status (ARM_FPS_REGNUM))
-    regcache->raw_collect (ARM_FPS_REGNUM, fp + NWFPE_FPSR_OFFSET);
-
-  /* Store the floating point registers.  */
-  for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
-    if (REG_VALID == regcache->get_register_status (regno))
-      collect_nwfpe_register (regcache, regno, fp);
-
-  if (have_ptrace_getregset == TRIBOOL_TRUE)
-    {
-      struct iovec iov;
-
-      iov.iov_base = &fp;
-      iov.iov_len = ARM_LINUX_SIZEOF_NWFPE;
-
-      ret = ptrace (PTRACE_SETREGSET, tid, NT_FPREGSET, &iov);
-    }
-  else
-    ret = ptrace (PTRACE_SETFPREGS, tid, 0, fp);
-
-  if (ret < 0)
-    perror_with_name (_("Unable to store floating point registers"));
-}
-
 /* Fetch all general registers of the process and store into
    regcache.  */
 
@@ -422,15 +332,11 @@  arm_linux_nat_target::fetch_registers (struct regcache *regcache, int regno)
 	fetch_wmmx_regs (regcache);
       if (tdep->vfp_register_count > 0)
 	fetch_vfp_regs (regcache);
-      if (tdep->have_fpa_registers)
-	fetch_fpregs (regcache);
     }
   else
     {
-      if (regno < ARM_F0_REGNUM || regno == ARM_PS_REGNUM)
+      if (regno <= ARM_PC_REGNUM || regno == ARM_PS_REGNUM)
 	fetch_regs (regcache);
-      else if (regno >= ARM_F0_REGNUM && regno <= ARM_FPS_REGNUM)
-	fetch_fpregs (regcache);
       else if (tdep->have_wmmx_registers
 	       && regno >= ARM_WR0_REGNUM && regno <= ARM_WCGR7_REGNUM)
 	fetch_wmmx_regs (regcache);
@@ -459,15 +365,11 @@  arm_linux_nat_target::store_registers (struct regcache *regcache, int regno)
 	store_wmmx_regs (regcache);
       if (tdep->vfp_register_count > 0)
 	store_vfp_regs (regcache);
-      if (tdep->have_fpa_registers)
-	store_fpregs (regcache);
     }
   else
     {
-      if (regno < ARM_F0_REGNUM || regno == ARM_PS_REGNUM)
+      if (regno <= ARM_PC_REGNUM || regno == ARM_PS_REGNUM)
 	store_regs (regcache);
-      else if ((regno >= ARM_F0_REGNUM) && (regno <= ARM_FPS_REGNUM))
-	store_fpregs (regcache);
       else if (tdep->have_wmmx_registers
 	       && regno >= ARM_WR0_REGNUM && regno <= ARM_WCGR7_REGNUM)
 	store_wmmx_regs (regcache);
@@ -499,7 +401,7 @@  void
 fill_fpregset (const struct regcache *regcache,
 	       gdb_fpregset_t *fpregsetp, int regno)
 {
-  arm_linux_collect_nwfpe (NULL, regcache, regno, fpregsetp, 0);
+  /* FPA is no longer supported.  */
 }
 
 /* Fill GDB's register array with the floating-point register values
@@ -508,7 +410,7 @@  fill_fpregset (const struct regcache *regcache,
 void
 supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregsetp)
 {
-  arm_linux_supply_nwfpe (NULL, regcache, -1, fpregsetp, 0);
+  /* FPA is no longer supported.  */
 }
 
 /* Fetch the thread-local storage pointer for libthread_db.  */
diff --git a/gdb/arm-linux-tdep.c b/gdb/arm-linux-tdep.c
index 1feb69fe6dd..d5ada33a05c 100644
--- a/gdb/arm-linux-tdep.c
+++ b/gdb/arm-linux-tdep.c
@@ -102,10 +102,8 @@  static const gdb_byte arm_linux_thumb2_le_breakpoint[] = { 0xf0, 0xf7, 0x00, 0xa
 
    For glibc, eglibc, and uclibc the following holds:  If the FP model is 
    SoftVFP or VFP (which implies EABI) then the PC is at offset 9 in the 
-   buffer.  This is also true for the SoftFPA model.  However, for the FPA 
-   model the PC is at offset 21 in the buffer.  */
+   buffer.  */
 #define ARM_LINUX_JB_ELEMENT_SIZE	ARM_INT_REGISTER_SIZE
-#define ARM_LINUX_JB_PC_FPA		21
 #define ARM_LINUX_JB_PC_EABI		9
 
 /*
@@ -540,119 +538,6 @@  arm_linux_collect_gregset (const struct regset *regset,
 			   gregs + ARM_INT_REGISTER_SIZE * ARM_PC_REGNUM);
 }
 
-/* Support for register format used by the NWFPE FPA emulator.  */
-
-#define typeNone		0x00
-#define typeSingle		0x01
-#define typeDouble		0x02
-#define typeExtended		0x03
-
-void
-supply_nwfpe_register (struct regcache *regcache, int regno,
-		       const gdb_byte *regs)
-{
-  const gdb_byte *reg_data;
-  gdb_byte reg_tag;
-  gdb_byte buf[ARM_FP_REGISTER_SIZE];
-
-  reg_data = regs + (regno - ARM_F0_REGNUM) * ARM_FP_REGISTER_SIZE;
-  reg_tag = regs[(regno - ARM_F0_REGNUM) + NWFPE_TAGS_OFFSET];
-  memset (buf, 0, ARM_FP_REGISTER_SIZE);
-
-  switch (reg_tag)
-    {
-    case typeSingle:
-      memcpy (buf, reg_data, 4);
-      break;
-    case typeDouble:
-      memcpy (buf, reg_data + 4, 4);
-      memcpy (buf + 4, reg_data, 4);
-      break;
-    case typeExtended:
-      /* We want sign and exponent, then least significant bits,
-	 then most significant.  NWFPE does sign, most, least.  */
-      memcpy (buf, reg_data, 4);
-      memcpy (buf + 4, reg_data + 8, 4);
-      memcpy (buf + 8, reg_data + 4, 4);
-      break;
-    default:
-      break;
-    }
-
-  regcache->raw_supply (regno, buf);
-}
-
-void
-collect_nwfpe_register (const struct regcache *regcache, int regno,
-			gdb_byte *regs)
-{
-  gdb_byte *reg_data;
-  gdb_byte reg_tag;
-  gdb_byte buf[ARM_FP_REGISTER_SIZE];
-
-  regcache->raw_collect (regno, buf);
-
-  /* NOTE drow/2006-06-07: This code uses the tag already in the
-     register buffer.  I've preserved that when moving the code
-     from the native file to the target file.  But this doesn't
-     always make sense.  */
-
-  reg_data = regs + (regno - ARM_F0_REGNUM) * ARM_FP_REGISTER_SIZE;
-  reg_tag = regs[(regno - ARM_F0_REGNUM) + NWFPE_TAGS_OFFSET];
-
-  switch (reg_tag)
-    {
-    case typeSingle:
-      memcpy (reg_data, buf, 4);
-      break;
-    case typeDouble:
-      memcpy (reg_data, buf + 4, 4);
-      memcpy (reg_data + 4, buf, 4);
-      break;
-    case typeExtended:
-      memcpy (reg_data, buf, 4);
-      memcpy (reg_data + 4, buf + 8, 4);
-      memcpy (reg_data + 8, buf + 4, 4);
-      break;
-    default:
-      break;
-    }
-}
-
-void
-arm_linux_supply_nwfpe (const struct regset *regset,
-			struct regcache *regcache,
-			int regnum, const void *regs_buf, size_t len)
-{
-  const gdb_byte *regs = (const gdb_byte *) regs_buf;
-  int regno;
-
-  if (regnum == ARM_FPS_REGNUM || regnum == -1)
-    regcache->raw_supply (ARM_FPS_REGNUM,
-			 regs + NWFPE_FPSR_OFFSET);
-
-  for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
-    if (regnum == -1 || regnum == regno)
-      supply_nwfpe_register (regcache, regno, regs);
-}
-
-void
-arm_linux_collect_nwfpe (const struct regset *regset,
-			 const struct regcache *regcache,
-			 int regnum, void *regs_buf, size_t len)
-{
-  gdb_byte *regs = (gdb_byte *) regs_buf;
-  int regno;
-
-  for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
-    if (regnum == -1 || regnum == regno)
-      collect_nwfpe_register (regcache, regno, regs);
-
-  if (regnum == ARM_FPS_REGNUM || regnum == -1)
-    regcache->raw_collect (ARM_FPS_REGNUM,
-			   regs + ARM_INT_REGISTER_SIZE * ARM_FPS_REGNUM);
-}
-
 /* Support VFP register format.  */
 
 #define ARM_LINUX_SIZEOF_VFP (32 * 8 + 4)
@@ -694,11 +579,6 @@  static const struct regset arm_linux_gregset =
     NULL, arm_linux_supply_gregset, arm_linux_collect_gregset
   };
 
-static const struct regset arm_linux_fpregset =
-  {
-    NULL, arm_linux_supply_nwfpe, arm_linux_collect_nwfpe
-  };
-
 static const struct regset arm_linux_vfpregset =
   {
     NULL, arm_linux_supply_vfp, arm_linux_collect_vfp
@@ -720,9 +600,6 @@  arm_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
   if (tdep->vfp_register_count > 0)
     cb (".reg-arm-vfp", ARM_LINUX_SIZEOF_VFP, ARM_LINUX_SIZEOF_VFP,
 	&arm_linux_vfpregset, "VFP floating-point", cb_data);
-  else if (tdep->have_fpa_registers)
-    cb (".reg2", ARM_LINUX_SIZEOF_NWFPE, ARM_LINUX_SIZEOF_NWFPE,
-	&arm_linux_fpregset, "FPA floating-point", cb_data);
 }
 
 /* Determine target description from core file.  */
@@ -1744,14 +1621,10 @@  arm_linux_init_abi (struct gdbarch_info info,
   tdep->thumb2_breakpoint_size = sizeof (arm_linux_thumb2_le_breakpoint);
 
   if (tdep->fp_model == ARM_FLOAT_AUTO)
-    tdep->fp_model = ARM_FLOAT_FPA;
+    tdep->fp_model = ARM_FLOAT_SOFT_VFP;
 
   switch (tdep->fp_model)
     {
-    case ARM_FLOAT_FPA:
-      tdep->jb_pc = ARM_LINUX_JB_PC_FPA;
-      break;
-    case ARM_FLOAT_SOFT_FPA:
     case ARM_FLOAT_SOFT_VFP:
     case ARM_FLOAT_VFP:
       tdep->jb_pc = ARM_LINUX_JB_PC_EABI;
diff --git a/gdb/arm-linux-tdep.h b/gdb/arm-linux-tdep.h
index 6ed55acf9b0..cb92c3f6bbe 100644
--- a/gdb/arm-linux-tdep.h
+++ b/gdb/arm-linux-tdep.h
@@ -23,23 +23,6 @@ 
 struct regset;
 struct regcache;
 
-#define ARM_LINUX_SIZEOF_NWFPE (8 * ARM_FP_REGISTER_SIZE \
-				+ 2 * ARM_INT_REGISTER_SIZE \
-				+ 8 + ARM_INT_REGISTER_SIZE)
-
-/* Support for register format used by the NWFPE FPA emulator.  Each
-   register takes three words, where either the first one, two, or
-   three hold a single, double, or extended precision value (depending
-   on the corresponding tag).  The register set is eight registers,
-   followed by the fpsr and fpcr, followed by eight tag bytes, and a
-   final word flag which indicates whether NWFPE has been
-   initialized.  */
-
-#define NWFPE_FPSR_OFFSET (8 * ARM_FP_REGISTER_SIZE)
-#define NWFPE_FPCR_OFFSET (NWFPE_FPSR_OFFSET + ARM_INT_REGISTER_SIZE)
-#define NWFPE_TAGS_OFFSET (NWFPE_FPCR_OFFSET + ARM_INT_REGISTER_SIZE)
-#define NWFPE_INITFLAG_OFFSET (NWFPE_TAGS_OFFSET + 8)
-
 void arm_linux_supply_gregset (const struct regset *regset,
 			       struct regcache *regcache,
 			       int regnum, const void *gregs_buf, size_t len);
@@ -47,18 +30,6 @@  void arm_linux_collect_gregset (const struct regset *regset,
 				const struct regcache *regcache,
 				int regnum, void *gregs_buf, size_t len);
 
-void supply_nwfpe_register (struct regcache *regcache, int regno,
-			    const gdb_byte *regs);
-void collect_nwfpe_register (const struct regcache *regcache, int regno,
-			     gdb_byte *regs);
-
-void arm_linux_supply_nwfpe (const struct regset *regset,
-			     struct regcache *regcache,
-			     int regnum, const void *regs_buf, size_t len);
-void arm_linux_collect_nwfpe (const struct regset *regset,
-			      const struct regcache *regcache,
-			      int regnum, void *regs_buf, size_t len);
-
 /* ARM GNU/Linux HWCAP values.  These are in defined in
    <asm/elf.h> in current kernels.  */
 #define HWCAP_VFP       64
diff --git a/gdb/arm-netbsd-nat.c b/gdb/arm-netbsd-nat.c
index 251159154c9..d37a1951c21 100644
--- a/gdb/arm-netbsd-nat.c
+++ b/gdb/arm-netbsd-nat.c
@@ -135,7 +135,7 @@  arm_netbsd_nat_target::fetch_registers (struct regcache *regcache, int regno)
 {
   if (regno >= 0)
     {
-      if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
+      if (regno <= ARM_PC_REGNUM || regno >= ARM_PS_REGNUM)
 	fetch_register (regcache, regno);
       else
 	fetch_fp_register (regcache, regno);
@@ -326,7 +326,7 @@  arm_netbsd_nat_target::store_registers (struct regcache *regcache, int regno)
 {
   if (regno >= 0)
     {
-      if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
+      if (regno <= ARM_PC_REGNUM || regno >= ARM_PS_REGNUM)
 	store_register (regcache, regno);
       else
 	store_fp_register (regcache, regno);
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index ead9bbf46c5..b33a53612a6 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -134,8 +134,6 @@  static struct cmd_list_element *showarmcmdlist = NULL;
 static const char *const fp_model_strings[] =
 {
   "auto",
-  "softfpa",
-  "fpa",
   "softvfp",
   "vfp",
   NULL
@@ -226,9 +224,7 @@  static const char *const arm_register_names[] =
  "r4",  "r5",  "r6",  "r7",	/*  4  5  6  7 */
  "r8",  "r9",  "r10", "r11",	/*  8  9 10 11 */
  "r12", "sp",  "lr",  "pc",	/* 12 13 14 15 */
- "f0",  "f1",  "f2",  "f3",	/* 16 17 18 19 */
- "f4",  "f5",  "f6",  "f7",	/* 20 21 22 23 */
- "fps", "cpsr" };		/* 24 25       */
+ "cpsr" };			/* 25 */
 
 /* Holds the current set of options to be passed to the disassembler.  */
 static char *arm_disassembler_options;
@@ -1877,7 +1873,7 @@  arm_analyze_prologue (struct gdbarch *gdbarch,
   enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
   int regno;
   CORE_ADDR offset, current_pc;
-  pv_t regs[ARM_FPS_REGNUM];
+  pv_t regs[ARM_PC_REGNUM];
   CORE_ADDR unrecognized_pc = 0;
   arm_gdbarch_tdep *tdep = gdbarch_tdep<arm_gdbarch_tdep> (gdbarch);
 
@@ -1891,7 +1887,7 @@  arm_analyze_prologue (struct gdbarch *gdbarch,
      and other operations that rely on a knowledge of the stack
      traceback.  */
 
-  for (regno = 0; regno < ARM_FPS_REGNUM; regno++)
+  for (regno = 0; regno < ARM_PC_REGNUM; regno++)
     regs[regno] = pv_register (regno, 0);
   pv_area stack (ARM_SP_REGNUM, gdbarch_addr_bit (gdbarch));
 
@@ -1982,51 +1978,6 @@  arm_analyze_prologue (struct gdbarch *gdbarch,
 	  uint32_t imm = arm_expand_immediate(insn & 0xfff);
 	  regs[ARM_SP_REGNUM] = pv_add_constant (regs[ARM_SP_REGNUM], -imm);
 	}
-      else if ((insn & 0xffff7fff) == 0xed6d0103	/* stfe f?,
-							   [sp, -#c]! */
-	       && tdep->have_fpa_registers)
-	{
-	  if (stack.store_would_trash (regs[ARM_SP_REGNUM]))
-	    break;
-
-	  regs[ARM_SP_REGNUM] = pv_add_constant (regs[ARM_SP_REGNUM], -12);
-	  regno = ARM_F0_REGNUM + ((insn >> 12) & 0x07);
-	  stack.store (regs[ARM_SP_REGNUM], 12, regs[regno]);
-	}
-      else if ((insn & 0xffbf0fff) == 0xec2d0200	/* sfmfd f0, 4,
-							   [sp!] */
-	       && tdep->have_fpa_registers)
-	{
-	  int n_saved_fp_regs;
-	  unsigned int fp_start_reg, fp_bound_reg;
-
-	  if (stack.store_would_trash (regs[ARM_SP_REGNUM]))
-	    break;
-
-	  if ((insn & 0x800) == 0x800)		/* N0 is set */
-	    {
-	      if ((insn & 0x40000) == 0x40000)	/* N1 is set */
-		n_saved_fp_regs = 3;
-	      else
-		n_saved_fp_regs = 1;
-	    }
-	  else
-	    {
-	      if ((insn & 0x40000) == 0x40000)	/* N1 is set */
-		n_saved_fp_regs = 2;
-	      else
-		n_saved_fp_regs = 4;
-	    }
-
-	  fp_start_reg = ARM_F0_REGNUM + ((insn >> 12) & 0x7);
-	  fp_bound_reg = fp_start_reg + n_saved_fp_regs;
-	  for (; fp_start_reg < fp_bound_reg; fp_start_reg++)
-	    {
-	      regs[ARM_SP_REGNUM] = pv_add_constant (regs[ARM_SP_REGNUM], -12);
-	      stack.store (regs[ARM_SP_REGNUM], 12,
-			   regs[fp_start_reg++]);
-	    }
-	}
       else if ((insn & 0xff000000) == 0xeb000000 && cache == NULL) /* bl */
 	{
 	  /* Allow some special function calls when skipping the
@@ -2103,7 +2054,7 @@  arm_analyze_prologue (struct gdbarch *gdbarch,
       cache->framereg = framereg;
       cache->framesize = framesize;
 
-      for (regno = 0; regno < ARM_FPS_REGNUM; regno++)
+      for (regno = 0; regno < ARM_PC_REGNUM; regno++)
 	if (stack.find_reg (gdbarch, regno, &offset))
 	  {
 	    cache->saved_regs[regno].set_addr (offset);
@@ -4666,58 +4617,6 @@  arm_frame_align (struct gdbarch *gdbarch, CORE_ADDR sp)
   return sp & ~ (CORE_ADDR) 7;
 }
 
-static void
-print_fpu_flags (struct ui_file *file, int flags)
-{
-  if (flags & (1 << 0))
-    gdb_puts ("IVO ", file);
-  if (flags & (1 << 1))
-    gdb_puts ("DVZ ", file);
-  if (flags & (1 << 2))
-    gdb_puts ("OFL ", file);
-  if (flags & (1 << 3))
-    gdb_puts ("UFL ", file);
-  if (flags & (1 << 4))
-    gdb_puts ("INX ", file);
-  gdb_putc ('\n', file);
-}
-
-/* Print interesting information about the floating point processor
-   (if present) or emulator.  */
-static void
-arm_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
-		      struct frame_info *frame, const char *args)
-{
-  unsigned long status = get_frame_register_unsigned (frame, ARM_FPS_REGNUM);
-  int type;
-
-  type = (status >> 24) & 127;
-  if (status & (1 << 31))
-    gdb_printf (file, _("Hardware FPU type %d\n"), type);
-  else
-    gdb_printf (file, _("Software FPU type %d\n"), type);
-  /* i18n: [floating point unit] mask */
-  gdb_puts (_("mask: "), file);
-  print_fpu_flags (file, status >> 16);
-  /* i18n: [floating point unit] flags */
-  gdb_puts (_("flags: "), file);
-  print_fpu_flags (file, status);
-}
-
-/* Construct the ARM extended floating point type.  */
-static struct type *
-arm_ext_type (struct gdbarch *gdbarch)
-{
-  arm_gdbarch_tdep *tdep = gdbarch_tdep<arm_gdbarch_tdep> (gdbarch);
-
-  if (!tdep->arm_ext_type)
-    tdep->arm_ext_type
-      = arch_float_type (gdbarch, -1, "builtin_type_arm_ext",
-			 floatformats_arm_ext);
-
-  return tdep->arm_ext_type;
-}
-
 static struct type *
 arm_neon_double_type (struct gdbarch *gdbarch)
 {
@@ -4902,14 +4801,7 @@  arm_register_type (struct gdbarch *gdbarch, int regnum)
 	return t;
     }
 
-  if (regnum >= ARM_F0_REGNUM && regnum < ARM_F0_REGNUM + NUM_FREGS)
-    {
-      if (!tdep->have_fpa_registers)
-	return builtin_type (gdbarch)->builtin_void;
-
-      return arm_ext_type (gdbarch);
-    }
-  else if (regnum == ARM_SP_REGNUM)
+  if (regnum == ARM_SP_REGNUM)
     return builtin_type (gdbarch)->builtin_data_ptr;
   else if (regnum == ARM_PC_REGNUM)
     return builtin_type (gdbarch)->builtin_func_ptr;
@@ -4931,17 +4823,6 @@  arm_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int reg)
   if (reg >= 0 && reg <= 15)
     return reg;
 
-  /* Legacy FPA encoding.  These were once used in a way which
-     overlapped with VFP register numbering, so their use is
-     discouraged, but GDB doesn't support the ARM toolchain
-     which used them for VFP.  */
-  if (reg >= 16 && reg <= 23)
-    return ARM_F0_REGNUM + reg - 16;
-
-  /* New assignments for the FPA registers.  */
-  if (reg >= 96 && reg <= 103)
-    return ARM_F0_REGNUM + reg - 96;
-
   /* WMMX register assignments.  */
   if (reg >= 104 && reg <= 111)
     return ARM_WCGR0_REGNUM + reg - 104;
@@ -5014,14 +4895,6 @@  arm_register_sim_regno (struct gdbarch *gdbarch, int regnum)
     return SIM_ARM_R0_REGNUM + reg;
   reg -= NUM_GREGS;
 
-  if (reg < NUM_FREGS)
-    return SIM_ARM_FP0_REGNUM + reg;
-  reg -= NUM_FREGS;
-
-  if (reg < NUM_SREGS)
-    return SIM_ARM_FPS_REGNUM + reg;
-  reg -= NUM_SREGS;
-
   internal_error (__FILE__, __LINE__, _("Bad REGNUM %d"), regnum);
 }
 
@@ -8686,20 +8559,6 @@  arm_extract_return_value (struct type *type, struct regcache *regs,
     {
       switch (tdep->fp_model)
 	{
-	case ARM_FLOAT_FPA:
-	  {
-	    /* The value is in register F0 in internal format.  We need to
-	       extract the raw value and then convert it to the desired
-	       internal type.  */
-	    bfd_byte tmpbuf[ARM_FP_REGISTER_SIZE];
-
-	    regs->cooked_read (ARM_F0_REGNUM, tmpbuf);
-	    target_float_convert (tmpbuf, arm_ext_type (gdbarch),
-				  valbuf, type);
-	  }
-	  break;
-
-	case ARM_FLOAT_SOFT_FPA:
 	case ARM_FLOAT_SOFT_VFP:
 	  /* ARM_FLOAT_VFP can arise if this is a variadic function so
 	     not using the VFP ABI code.  */
@@ -8896,18 +8755,10 @@  arm_store_return_value (struct type *type, struct regcache *regs,
 
   if (type->code () == TYPE_CODE_FLT)
     {
-      gdb_byte buf[ARM_FP_REGISTER_SIZE];
       arm_gdbarch_tdep *tdep = gdbarch_tdep<arm_gdbarch_tdep> (gdbarch);
 
       switch (tdep->fp_model)
 	{
-	case ARM_FLOAT_FPA:
-
-	  target_float_convert (valbuf, type, buf, arm_ext_type (gdbarch));
-	  regs->cooked_write (ARM_F0_REGNUM, buf);
-	  break;
-
-	case ARM_FLOAT_SOFT_FPA:
 	case ARM_FLOAT_SOFT_VFP:
 	  /* ARM_FLOAT_VFP can arise if this is a variadic function so
 	     not using the VFP ABI code.  */
@@ -9722,71 +9573,6 @@  arm_elf_osabi_sniffer (bfd *abfd)
   return osabi;
 }
 
-static int
-arm_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
-			 const struct reggroup *group)
-{
-  /* FPS register's type is INT, but belongs to float_reggroup.  Beside
-     this, FPS register belongs to save_regroup, restore_reggroup, and
-     all_reggroup, of course.  */
-  if (regnum == ARM_FPS_REGNUM)
-    return (group == float_reggroup
-	    || group == save_reggroup
-	    || group == restore_reggroup
-	    || group == all_reggroup);
-  else
-    return default_register_reggroup_p (gdbarch, regnum, group);
-}
-
-/* For backward-compatibility we allow two 'g' packet lengths with
-   the remote protocol depending on whether FPA registers are
-   supplied.  M-profile targets do not have FPA registers, but some
-   stubs already exist in the wild which use a 'g' packet which
-   supplies them albeit with dummy values.  The packet format which
-   includes FPA registers should be considered deprecated for
-   M-profile targets.  */
-
-static void
-arm_register_g_packet_guesses (struct gdbarch *gdbarch)
-{
-  arm_gdbarch_tdep *tdep = gdbarch_tdep<arm_gdbarch_tdep> (gdbarch);
-
-  if (tdep->is_m)
-    {
-      const target_desc *tdesc;
-
-      /* If we know from the executable this is an M-profile target,
-	 cater for remote targets whose register set layout is the
-	 same as the FPA layout.  */
-      tdesc = arm_read_mprofile_description (ARM_M_TYPE_WITH_FPA);
-      register_remote_g_packet_guess (gdbarch,
-				      ARM_CORE_REGS_SIZE + ARM_FP_REGS_SIZE,
-				      tdesc);
-
-      /* The regular M-profile layout.  */
-      tdesc = arm_read_mprofile_description (ARM_M_TYPE_M_PROFILE);
-      register_remote_g_packet_guess (gdbarch, ARM_CORE_REGS_SIZE,
-				      tdesc);
-
-      /* M-profile plus M4F VFP.  */
-      tdesc = arm_read_mprofile_description (ARM_M_TYPE_VFP_D16);
-      register_remote_g_packet_guess (gdbarch,
-				      ARM_CORE_REGS_SIZE + ARM_VFP2_REGS_SIZE,
-				      tdesc);
-      /* M-profile plus MVE.  */
-      tdesc = arm_read_mprofile_description (ARM_M_TYPE_MVE);
-      register_remote_g_packet_guess (gdbarch, ARM_CORE_REGS_SIZE
-				      + ARM_VFP2_REGS_SIZE
-				      + ARM_INT_REGISTER_SIZE, tdesc);
-
-      /* M-profile system (stack pointers).  */
-      tdesc = arm_read_mprofile_description (ARM_M_TYPE_SYSTEM);
-      register_remote_g_packet_guess (gdbarch, 2 * ARM_INT_REGISTER_SIZE, tdesc);
-    }
-
-  /* Otherwise we don't have a useful guess.  */
-}
-
 /* Implement the code_of_frame_writable gdbarch method.  */
 
 static int
@@ -9848,7 +9634,6 @@  arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   bool have_s_pseudos = false, have_q_pseudos = false;
   bool have_wmmx_registers = false;
   bool have_neon = false;
-  bool have_fpa_registers = true;
   const struct target_desc *tdesc = info.target_desc;
   bool have_vfp = false;
   bool have_mve = false;
@@ -10015,21 +9800,13 @@  arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 	    {
 	      switch (e_flags & (EF_ARM_SOFT_FLOAT | EF_ARM_VFP_FLOAT))
 		{
-		case 0:
-		  /* Leave it as "auto".  Strictly speaking this case
-		     means FPA, but almost nobody uses that now, and
-		     many toolchains fail to set the appropriate bits
-		     for the floating-point model they use.  */
-		  break;
-		case EF_ARM_SOFT_FLOAT:
-		  fp_model = ARM_FLOAT_SOFT_FPA;
+		case 0: /* Default to soft-float VFP.  */
+		case EF_ARM_SOFT_FLOAT | EF_ARM_VFP_FLOAT:
+		  fp_model = ARM_FLOAT_SOFT_VFP;
 		  break;
 		case EF_ARM_VFP_FLOAT:
 		  fp_model = ARM_FLOAT_VFP;
 		  break;
-		case EF_ARM_SOFT_FLOAT | EF_ARM_VFP_FLOAT:
-		  fp_model = ARM_FLOAT_SOFT_VFP;
-		  break;
 		}
 	    }
 
@@ -10122,20 +9899,6 @@  arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 	    }
 	}
 
-      feature = tdesc_find_feature (tdesc,
-				    "org.gnu.gdb.arm.fpa");
-      if (feature != NULL)
-	{
-	  valid_p = 1;
-	  for (i = ARM_F0_REGNUM; i <= ARM_FPS_REGNUM; i++)
-	    valid_p &= tdesc_numbered_register (feature, tdesc_data.get (), i,
-						arm_register_names[i]);
-	  if (!valid_p)
-	    return NULL;
-	}
-      else
-	have_fpa_registers = false;
-
       feature = tdesc_find_feature (tdesc,
 				    "org.gnu.gdb.xscale.iwmmxt");
       if (feature != NULL)
@@ -10389,7 +10152,6 @@  arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep->fp_model = fp_model;
   tdep->is_m = is_m;
   tdep->have_sec_ext = have_sec_ext;
-  tdep->have_fpa_registers = have_fpa_registers;
   tdep->have_wmmx_registers = have_wmmx_registers;
   gdb_assert (vfp_register_count == 0
 	      || vfp_register_count == 16
@@ -10421,8 +10183,6 @@  arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       tdep->m_profile_psp_s_regnum = m_profile_psp_s_regnum;
     }
 
-  arm_register_g_packet_guesses (gdbarch);
-
   /* Breakpoints.  */
   switch (info.byte_order_for_code)
     {
@@ -10508,12 +10268,6 @@  arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_pc_regnum (gdbarch, ARM_PC_REGNUM);
   set_gdbarch_num_regs (gdbarch, register_count);
   set_gdbarch_register_type (gdbarch, arm_register_type);
-  set_gdbarch_register_reggroup_p (gdbarch, arm_register_reggroup_p);
-
-  /* This "info float" is FPA-specific.  Use the generic version if we
-     do not have FPA.  */
-  if (tdep->have_fpa_registers)
-    set_gdbarch_print_float_info (gdbarch, arm_print_float_info);
 
   /* Internal <-> external register number maps.  */
   set_gdbarch_dwarf2_reg_to_regnum (gdbarch, arm_dwarf_reg_to_regnum);
@@ -10565,29 +10319,13 @@  arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   /* Watchpoints are not steppable.  */
   set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1);
 
-  /* We used to default to FPA for generic ARM, but almost nobody
-     uses that now, and we now provide a way for the user to force
-     the model.  So default to the most useful variant.  */
-  if (tdep->fp_model == ARM_FLOAT_AUTO)
-    tdep->fp_model = ARM_FLOAT_SOFT_FPA;
-
   if (tdep->jb_pc >= 0)
     set_gdbarch_get_longjmp_target (gdbarch, arm_get_longjmp_target);
 
   /* Floating point sizes and format.  */
   set_gdbarch_float_format (gdbarch, floatformats_ieee_single);
-  if (tdep->fp_model == ARM_FLOAT_SOFT_FPA || tdep->fp_model == ARM_FLOAT_FPA)
-    {
-      set_gdbarch_double_format
-	(gdbarch, floatformats_ieee_double_littlebyte_bigword);
-      set_gdbarch_long_double_format
-	(gdbarch, floatformats_ieee_double_littlebyte_bigword);
-    }
-  else
-    {
-      set_gdbarch_double_format (gdbarch, floatformats_ieee_double);
-      set_gdbarch_long_double_format (gdbarch, floatformats_ieee_double);
-    }
+  set_gdbarch_double_format (gdbarch, floatformats_ieee_double);
+  set_gdbarch_long_double_format (gdbarch, floatformats_ieee_double);
 
   /* Hook used to decorate frames with signed return addresses, only available
      for ARMv8.1-m PACBTI.  */
@@ -10678,8 +10416,6 @@  arm_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file)
 
   gdb_printf (file, _("arm_dump_tdep: fp_model = %i\n"),
 	      (int) tdep->fp_model);
-  gdb_printf (file, _("arm_dump_tdep: have_fpa_registers = %i\n"),
-	      (int) tdep->have_fpa_registers);
   gdb_printf (file, _("arm_dump_tdep: have_wmmx_registers = %i\n"),
 	      (int) tdep->have_wmmx_registers);
   gdb_printf (file, _("arm_dump_tdep: vfp_register_count = %i\n"),
@@ -10820,8 +10556,6 @@  _initialize_arm_tdep ()
 			_("Set the floating point type."),
 			_("Show the floating point type."),
 			_("auto - Determine the FP typefrom the OS-ABI.\n\
-softfpa - Software FP, mixed-endian doubles on little-endian ARMs.\n\
-fpa - FPA co-processor (GCC compiled).\n\
 softvfp - Software FP with pure-endian doubles.\n\
 vfp - VFP co-processor."),
 			set_fp_model_sfunc, show_fp_model,
diff --git a/gdb/arm-tdep.h b/gdb/arm-tdep.h
index 67dd1151da4..594961e52ec 100644
--- a/gdb/arm-tdep.h
+++ b/gdb/arm-tdep.h
@@ -62,8 +62,6 @@  extern bool arm_apcs_32;
 enum arm_float_model
 {
   ARM_FLOAT_AUTO,	/* Automatic detection.  Do not set in tdep.  */
-  ARM_FLOAT_SOFT_FPA,	/* Traditional soft-float (mixed-endian on LE ARM).  */
-  ARM_FLOAT_FPA,	/* FPA co-processor.  GCC calling convention.  */
   ARM_FLOAT_SOFT_VFP,	/* Soft-float with pure-endian doubles.  */
   ARM_FLOAT_VFP,	/* Full VFP calling convention.  */
   ARM_FLOAT_LAST	/* Keep at end.  */
@@ -95,7 +93,6 @@  struct arm_gdbarch_tdep : gdbarch_tdep_base
 
   enum arm_float_model fp_model {}; /* Floating point calling conventions.  */
 
-  bool have_fpa_registers = false;	/* Does the target report the FPA registers?  */
   bool have_wmmx_registers = false;	/* Does the target report the WMMX registers?  */
   /* The number of VFP registers reported by the target.  It is zero
      if VFP registers are not supported.  */
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 238a49b027d..2111a584b88 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -25309,11 +25309,6 @@  argument @var{fputype} can be one of these:
 @table @code
 @item auto
 Determine the FPU type by querying the OS ABI.
-@item softfpa
-Software FPU, with mixed-endian doubles on little-endian ARM
-processors.
-@item fpa
-GCC-compiled FPA co-processor.
 @item softvfp
 Software FPU with pure-endian doubles.
 @item vfp
@@ -46919,9 +46914,6 @@  Double precision IEEE floating point.
 @item bfloat16
 The 16-bit @dfn{brain floating point} format used e.g.@: by x86 and ARM.
 
-@item arm_fpa_ext
-The 12-byte extended precision format used by ARM FPA registers.
-
 @item i387_ext
 The 10-byte extended precision format used by x87 registers.
 
@@ -47106,8 +47098,9 @@  feature is replaced by @samp{org.gnu.gdb.arm.m-profile}.  It should contain
 registers @samp{r0} through @samp{r13}, @samp{sp}, @samp{lr}, @samp{pc},
 and @samp{xpsr}.
 
-The @samp{org.gnu.gdb.arm.fpa} feature is optional.  If present, it
-should contain registers @samp{f0} through @samp{f7} and @samp{fps}.
+The @samp{org.gnu.gdb.arm.fpa} feature is no longer supported.  It
+used to contain registers @samp{f0} through @samp{f7} and @samp{fps}, for the
+legacy FPA feature.
 
 The @samp{org.gnu.gdb.arm.m-profile-mve} feature is optional.  If present, it
 must contain register @samp{vpr}.
diff --git a/gdb/features/Makefile b/gdb/features/Makefile
index 061cb2ed032..3d0ed4edafa 100644
--- a/gdb/features/Makefile
+++ b/gdb/features/Makefile
@@ -204,11 +204,9 @@  FEATURE_XMLFILES = aarch64-core.xml \
 	arc/v2-core.xml \
 	arc/v2-aux.xml \
 	arm/arm-core.xml \
-	arm/arm-fpa.xml \
 	arm/arm-m-profile.xml \
 	arm/arm-m-profile-mve.xml \
 	arm/arm-m-system.xml \
-	arm/arm-m-profile-with-fpa.xml \
 	arm/arm-tls.xml \
 	arm/arm-vfpv2.xml \
 	arm/arm-vfpv3.xml \
diff --git a/gdb/features/arm/arm-fpa.c b/gdb/features/arm/arm-fpa.c
deleted file mode 100644
index 65a49f5f3f1..00000000000
--- a/gdb/features/arm/arm-fpa.c
+++ /dev/null
@@ -1,23 +0,0 @@ 
-/* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
-  Original: arm-fpa.xml */
-
-#include "gdbsupport/tdesc.h"
-
-static int
-create_feature_arm_arm_fpa (struct target_desc *result, long regnum)
-{
-  struct tdesc_feature *feature;
-
-  feature = tdesc_create_feature (result, "org.gnu.gdb.arm.fpa");
-  regnum = 16;
-  tdesc_create_reg (feature, "f0", regnum++, 1, NULL, 96, "arm_fpa_ext");
-  tdesc_create_reg (feature, "f1", regnum++, 1, NULL, 96, "arm_fpa_ext");
-  tdesc_create_reg (feature, "f2", regnum++, 1, NULL, 96, "arm_fpa_ext");
-  tdesc_create_reg (feature, "f3", regnum++, 1, NULL, 96, "arm_fpa_ext");
-  tdesc_create_reg (feature, "f4", regnum++, 1, NULL, 96, "arm_fpa_ext");
-  tdesc_create_reg (feature, "f5", regnum++, 1, NULL, 96, "arm_fpa_ext");
-  tdesc_create_reg (feature, "f6", regnum++, 1, NULL, 96, "arm_fpa_ext");
-  tdesc_create_reg (feature, "f7", regnum++, 1, NULL, 96, "arm_fpa_ext");
-  tdesc_create_reg (feature, "fps", regnum++, 1, NULL, 32, "int");
-  return regnum;
-}
diff --git a/gdb/features/arm/arm-fpa.xml b/gdb/features/arm/arm-fpa.xml
deleted file mode 100644
index d533b25132f..00000000000
--- a/gdb/features/arm/arm-fpa.xml
+++ /dev/null
@@ -1,23 +0,0 @@ 
-<?xml version="1.0"?>
-<!-- Copyright (C) 2007-2022 Free Software Foundation, Inc.
-
-     Copying and distribution of this file, with or without modification,
-     are permitted in any medium without royalty provided the copyright
-     notice and this notice are preserved.  -->
-
-<!DOCTYPE feature SYSTEM "gdb-target.dtd">
-<feature name="org.gnu.gdb.arm.fpa">
-  <!-- f0's regnum is set explicitly, because the FPA registers
-       historically were placed between the PC and the CPSR in the "g"
-       packet - in the middle of org.gnu.gdb.arm.core.  -->
-  <reg name="f0" bitsize="96" type="arm_fpa_ext" regnum="16"/>
-  <reg name="f1" bitsize="96" type="arm_fpa_ext"/>
-  <reg name="f2" bitsize="96" type="arm_fpa_ext"/>
-  <reg name="f3" bitsize="96" type="arm_fpa_ext"/>
-  <reg name="f4" bitsize="96" type="arm_fpa_ext"/>
-  <reg name="f5" bitsize="96" type="arm_fpa_ext"/>
-  <reg name="f6" bitsize="96" type="arm_fpa_ext"/>
-  <reg name="f7" bitsize="96" type="arm_fpa_ext"/>
-
-  <reg name="fps" bitsize="32"/>
-</feature>
diff --git a/gdb/features/arm/arm-m-profile-with-fpa.c b/gdb/features/arm/arm-m-profile-with-fpa.c
deleted file mode 100644
index 2b7c78597bb..00000000000
--- a/gdb/features/arm/arm-m-profile-with-fpa.c
+++ /dev/null
@@ -1,39 +0,0 @@ 
-/* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
-  Original: arm-m-profile-with-fpa.xml */
-
-#include "gdbsupport/tdesc.h"
-
-static int
-create_feature_arm_arm_m_profile_with_fpa (struct target_desc *result, long regnum)
-{
-  struct tdesc_feature *feature;
-
-  feature = tdesc_create_feature (result, "org.gnu.gdb.arm.m-profile");
-  tdesc_create_reg (feature, "r0", regnum++, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r1", regnum++, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r2", regnum++, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r3", regnum++, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r4", regnum++, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r5", regnum++, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r6", regnum++, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r7", regnum++, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r8", regnum++, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r9", regnum++, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r10", regnum++, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r11", regnum++, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r12", regnum++, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "sp", regnum++, 1, NULL, 32, "data_ptr");
-  tdesc_create_reg (feature, "lr", regnum++, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "pc", regnum++, 1, NULL, 32, "code_ptr");
-  tdesc_create_reg (feature, "", regnum++, 1, NULL, 96, "arm_fpa_ext");
-  tdesc_create_reg (feature, "", regnum++, 1, NULL, 96, "arm_fpa_ext");
-  tdesc_create_reg (feature, "", regnum++, 1, NULL, 96, "arm_fpa_ext");
-  tdesc_create_reg (feature, "", regnum++, 1, NULL, 96, "arm_fpa_ext");
-  tdesc_create_reg (feature, "", regnum++, 1, NULL, 96, "arm_fpa_ext");
-  tdesc_create_reg (feature, "", regnum++, 1, NULL, 96, "arm_fpa_ext");
-  tdesc_create_reg (feature, "", regnum++, 1, NULL, 96, "arm_fpa_ext");
-  tdesc_create_reg (feature, "", regnum++, 1, NULL, 96, "arm_fpa_ext");
-  tdesc_create_reg (feature, "", regnum++, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "xpsr", regnum++, 1, NULL, 32, "int");
-  return regnum;
-}
diff --git a/gdb/features/arm/arm-m-profile-with-fpa.xml b/gdb/features/arm/arm-m-profile-with-fpa.xml
deleted file mode 100644
index 850ed42cbfd..00000000000
--- a/gdb/features/arm/arm-m-profile-with-fpa.xml
+++ /dev/null
@@ -1,39 +0,0 @@ 
-<?xml version="1.0"?>
-<!-- Copyright (C) 2019-2022 Free Software Foundation, Inc.
-
-     Copying and distribution of this file, with or without modification,
-     are permitted in any medium without royalty provided the copyright
-     notice and this notice are preserved.  -->
-
-<!DOCTYPE feature SYSTEM "gdb-target.dtd">
-<feature name="org.gnu.gdb.arm.m-profile">
-  <reg name="r0" bitsize="32"/>
-  <reg name="r1" bitsize="32"/>
-  <reg name="r2" bitsize="32"/>
-  <reg name="r3" bitsize="32"/>
-  <reg name="r4" bitsize="32"/>
-  <reg name="r5" bitsize="32"/>
-  <reg name="r6" bitsize="32"/>
-  <reg name="r7" bitsize="32"/>
-  <reg name="r8" bitsize="32"/>
-  <reg name="r9" bitsize="32"/>
-  <reg name="r10" bitsize="32"/>
-  <reg name="r11" bitsize="32"/>
-  <reg name="r12" bitsize="32"/>
-  <reg name="sp" bitsize="32" type="data_ptr"/>
-  <reg name="lr" bitsize="32"/>
-  <reg name="pc" bitsize="32" type="code_ptr"/>
-
-  <!-- Slack for unused FPA registers (f0-f7 + fps).  -->
-  <reg name="" bitsize="96" type="arm_fpa_ext" regnum="16"/>
-  <reg name="" bitsize="96" type="arm_fpa_ext"/>
-  <reg name="" bitsize="96" type="arm_fpa_ext"/>
-  <reg name="" bitsize="96" type="arm_fpa_ext"/>
-  <reg name="" bitsize="96" type="arm_fpa_ext"/>
-  <reg name="" bitsize="96" type="arm_fpa_ext"/>
-  <reg name="" bitsize="96" type="arm_fpa_ext"/>
-  <reg name="" bitsize="96" type="arm_fpa_ext"/>
-  <reg name="" bitsize="32"/>
-
-  <reg name="xpsr" bitsize="32" regnum="25"/>
-</feature>
diff --git a/gdb/target-descriptions.c b/gdb/target-descriptions.c
index 044b171ecd2..45a3df941c5 100644
--- a/gdb/target-descriptions.c
+++ b/gdb/target-descriptions.c
@@ -132,10 +132,6 @@  make_gdb_type (struct gdbarch *gdbarch, struct tdesc_type *ttype)
 	  m_type = arch_float_type (m_gdbarch, -1, "builtin_type_ieee_double",
 				    floatformats_ieee_double);
 	  return;
-	case TDESC_TYPE_ARM_FPA_EXT:
-	  m_type = arch_float_type (m_gdbarch, -1, "builtin_type_arm_ext",
-				    floatformats_arm_ext);
-	  return;
 
 	case TDESC_TYPE_I387_EXT:
 	  m_type = arch_float_type (m_gdbarch, -1, "builtin_type_i387_ext",
diff --git a/gdb/testsuite/gdb.base/long_long.exp b/gdb/testsuite/gdb.base/long_long.exp
index 9c8dd16b7eb..bb4c1a1859e 100644
--- a/gdb/testsuite/gdb.base/long_long.exp
+++ b/gdb/testsuite/gdb.base/long_long.exp
@@ -141,22 +141,10 @@  gdb_test_ptr "p/a val.oct" "" "" "0x77053977" "0xa72ee53977053977"
 gdb_test "p/c val.oct" "'w'"
 
 if { $sizeof_double == 8 || $sizeof_long_double == 8 } {
-    # ARM FPA floating point numbers are not strictly little endian or big
-    # endian, but a hybrid.  They are in little endian format with the two
-    # words swapped in big endian format.
     # EABI targets default to natural-endian VFP format.
-
-    if { ([istarget "arm*-*-*"]) \
-	 && !([istarget "*-*-*eabi*"] || \
-	      [istarget "*-*-mingw32ce*"] || \
-	      [istarget "*-*-openbsd*"]) } then {
-	# assume the long long represents a floating point double in ARM format
-	gdb_test "p/f val.oct" "2.1386676354387559e\\+265"
-    } else {
-	# assume the long long represents a floating point double in little
-	# endian format
-	gdb_test "p/f val.oct" "-5.9822653797615723e-120"
-    }
+    # Assume the long long represents a floating point double in little
+    # endian format
+    gdb_test "p/f val.oct" "-5.9822653797615723e-120"
 } else {
     gdb_test "p/f val.oct" "-2.42716126e-15"
 }
diff --git a/gdbserver/linux-arm-low.cc b/gdbserver/linux-arm-low.cc
index ab6209a3abc..fb3f02088ca 100644
--- a/gdbserver/linux-arm-low.cc
+++ b/gdbserver/linux-arm-low.cc
@@ -983,8 +983,7 @@  arm_read_description (void)
 	return arm_linux_read_description (ARM_FP_TYPE_VFPV2);
     }
 
-  /* The default configuration uses legacy FPA registers, probably
-     simulated.  */
+  /* No floating point registers.  */
   return arm_linux_read_description (ARM_FP_TYPE_NONE);
 }
 
@@ -1088,9 +1087,9 @@  static struct regset_info arm_regsets[] = {
   { PTRACE_GETREGS, PTRACE_SETREGS, 0,
     ARM_CORE_REGS_SIZE + ARM_INT_REGISTER_SIZE, GENERAL_REGS,
     arm_fill_gregset, arm_store_gregset },
-  { PTRACE_GETWMMXREGS, PTRACE_SETWMMXREGS, 0, IWMMXT_REGS_SIZE, EXTENDED_REGS,
+  { PTRACE_GETWMMXREGS, PTRACE_SETWMMXREGS, 0, IWMMXT_REGS_SIZE, OPTIONAL_REGS,
     arm_fill_wmmxregset, arm_store_wmmxregset },
-  { PTRACE_GETVFPREGS, PTRACE_SETVFPREGS, 0, ARM_VFP3_REGS_SIZE, EXTENDED_REGS,
+  { PTRACE_GETVFPREGS, PTRACE_SETVFPREGS, 0, ARM_VFP3_REGS_SIZE, OPTIONAL_REGS,
     arm_fill_vfpregset, arm_store_vfpregset },
   NULL_REGSET
 };
diff --git a/gdbsupport/tdesc.cc b/gdbsupport/tdesc.cc
index 4d41d0b168a..0b0b765cb3d 100644
--- a/gdbsupport/tdesc.cc
+++ b/gdbsupport/tdesc.cc
@@ -53,7 +53,6 @@  static tdesc_type_builtin tdesc_predefined_types[] =
   { "ieee_half", TDESC_TYPE_IEEE_HALF },
   { "ieee_single", TDESC_TYPE_IEEE_SINGLE },
   { "ieee_double", TDESC_TYPE_IEEE_DOUBLE },
-  { "arm_fpa_ext", TDESC_TYPE_ARM_FPA_EXT },
   { "i387_ext", TDESC_TYPE_I387_EXT },
   { "bfloat16", TDESC_TYPE_BFLOAT16 }
 };
diff --git a/gdbsupport/tdesc.h b/gdbsupport/tdesc.h
index 403aa2c3d19..082819ada13 100644
--- a/gdbsupport/tdesc.h
+++ b/gdbsupport/tdesc.h
@@ -171,7 +171,6 @@  enum tdesc_type_kind
   TDESC_TYPE_IEEE_HALF,
   TDESC_TYPE_IEEE_SINGLE,
   TDESC_TYPE_IEEE_DOUBLE,
-  TDESC_TYPE_ARM_FPA_EXT,
   TDESC_TYPE_I387_EXT,
   TDESC_TYPE_BFLOAT16,