/* Target-dependent code for Motorola 68000 BSD's.

   Copyright (C) 2004-2015 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 "arch-utils.h"
#include "frame.h"
#include "osabi.h"
#include "regcache.h"
#include "regset.h"
#include "trad-frame.h"
#include "tramp-frame.h"
#include "gdbtypes.h"

#include "m68k-tdep.h"
#include "solib-svr4.h"

/* Core file support.  */

/* Sizeof `struct reg' in <machine/reg.h>.  */
#define M68KBSD_SIZEOF_GREGS	(18 * 4)

/* Sizeof `struct fpreg' in <machine/reg.h.  */
#define M68KBSD_SIZEOF_FPREGS	(((8 * 3) + 3) * 4)

int
m68kbsd_fpreg_offset (struct gdbarch *gdbarch, int regnum)
{
  int fp_len = TYPE_LENGTH (gdbarch_register_type (gdbarch, regnum));
  
  if (regnum >= M68K_FPC_REGNUM)
    return 8 * fp_len + (regnum - M68K_FPC_REGNUM) * 4;

  return (regnum - M68K_FP0_REGNUM) * fp_len;
}

/* 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
m68kbsd_supply_fpregset (const struct regset *regset,
			 struct regcache *regcache,
			 int regnum, const void *fpregs, size_t len)
{
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
  const gdb_byte *regs = fpregs;
  int i;

  gdb_assert (len >= M68KBSD_SIZEOF_FPREGS);

  for (i = M68K_FP0_REGNUM; i <= M68K_PC_REGNUM; i++)
    {
      if (regnum == i || regnum == -1)
	regcache_raw_supply (regcache, i,
			     regs + m68kbsd_fpreg_offset (gdbarch, 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.  */

static void
m68kbsd_supply_gregset (const struct regset *regset,
			struct regcache *regcache,
			int regnum, const void *gregs, size_t len)
{
  const gdb_byte *regs = gregs;
  int i;

  gdb_assert (len >= M68KBSD_SIZEOF_GREGS);

  for (i = M68K_D0_REGNUM; i <= M68K_PC_REGNUM; i++)
    {
      if (regnum == i || regnum == -1)
	regcache_raw_supply (regcache, i, regs + i * 4);
    }

  if (len >= M68KBSD_SIZEOF_GREGS + M68KBSD_SIZEOF_FPREGS)
    {
      regs += M68KBSD_SIZEOF_GREGS;
      len -= M68KBSD_SIZEOF_GREGS;
      m68kbsd_supply_fpregset (regset, regcache, regnum, regs, len);
    }
}

/* Motorola 68000 register sets.  */

static const struct regset m68kbsd_gregset =
{
  NULL,
  m68kbsd_supply_gregset,
  NULL,
  REGSET_VARIABLE_SIZE
};

static const struct regset m68kbsd_fpregset =
{
  NULL,
  m68kbsd_supply_fpregset
};

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

static void
m68kbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
				      iterate_over_regset_sections_cb *cb,
				      void *cb_data,
				      const struct regcache *regcache)
{
  cb (".reg", M68KBSD_SIZEOF_GREGS, &m68kbsd_gregset, NULL, cb_data);
  cb (".reg2", M68KBSD_SIZEOF_FPREGS, &m68kbsd_fpregset, NULL, cb_data);
}


/* Signal trampolines.  */

static void
m68kobsd_sigtramp_cache_init (const struct tramp_frame *self,
			      struct frame_info *this_frame,
			      struct trad_frame_cache *this_cache,
			      CORE_ADDR func)
{
  CORE_ADDR addr, base, pc;
  int regnum;

  base = get_frame_register_unsigned (this_frame, M68K_SP_REGNUM);

  /* The 'addql #4,%sp' instruction at offset 8 adjusts the stack
     pointer.  Adjust the frame base accordingly.  */
  pc = get_frame_register_unsigned (this_frame, M68K_PC_REGNUM);
  if ((pc - func) > 8)
    base -= 4;

  /* Get frame pointer, stack pointer, program counter and processor
     state from `struct sigcontext'.  */
  addr = get_frame_memory_unsigned (this_frame, base + 8, 4);
  trad_frame_set_reg_addr (this_cache, M68K_FP_REGNUM, addr + 8);
  trad_frame_set_reg_addr (this_cache, M68K_SP_REGNUM, addr + 12);
  trad_frame_set_reg_addr (this_cache, M68K_PC_REGNUM, addr + 20);
  trad_frame_set_reg_addr (this_cache, M68K_PS_REGNUM, addr + 24);

  /* The sc_ap member of `struct sigcontext' points to additional
     hardware state.  Here we find the missing registers.  */
  addr = get_frame_memory_unsigned (this_frame, addr + 16, 4) + 4;
  for (regnum = M68K_D0_REGNUM; regnum < M68K_FP_REGNUM; regnum++, addr += 4)
    trad_frame_set_reg_addr (this_cache, regnum, addr);

  /* Construct the frame ID using the function start.  */
  trad_frame_set_id (this_cache, frame_id_build (base, func));
}

