/* none on ARM target support.

   Copyright (C) 2020-2024 Free Software Foundation, Inc.

   This file is part of GDB.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

#include "arm-tdep.h"
#include "arch-utils.h"
#include "extract-store-integer.h"
#include "regcache.h"
#include "elf-bfd.h"
#include "regset.h"
#include "user-regs.h"

#ifdef HAVE_ELF
#include "elf-none-tdep.h"
#endif

/* Core file and register set support.  */
#define ARM_NONE_SIZEOF_GREGSET (18 * ARM_INT_REGISTER_SIZE)

/* Support VFP register format.  */
#define ARM_NONE_SIZEOF_VFP (32 * 8 + 4)

/* The index to access CPSR in user_regs as defined in GLIBC.  */
#define ARM_NONE_CPSR_GREGNUM 16

/* Supply register REGNUM from buffer GREGS_BUF (length LEN bytes) into
   REGCACHE.  If REGNUM is -1 then supply all registers.  The set of
   registers that this function will supply is limited to the general
   purpose registers.

   The layout of the registers here is based on the ARM GNU/Linux
   layout.  */

static void
arm_none_supply_gregset (const struct regset *regset,
			 struct regcache *regcache,
			 int regnum, const void *gregs_buf, size_t len)
{
  struct gdbarch *gdbarch = regcache->arch ();
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  const gdb_byte *gregs = (const gdb_byte *) gregs_buf;

  for (int regno = ARM_A1_REGNUM; regno < ARM_PC_REGNUM; regno++)
    if (regnum == -1 || regnum == regno)
      regcache->raw_supply (regno, gregs + ARM_INT_REGISTER_SIZE * regno);

  if (regnum == ARM_PS_REGNUM || regnum == -1)
    {
      if (arm_apcs_32)
	regcache->raw_supply (ARM_PS_REGNUM,
			      gregs + ARM_INT_REGISTER_SIZE
			      * ARM_NONE_CPSR_GREGNUM);
      else
	regcache->raw_supply (ARM_PS_REGNUM,
			     gregs + ARM_INT_REGISTER_SIZE * ARM_PC_REGNUM);
    }

  if (regnum == ARM_PC_REGNUM || regnum == -1)
    {
      gdb_byte pc_buf[ARM_INT_REGISTER_SIZE];

      CORE_ADDR reg_pc
	= extract_unsigned_integer (gregs + ARM_INT_REGISTER_SIZE
				    * ARM_PC_REGNUM,
				    ARM_INT_REGISTER_SIZE, byte_order);
      reg_pc = gdbarch_addr_bits_remove (gdbarch, reg_pc);
      store_unsigned_integer (pc_buf, ARM_INT_REGISTER_SIZE, byte_order,
			      reg_pc);
      regcache->raw_supply (ARM_PC_REGNUM, pc_buf);
    }
}

/* Collect register REGNUM from REGCACHE and place it into buffer GREGS_BUF
   (length LEN bytes).  If REGNUM is -1 then collect all registers.  The
   set of registers that this function will collect is limited to the
   general purpose registers.

   The layout of the registers here is based on the ARM GNU/Linux
   layout.  */

static void
arm_none_collect_gregset (const struct regset *regset,
			  const struct regcache *regcache,
			  int regnum, void *gregs_buf, size_t len)
{
  gdb_byte *gregs = (gdb_byte *) gregs_buf;

  for (int regno = ARM_A1_REGNUM; regno < ARM_PC_REGNUM; regno++)
    if (regnum == -1 || regnum == regno)
      regcache->raw_collect (regno,
			     gregs + ARM_INT_REGISTER_SIZE * regno);

  if (regnum == ARM_PS_REGNUM || regnum == -1)
    {
      if (arm_apcs_32)
	regcache->raw_collect (ARM_PS_REGNUM,
			       gregs + ARM_INT_REGISTER_SIZE
			       * ARM_NONE_CPSR_GREGNUM);
      else
	regcache->raw_collect (ARM_PS_REGNUM,
			       gregs + ARM_INT_REGISTER_SIZE * ARM_PC_REGNUM);
    }

  if (regnum == ARM_PC_REGNUM || regnum == -1)
    regcache->raw_collect (ARM_PC_REGNUM,
			   gregs + ARM_INT_REGISTER_SIZE * ARM_PC_REGNUM);
}

/* Supply VFP registers from REGS_BUF into REGCACHE.  */

static void
arm_none_supply_vfp (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;

  if (regnum == ARM_FPSCR_REGNUM || regnum == -1)
    regcache->raw_supply (ARM_FPSCR_REGNUM, regs + 32 * 8);

  for (int regno = ARM_D0_REGNUM; regno <= ARM_D31_REGNUM; regno++)
    if (regnum == -1 || regnum == regno)
      regcache->raw_supply (regno, regs + (regno - ARM_D0_REGNUM) * 8);
}

/* Collect VFP registers from REGCACHE into REGS_BUF.  */

static void
arm_none_collect_vfp (const struct regset *regset,
		      const struct regcache *regcache,
		      int regnum, void *regs_buf, size_t len)
{
  gdb_byte *regs = (gdb_byte *) regs_buf;

  if (regnum == ARM_FPSCR_REGNUM || regnum == -1)
    regcache->raw_collect (ARM_FPSCR_REGNUM, regs + 32 * 8);

  for (int regno = ARM_D0_REGNUM; regno <= ARM_D31_REGNUM; regno++)
    if (regnum == -1 || regnum == regno)
      regcache->raw_collect (regno, regs + (regno - ARM_D0_REGNUM) * 8);
}

/* The general purpose register set.  */

static const struct regset arm_none_gregset =
  {
    nullptr, arm_none_supply_gregset, arm_none_collect_gregset
  };

/* The VFP register set.  */

static const struct regset arm_none_vfpregset =
  {
    nullptr, arm_none_supply_vfp, arm_none_collect_vfp
  };

/* Iterate over core file register note sections.  */

static void
arm_none_iterate_over_regset_sections (struct gdbarch *gdbarch,
				       iterate_over_regset_sections_cb *cb,
				       void *cb_data,
				       const struct regcache *regcache)
{
  arm_gdbarch_tdep *tdep = gdbarch_tdep<arm_gdbarch_tdep> (gdbarch);

  cb (".reg", ARM_NONE_SIZEOF_GREGSET, ARM_NONE_SIZEOF_GREGSET,
      &arm_none_gregset, nullptr, cb_data);

  if (tdep->vfp_register_count > 0)
    cb (".reg-arm-vfp", ARM_NONE_SIZEOF_VFP, ARM_NONE_SIZEOF_VFP,
	&arm_none_vfpregset, "VFP floating-point", cb_data);
}

/* Initialize ARM bare-metal ABI info.  */

static void
arm_none_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
#ifdef HAVE_ELF
  elf_none_init_abi (gdbarch);
#endif

  /* Iterate over registers for reading and writing bare metal ARM core
     files.  */
  set_gdbarch_iterate_over_regset_sections
    (gdbarch, arm_none_iterate_over_regset_sections);
}

/* Initialize ARM bare-metal target support.  */

void _initialize_arm_none_tdep ();
void
_initialize_arm_none_tdep ()
{
  gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_NONE,
			  arm_none_init_abi);
}
