/* Native-dependent code for NetBSD/hppa.

   Copyright (C) 2008-2020 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 "defs.h"
#include "inferior.h"
#include "regcache.h"

#include <sys/types.h>
#include <sys/ptrace.h>
#include <machine/reg.h>

#include "hppa-tdep.h"
#include "inf-ptrace.h"

#include "netbsd-nat.h"

class hppa_nbsd_nat_target final : public nbsd_nat_target
{
  void fetch_registers (struct regcache *, int) override;
  void store_registers (struct regcache *, int) override;
};

static hppa_nbsd_nat_target the_hppa_nbsd_nat_target;

static int
hppanbsd_gregset_supplies_p (int regnum)
{
  return ((regnum >= HPPA_R0_REGNUM && regnum <= HPPA_R31_REGNUM) ||
          (regnum >= HPPA_SAR_REGNUM && regnum <= HPPA_PCSQ_TAIL_REGNUM) ||
          regnum == HPPA_IPSW_REGNUM ||
	  (regnum >= HPPA_SR4_REGNUM && regnum <= HPPA_SR4_REGNUM + 5));
}

static int
hppanbsd_fpregset_supplies_p (int regnum)
{
  return (regnum >= HPPA_FP0_REGNUM && regnum <= HPPA_FP31R_REGNUM);
}

/* Supply the general-purpose registers stored in GREGS to REGCACHE.  */

static void
hppanbsd_supply_gregset (struct regcache *regcache, const void *gregs)
{
  const char *regs = gregs;
  const int *r = gregs;
  int regnum;

  for (regnum = HPPA_R1_REGNUM; regnum <= HPPA_R31_REGNUM; regnum++)
    regcache->raw_supply (regnum, regs + regnum * 4);

  regcache->raw_supply (HPPA_SAR_REGNUM, regs + 32 * 4);
  regcache->raw_supply (HPPA_PCSQ_HEAD_REGNUM, regs + 33 * 4);
  regcache->raw_supply (HPPA_PCSQ_TAIL_REGNUM, regs + 34 * 4);
  regcache->raw_supply (HPPA_PCOQ_HEAD_REGNUM, regs + 35 * 4);
  regcache->raw_supply (HPPA_PCOQ_TAIL_REGNUM, regs + 36 * 4);
  regcache->raw_supply (HPPA_IPSW_REGNUM, regs);
  regcache->raw_supply (HPPA_SR4_REGNUM, regs + 41 * 4);
  regcache->raw_supply (HPPA_SR4_REGNUM + 1, regs + 37 * 4);
  regcache->raw_supply (HPPA_SR4_REGNUM + 2, regs + 38 * 4);
  regcache->raw_supply (HPPA_SR4_REGNUM + 3, regs + 39 * 4);
  regcache->raw_supply (HPPA_SR4_REGNUM + 4, regs + 40 * 4);
}

/* Supply the floating-point registers stored in FPREGS to REGCACHE.  */

static void
hppanbsd_supply_fpregset (struct regcache *regcache, const void *fpregs)
{
  const char *regs = fpregs;
  int regnum;

  for (regnum = HPPA_FP0_REGNUM; regnum <= HPPA_FP31R_REGNUM;
       regnum += 2, regs += 8)
    {
      regcache->raw_supply (regnum, regs);
      regcache->raw_supply (regnum + 1, regs + 4);
    }
}

/* Collect the general-purpose registers from REGCACHE and store them
   in GREGS.  */