static const struct tramp_frame m68kobsd_sigtramp = {
  SIGTRAMP_FRAME,
  2,
  {
    { 0x206f, -1 }, { 0x000c, -1},	/* moveal %sp@(12),%a0 */
    { 0x4e90, -1 },			/* jsr %a0@ */
    { 0x588f, -1 },			/* addql #4,%sp */
    { 0x4e41, -1 },			/* trap #1 */
    { 0x2f40, -1 }, { 0x0004, -1 },	/* moveal %d0,%sp@(4) */
    { 0x7001, -1 },			/* moveq #SYS_exit,%d0 */
    { 0x4e40, -1 },			/* trap #0 */
    { TRAMP_SENTINEL_INSN, -1 }
  },
  m68kobsd_sigtramp_cache_init
};


static void
m68kbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);

  tdep->jb_pc = 5;
  tdep->jb_elt_size = 4;

  set_gdbarch_decr_pc_after_break (gdbarch, 2);

  set_gdbarch_iterate_over_regset_sections
    (gdbarch, m68kbsd_iterate_over_regset_sections);
}

/* OpenBSD and NetBSD a.out.  */

static void
m68kbsd_aout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);

  m68kbsd_init_abi (info, gdbarch);

  tdep->struct_return = reg_struct_return;

  tramp_frame_prepend_unwinder (gdbarch, &m68kobsd_sigtramp);
}

/* NetBSD ELF.  */

static void
m68kbsd_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);

  m68kbsd_init_abi (info, gdbarch);

  /* NetBSD ELF uses the SVR4 ABI.  */
  m68k_svr4_init_abi (info, gdbarch);
  tdep->struct_return = pcc_struct_return;

  /* NetBSD ELF uses SVR4-style shared libraries.  */
  set_solib_svr4_fetch_link_map_offsets
    (gdbarch, svr4_ilp32_fetch_link_map_offsets);
}


static enum gdb_osabi
m68kbsd_aout_osabi_sniffer (bfd *abfd)
{
  if (strcmp (bfd_get_target (abfd), "a.out-m68k-netbsd") == 0
      || strcmp (bfd_get_target (abfd), "a.out-m68k4k-netbsd") == 0)
    return GDB_OSABI_NETBSD_AOUT;

  return GDB_OSABI_UNKNOWN;
}

static enum gdb_osabi
m68kbsd_core_osabi_sniffer (bfd *abfd)
{
  if (strcmp (bfd_get_target (abfd), "netbsd-core") == 0)
    return GDB_OSABI_NETBSD_AOUT;

  return GDB_OSABI_UNKNOWN;
}


/* Provide a prototype to silence -Wmissing-prototypes.  */
void _initialize_m68kbsd_tdep (void);

void
_initialize_m68kbsd_tdep (void)
{
  gdbarch_register_osabi_sniffer (bfd_arch_m68k, bfd_target_aout_flavour,
				  m68kbsd_aout_osabi_sniffer);

  /* BFD doesn't set a flavour for NetBSD style a.out core files.  */
  gdbarch_register_osabi_sniffer (bfd_arch_m68k, bfd_target_unknown_flavour,
				  m68kbsd_core_osabi_sniffer);

  gdbarch_register_osabi (bfd_arch_m68k, 0, GDB_OSABI_NETBSD_AOUT,
			  m68kbsd_aout_init_abi);
  gdbarch_register_osabi (bfd_arch_m68k, 0, GDB_OSABI_NETBSD_ELF,
			  m68kbsd_elf_init_abi);
}