static void
hppanbsd_collect_gregset (const struct regcache *regcache,
			  void *gregs, int regnum)
{
  char *regs = gregs;
  int *r = gregs;
  int i;

  for (i = HPPA_R1_REGNUM; i <= HPPA_R31_REGNUM; i++)
    {
      if (regnum == -1 || regnum == i)
	regcache->raw_collect (i, regs + i * 4);
    }

  if (regnum == -1 || regnum == HPPA_IPSW_REGNUM)
    regcache->raw_collect (HPPA_IPSW_REGNUM, regs);
  if (regnum == -1 || regnum == HPPA_PCOQ_HEAD_REGNUM)
    regcache->raw_collect (HPPA_PCOQ_HEAD_REGNUM, regs + 35 * 4);
  if (regnum == -1 || regnum == HPPA_PCOQ_TAIL_REGNUM)
    regcache->raw_collect (HPPA_PCOQ_TAIL_REGNUM, regs + 36 * 4);

  if (regnum == -1 || regnum == HPPA_SAR_REGNUM)
    regcache->raw_collect (HPPA_SAR_REGNUM, regs + 32 * 4);
  if (regnum == -1 || regnum == HPPA_PCSQ_HEAD_REGNUM)
    regcache->raw_collect (HPPA_PCSQ_HEAD_REGNUM, regs + 33 * 4);
  if (regnum == -1 || regnum == HPPA_PCSQ_TAIL_REGNUM)
    regcache->raw_collect (HPPA_PCSQ_TAIL_REGNUM, regs + 34 * 4);
  if (regnum == -1 || regnum == HPPA_PCOQ_HEAD_REGNUM)
    regcache->raw_collect (HPPA_PCOQ_HEAD_REGNUM, regs + 35 * 4);
  if (regnum == -1 || regnum == HPPA_PCOQ_TAIL_REGNUM)
    regcache->raw_collect (HPPA_PCOQ_TAIL_REGNUM, regs + 36 * 4);
  if (regnum == -1 || regnum == HPPA_IPSW_REGNUM)
    regcache->raw_collect (HPPA_IPSW_REGNUM, regs);
  if (regnum == -1 || regnum == HPPA_SR4_REGNUM)
    regcache->raw_collect (HPPA_SR4_REGNUM, regs + 41 * 4);
  if (regnum == -1 || regnum == HPPA_SR4_REGNUM + 1)
    regcache->raw_collect (HPPA_SR4_REGNUM + 1, regs + 37 * 4);
  if (regnum == -1 || regnum == HPPA_SR4_REGNUM + 2)
    regcache->raw_collect (HPPA_SR4_REGNUM + 2, regs + 38 * 4);
  if (regnum == -1 || regnum == HPPA_SR4_REGNUM + 3)
    regcache->raw_collect (HPPA_SR4_REGNUM + 3, regs + 39 * 4);
  if (regnum == -1 || regnum == HPPA_SR4_REGNUM + 4)
    regcache->raw_collect (HPPA_SR4_REGNUM + 4, regs + 40 * 4);
}

/* Collect the floating-point registers from REGCACHE and store them
   in FPREGS.  */

static void
hppanbsd_collect_fpregset (struct regcache *regcache,
			  void *fpregs, int regnum)
{
  char *regs = fpregs;
  int i;

  for (i = HPPA_FP0_REGNUM; i <= HPPA_FP31R_REGNUM; i += 2, regs += 8)
    {
      if (regnum == -1 || regnum == i || regnum == i + 1)
	{
	  regcache->raw_collect (i, regs);
	  regcache->raw_collect (i + 1, regs + 4);
	}
    }
}


/* Fetch register REGNUM from the inferior.  If REGNUM is -1, do this
   for all registers (including the floating-point registers).  */

void
hppa_nbsd_nat_target::fetch_registers (struct regcache *regcache, int regnum)

{
  pid_t pid = regcache->ptid ().pid ();
  int lwp = regcache->ptid ().lwp ();

  if (regnum == -1 || hppanbsd_gregset_supplies_p (regnum))
    {
      struct reg regs;

      if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) &regs, lwp) == -1)
	perror_with_name (_("Couldn't get registers"));

      hppanbsd_supply_gregset (regcache, &regs);
    }

  if (regnum == -1 || hppanbsd_fpregset_supplies_p (regnum))
    {
      struct fpreg fpregs;

      if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, lwp) == -1)
	perror_with_name (_("Couldn't get floating point status"));

      hppanbsd_supply_fpregset (regcache, &fpregs);
    }
}

/* Store register REGNUM back into the inferior.  If REGNUM is -1, do
   this for all registers (including the floating-point registers).  */

void
hppa_nbsd_nat_target::store_registers (struct regcache *regcache, int regnum)
{
  pid_t pid = regcache->ptid ().pid ();
  int lwp = regcache->ptid ().lwp ();

  if (regnum == -1 || hppanbsd_gregset_supplies_p (regnum))
    {
      struct reg regs;

      if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) &regs, lwp) == -1)
        perror_with_name (_("Couldn't get registers"));

      hppanbsd_collect_gregset (regcache, &regs, regnum);

      if (ptrace (PT_SETREGS, pid, (PTRACE_TYPE_ARG3) &regs, lwp) == -1)
        perror_with_name (_("Couldn't write registers"));
    }

  if (regnum == -1 || hppanbsd_fpregset_supplies_p (regnum))
    {
      struct fpreg fpregs;

      if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, lwp) == -1)
	perror_with_name (_("Couldn't get floating point status"));

      hppanbsd_collect_fpregset (regcache, &fpregs, regnum);

      if (ptrace (PT_SETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, lwp) == -1)
	perror_with_name (_("Couldn't write floating point status"));
    }
}

void _initialize_hppanbsd_nat ();
void
_initialize_hppanbsd_nat ()
{
  add_inf_child_target (&the_hppa_nbsd_nat_target);
}
