166e63ce3Schristos /* Target-dependent code for GNU/Linux running on the Fujitsu FR-V,
266e63ce3Schristos    for GDB.
366e63ce3Schristos 
4*1424dfb3Schristos    Copyright (C) 2004-2020 Free Software Foundation, Inc.
566e63ce3Schristos 
666e63ce3Schristos    This file is part of GDB.
766e63ce3Schristos 
866e63ce3Schristos    This program is free software; you can redistribute it and/or modify
966e63ce3Schristos    it under the terms of the GNU General Public License as published by
1066e63ce3Schristos    the Free Software Foundation; either version 3 of the License, or
1166e63ce3Schristos    (at your option) any later version.
1266e63ce3Schristos 
1366e63ce3Schristos    This program is distributed in the hope that it will be useful,
1466e63ce3Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
1566e63ce3Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1666e63ce3Schristos    GNU General Public License for more details.
1766e63ce3Schristos 
1866e63ce3Schristos    You should have received a copy of the GNU General Public License
1966e63ce3Schristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
2066e63ce3Schristos 
2166e63ce3Schristos #include "defs.h"
2266e63ce3Schristos #include "gdbcore.h"
2366e63ce3Schristos #include "target.h"
2466e63ce3Schristos #include "frame.h"
2566e63ce3Schristos #include "osabi.h"
2666e63ce3Schristos #include "regcache.h"
2766e63ce3Schristos #include "elf-bfd.h"
2866e63ce3Schristos #include "elf/frv.h"
2966e63ce3Schristos #include "frv-tdep.h"
3066e63ce3Schristos #include "trad-frame.h"
3166e63ce3Schristos #include "frame-unwind.h"
3266e63ce3Schristos #include "regset.h"
3366e63ce3Schristos #include "linux-tdep.h"
34*1424dfb3Schristos #include "gdbarch.h"
3566e63ce3Schristos 
3666e63ce3Schristos /* Define the size (in bytes) of an FR-V instruction.  */
3766e63ce3Schristos static const int frv_instr_size = 4;
3866e63ce3Schristos 
3966e63ce3Schristos enum {
4066e63ce3Schristos   NORMAL_SIGTRAMP = 1,
4166e63ce3Schristos   RT_SIGTRAMP = 2
4266e63ce3Schristos };
4366e63ce3Schristos 
4466e63ce3Schristos static int
frv_linux_pc_in_sigtramp(struct gdbarch * gdbarch,CORE_ADDR pc,const char * name)4548596154Schristos frv_linux_pc_in_sigtramp (struct gdbarch *gdbarch, CORE_ADDR pc,
4648596154Schristos 			  const char *name)
4766e63ce3Schristos {
4866e63ce3Schristos   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
4948596154Schristos   gdb_byte buf[frv_instr_size];
5066e63ce3Schristos   LONGEST instr;
5166e63ce3Schristos   int retval = 0;
5266e63ce3Schristos 
5366e63ce3Schristos   if (target_read_memory (pc, buf, sizeof buf) != 0)
5466e63ce3Schristos     return 0;
5566e63ce3Schristos 
5666e63ce3Schristos   instr = extract_unsigned_integer (buf, sizeof buf, byte_order);
5766e63ce3Schristos 
5866e63ce3Schristos   if (instr == 0x8efc0077)	/* setlos #__NR_sigreturn, gr7 */
5966e63ce3Schristos     retval = NORMAL_SIGTRAMP;
6048596154Schristos   else if (instr == 0x8efc00ad)	/* setlos #__NR_rt_sigreturn, gr7 */
6166e63ce3Schristos     retval = RT_SIGTRAMP;
6266e63ce3Schristos   else
6366e63ce3Schristos     return 0;
6466e63ce3Schristos 
6566e63ce3Schristos   if (target_read_memory (pc + frv_instr_size, buf, sizeof buf) != 0)
6666e63ce3Schristos     return 0;
6766e63ce3Schristos   instr = extract_unsigned_integer (buf, sizeof buf, byte_order);
6866e63ce3Schristos   if (instr != 0xc0700000)	/* tira	gr0, 0 */
6966e63ce3Schristos     return 0;
7066e63ce3Schristos 
7166e63ce3Schristos   /* If we get this far, we'll return a non-zero value, either
7266e63ce3Schristos      NORMAL_SIGTRAMP (1) or RT_SIGTRAMP (2).  */
7366e63ce3Schristos   return retval;
7466e63ce3Schristos }
7566e63ce3Schristos 
7666e63ce3Schristos /* Given NEXT_FRAME, the "callee" frame of the sigtramp frame that we
7766e63ce3Schristos    wish to decode, and REGNO, one of the frv register numbers defined
7866e63ce3Schristos    in frv-tdep.h, return the address of the saved register (corresponding
7966e63ce3Schristos    to REGNO) in the sigtramp frame.  Return -1 if the register is not
8066e63ce3Schristos    found in the sigtramp frame.  The magic numbers in the code below
8166e63ce3Schristos    were computed by examining the following kernel structs:
8266e63ce3Schristos 
8366e63ce3Schristos    From arch/frv/kernel/signal.c:
8466e63ce3Schristos 
8566e63ce3Schristos       struct sigframe
8666e63ce3Schristos       {
8766e63ce3Schristos 	      void (*pretcode)(void);
8866e63ce3Schristos 	      int sig;
8966e63ce3Schristos 	      struct sigcontext sc;
9066e63ce3Schristos 	      unsigned long extramask[_NSIG_WORDS-1];
9166e63ce3Schristos 	      uint32_t retcode[2];
9266e63ce3Schristos       };
9366e63ce3Schristos 
9466e63ce3Schristos       struct rt_sigframe
9566e63ce3Schristos       {
9666e63ce3Schristos 	      void (*pretcode)(void);
9766e63ce3Schristos 	      int sig;
9866e63ce3Schristos 	      struct siginfo *pinfo;
9966e63ce3Schristos 	      void *puc;
10066e63ce3Schristos 	      struct siginfo info;
10166e63ce3Schristos 	      struct ucontext uc;
10266e63ce3Schristos 	      uint32_t retcode[2];
10366e63ce3Schristos       };
10466e63ce3Schristos 
10566e63ce3Schristos    From include/asm-frv/ucontext.h:
10666e63ce3Schristos 
10766e63ce3Schristos       struct ucontext {
10866e63ce3Schristos 	      unsigned long		uc_flags;
10966e63ce3Schristos 	      struct ucontext		*uc_link;
11066e63ce3Schristos 	      stack_t			uc_stack;
11166e63ce3Schristos 	      struct sigcontext	uc_mcontext;
11266e63ce3Schristos 	      sigset_t		uc_sigmask;
11366e63ce3Schristos       };
11466e63ce3Schristos 
11566e63ce3Schristos    From include/asm-frv/signal.h:
11666e63ce3Schristos 
11766e63ce3Schristos       typedef struct sigaltstack {
11866e63ce3Schristos 	      void *ss_sp;
11966e63ce3Schristos 	      int ss_flags;
12066e63ce3Schristos 	      size_t ss_size;
12166e63ce3Schristos       } stack_t;
12266e63ce3Schristos 
12366e63ce3Schristos    From include/asm-frv/sigcontext.h:
12466e63ce3Schristos 
12566e63ce3Schristos       struct sigcontext {
12666e63ce3Schristos 	      struct user_context	sc_context;
12766e63ce3Schristos 	      unsigned long		sc_oldmask;
12866e63ce3Schristos       } __attribute__((aligned(8)));
12966e63ce3Schristos 
13066e63ce3Schristos    From include/asm-frv/registers.h:
13166e63ce3Schristos       struct user_int_regs
13266e63ce3Schristos       {
13366e63ce3Schristos 	      unsigned long		psr;
13466e63ce3Schristos 	      unsigned long		isr;
13566e63ce3Schristos 	      unsigned long		ccr;
13666e63ce3Schristos 	      unsigned long		cccr;
13766e63ce3Schristos 	      unsigned long		lr;
13866e63ce3Schristos 	      unsigned long		lcr;
13966e63ce3Schristos 	      unsigned long		pc;
14066e63ce3Schristos 	      unsigned long		__status;
14166e63ce3Schristos 	      unsigned long		syscallno;
14266e63ce3Schristos 	      unsigned long		orig_gr8;
14366e63ce3Schristos 	      unsigned long		gner[2];
14466e63ce3Schristos 	      unsigned long long	iacc[1];
14566e63ce3Schristos 
14666e63ce3Schristos 	      union {
14766e63ce3Schristos 		      unsigned long	tbr;
14866e63ce3Schristos 		      unsigned long	gr[64];
14966e63ce3Schristos 	      };
15066e63ce3Schristos       };
15166e63ce3Schristos 
15266e63ce3Schristos       struct user_fpmedia_regs
15366e63ce3Schristos       {
15466e63ce3Schristos 	      unsigned long	fr[64];
15566e63ce3Schristos 	      unsigned long	fner[2];
15666e63ce3Schristos 	      unsigned long	msr[2];
15766e63ce3Schristos 	      unsigned long	acc[8];
15866e63ce3Schristos 	      unsigned char	accg[8];
15966e63ce3Schristos 	      unsigned long	fsr[1];
16066e63ce3Schristos       };
16166e63ce3Schristos 
16266e63ce3Schristos       struct user_context
16366e63ce3Schristos       {
16466e63ce3Schristos 	      struct user_int_regs		i;
16566e63ce3Schristos 	      struct user_fpmedia_regs	f;
16666e63ce3Schristos 
16766e63ce3Schristos 	      void *extension;
16866e63ce3Schristos       } __attribute__((aligned(8)));  */
16966e63ce3Schristos 
17066e63ce3Schristos static LONGEST
frv_linux_sigcontext_reg_addr(struct frame_info * this_frame,int regno,CORE_ADDR * sc_addr_cache_ptr)17166e63ce3Schristos frv_linux_sigcontext_reg_addr (struct frame_info *this_frame, int regno,
17266e63ce3Schristos                                CORE_ADDR *sc_addr_cache_ptr)
17366e63ce3Schristos {
17466e63ce3Schristos   struct gdbarch *gdbarch = get_frame_arch (this_frame);
17566e63ce3Schristos   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
17666e63ce3Schristos   CORE_ADDR sc_addr;
17766e63ce3Schristos 
17866e63ce3Schristos   if (sc_addr_cache_ptr && *sc_addr_cache_ptr)
17966e63ce3Schristos     {
18066e63ce3Schristos       sc_addr = *sc_addr_cache_ptr;
18166e63ce3Schristos     }
18266e63ce3Schristos   else
18366e63ce3Schristos     {
18466e63ce3Schristos       CORE_ADDR pc, sp;
18548596154Schristos       gdb_byte buf[4];
18666e63ce3Schristos       int tramp_type;
18766e63ce3Schristos 
18866e63ce3Schristos       pc = get_frame_pc (this_frame);
18966e63ce3Schristos       tramp_type = frv_linux_pc_in_sigtramp (gdbarch, pc, 0);
19066e63ce3Schristos 
19166e63ce3Schristos       get_frame_register (this_frame, sp_regnum, buf);
19266e63ce3Schristos       sp = extract_unsigned_integer (buf, sizeof buf, byte_order);
19366e63ce3Schristos 
19466e63ce3Schristos       if (tramp_type == NORMAL_SIGTRAMP)
19566e63ce3Schristos 	{
19666e63ce3Schristos 	  /* For a normal sigtramp frame, the sigcontext struct starts
19766e63ce3Schristos 	     at SP + 8.  */
19866e63ce3Schristos 	  sc_addr = sp + 8;
19966e63ce3Schristos 	}
20066e63ce3Schristos       else if (tramp_type == RT_SIGTRAMP)
20166e63ce3Schristos 	{
20266e63ce3Schristos 	  /* For a realtime sigtramp frame, SP + 12 contains a pointer
20366e63ce3Schristos  	     to a ucontext struct.  The ucontext struct contains a
20466e63ce3Schristos  	     sigcontext struct starting 24 bytes in.  (The offset of
20566e63ce3Schristos  	     uc_mcontext within struct ucontext is derived as follows:
20666e63ce3Schristos  	     stack_t is a 12-byte struct and struct sigcontext is
20766e63ce3Schristos  	     8-byte aligned.  This gives an offset of 8 + 12 + 4 (for
20866e63ce3Schristos  	     padding) = 24.)  */
20966e63ce3Schristos 	  if (target_read_memory (sp + 12, buf, sizeof buf) != 0)
21066e63ce3Schristos 	    {
21166e63ce3Schristos 	      warning (_("Can't read realtime sigtramp frame."));
21266e63ce3Schristos 	      return 0;
21366e63ce3Schristos 	    }
21466e63ce3Schristos 	  sc_addr = extract_unsigned_integer (buf, sizeof buf, byte_order);
21566e63ce3Schristos  	  sc_addr += 24;
21666e63ce3Schristos 	}
21766e63ce3Schristos       else
21866e63ce3Schristos 	internal_error (__FILE__, __LINE__, _("not a signal trampoline"));
21966e63ce3Schristos 
22066e63ce3Schristos       if (sc_addr_cache_ptr)
22166e63ce3Schristos 	*sc_addr_cache_ptr = sc_addr;
22266e63ce3Schristos     }
22366e63ce3Schristos 
22466e63ce3Schristos   switch (regno)
22566e63ce3Schristos     {
22666e63ce3Schristos     case psr_regnum :
22766e63ce3Schristos       return sc_addr + 0;
22866e63ce3Schristos     /* sc_addr + 4 has "isr", the Integer Status Register.  */
22966e63ce3Schristos     case ccr_regnum :
23066e63ce3Schristos       return sc_addr + 8;
23166e63ce3Schristos     case cccr_regnum :
23266e63ce3Schristos       return sc_addr + 12;
23366e63ce3Schristos     case lr_regnum :
23466e63ce3Schristos       return sc_addr + 16;
23566e63ce3Schristos     case lcr_regnum :
23666e63ce3Schristos       return sc_addr + 20;
23766e63ce3Schristos     case pc_regnum :
23866e63ce3Schristos       return sc_addr + 24;
23966e63ce3Schristos     /* sc_addr + 28 is __status, the exception status.
24066e63ce3Schristos        sc_addr + 32 is syscallno, the syscall number or -1.
24166e63ce3Schristos        sc_addr + 36 is orig_gr8, the original syscall arg #1.
24266e63ce3Schristos        sc_addr + 40 is gner[0].
24366e63ce3Schristos        sc_addr + 44 is gner[1].  */
24466e63ce3Schristos     case iacc0h_regnum :
24566e63ce3Schristos       return sc_addr + 48;
24666e63ce3Schristos     case iacc0l_regnum :
24766e63ce3Schristos       return sc_addr + 52;
24866e63ce3Schristos     default :
24966e63ce3Schristos       if (first_gpr_regnum <= regno && regno <= last_gpr_regnum)
25066e63ce3Schristos 	return sc_addr + 56 + 4 * (regno - first_gpr_regnum);
25166e63ce3Schristos       else if (first_fpr_regnum <= regno && regno <= last_fpr_regnum)
25266e63ce3Schristos 	return sc_addr + 312 + 4 * (regno - first_fpr_regnum);
25366e63ce3Schristos       else
25466e63ce3Schristos 	return -1;  /* not saved.  */
25566e63ce3Schristos     }
25666e63ce3Schristos }
25766e63ce3Schristos 
25866e63ce3Schristos /* Signal trampolines.  */
25966e63ce3Schristos 
26066e63ce3Schristos static struct trad_frame_cache *
frv_linux_sigtramp_frame_cache(struct frame_info * this_frame,void ** this_cache)26166e63ce3Schristos frv_linux_sigtramp_frame_cache (struct frame_info *this_frame,
26266e63ce3Schristos 				void **this_cache)
26366e63ce3Schristos {
26466e63ce3Schristos   struct gdbarch *gdbarch = get_frame_arch (this_frame);
26566e63ce3Schristos   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
26666e63ce3Schristos   struct trad_frame_cache *cache;
26766e63ce3Schristos   CORE_ADDR addr;
26848596154Schristos   gdb_byte buf[4];
26966e63ce3Schristos   int regnum;
27066e63ce3Schristos   CORE_ADDR sc_addr_cache_val = 0;
27166e63ce3Schristos   struct frame_id this_id;
27266e63ce3Schristos 
27366e63ce3Schristos   if (*this_cache)
274c03b94e9Schristos     return (struct trad_frame_cache *) *this_cache;
27566e63ce3Schristos 
27666e63ce3Schristos   cache = trad_frame_cache_zalloc (this_frame);
27766e63ce3Schristos 
27866e63ce3Schristos   /* FIXME: cagney/2004-05-01: This is is long standing broken code.
27966e63ce3Schristos      The frame ID's code address should be the start-address of the
28066e63ce3Schristos      signal trampoline and not the current PC within that
28166e63ce3Schristos      trampoline.  */
28266e63ce3Schristos   get_frame_register (this_frame, sp_regnum, buf);
28366e63ce3Schristos   addr = extract_unsigned_integer (buf, sizeof buf, byte_order);
28466e63ce3Schristos   this_id = frame_id_build (addr, get_frame_pc (this_frame));
28566e63ce3Schristos   trad_frame_set_id (cache, this_id);
28666e63ce3Schristos 
28766e63ce3Schristos   for (regnum = 0; regnum < frv_num_regs; regnum++)
28866e63ce3Schristos     {
28966e63ce3Schristos       LONGEST reg_addr = frv_linux_sigcontext_reg_addr (this_frame, regnum,
29066e63ce3Schristos 							&sc_addr_cache_val);
29166e63ce3Schristos       if (reg_addr != -1)
29266e63ce3Schristos 	trad_frame_set_reg_addr (cache, regnum, reg_addr);
29366e63ce3Schristos     }
29466e63ce3Schristos 
29566e63ce3Schristos   *this_cache = cache;
29666e63ce3Schristos   return cache;
29766e63ce3Schristos }
29866e63ce3Schristos 
29966e63ce3Schristos static void
frv_linux_sigtramp_frame_this_id(struct frame_info * this_frame,void ** this_cache,struct frame_id * this_id)30066e63ce3Schristos frv_linux_sigtramp_frame_this_id (struct frame_info *this_frame,
30166e63ce3Schristos 				  void **this_cache,
30266e63ce3Schristos 				  struct frame_id *this_id)
30366e63ce3Schristos {
30466e63ce3Schristos   struct trad_frame_cache *cache
30566e63ce3Schristos     = frv_linux_sigtramp_frame_cache (this_frame, this_cache);
30666e63ce3Schristos   trad_frame_get_id (cache, this_id);
30766e63ce3Schristos }
30866e63ce3Schristos 
30966e63ce3Schristos static struct value *
frv_linux_sigtramp_frame_prev_register(struct frame_info * this_frame,void ** this_cache,int regnum)31066e63ce3Schristos frv_linux_sigtramp_frame_prev_register (struct frame_info *this_frame,
31166e63ce3Schristos 					void **this_cache, int regnum)
31266e63ce3Schristos {
31366e63ce3Schristos   /* Make sure we've initialized the cache.  */
31466e63ce3Schristos   struct trad_frame_cache *cache
31566e63ce3Schristos     = frv_linux_sigtramp_frame_cache (this_frame, this_cache);
31666e63ce3Schristos   return trad_frame_get_register (cache, this_frame, regnum);
31766e63ce3Schristos }
31866e63ce3Schristos 
31966e63ce3Schristos static int
frv_linux_sigtramp_frame_sniffer(const struct frame_unwind * self,struct frame_info * this_frame,void ** this_cache)32066e63ce3Schristos frv_linux_sigtramp_frame_sniffer (const struct frame_unwind *self,
32166e63ce3Schristos 				  struct frame_info *this_frame,
32266e63ce3Schristos 				  void **this_cache)
32366e63ce3Schristos {
32466e63ce3Schristos   struct gdbarch *gdbarch = get_frame_arch (this_frame);
32566e63ce3Schristos   CORE_ADDR pc = get_frame_pc (this_frame);
32648596154Schristos   const char *name;
32766e63ce3Schristos 
32866e63ce3Schristos   find_pc_partial_function (pc, &name, NULL, NULL);
32966e63ce3Schristos   if (frv_linux_pc_in_sigtramp (gdbarch, pc, name))
33066e63ce3Schristos     return 1;
33166e63ce3Schristos 
33266e63ce3Schristos   return 0;
33366e63ce3Schristos }
33466e63ce3Schristos 
33566e63ce3Schristos static const struct frame_unwind frv_linux_sigtramp_frame_unwind =
33666e63ce3Schristos {
33766e63ce3Schristos   SIGTRAMP_FRAME,
33866e63ce3Schristos   default_frame_unwind_stop_reason,
33966e63ce3Schristos   frv_linux_sigtramp_frame_this_id,
34066e63ce3Schristos   frv_linux_sigtramp_frame_prev_register,
34166e63ce3Schristos   NULL,
34266e63ce3Schristos   frv_linux_sigtramp_frame_sniffer
34366e63ce3Schristos };
34466e63ce3Schristos 
34566e63ce3Schristos /* The FRV kernel defines ELF_NGREG as 46.  We add 2 in order to include
34666e63ce3Schristos    the loadmap addresses in the register set.  (See below for more info.)  */
34766e63ce3Schristos #define FRV_ELF_NGREG (46 + 2)
34866e63ce3Schristos typedef unsigned char frv_elf_greg_t[4];
34966e63ce3Schristos typedef struct { frv_elf_greg_t reg[FRV_ELF_NGREG]; } frv_elf_gregset_t;
35066e63ce3Schristos 
35166e63ce3Schristos typedef unsigned char frv_elf_fpreg_t[4];
35266e63ce3Schristos typedef struct
35366e63ce3Schristos {
35466e63ce3Schristos   frv_elf_fpreg_t fr[64];
35566e63ce3Schristos   frv_elf_fpreg_t fner[2];
35666e63ce3Schristos   frv_elf_fpreg_t msr[2];
35766e63ce3Schristos   frv_elf_fpreg_t acc[8];
35866e63ce3Schristos   unsigned char accg[8];
35966e63ce3Schristos   frv_elf_fpreg_t fsr[1];
36066e63ce3Schristos } frv_elf_fpregset_t;
36166e63ce3Schristos 
36226a53354Schristos /* Register maps.  */
36366e63ce3Schristos 
36426a53354Schristos static const struct regcache_map_entry frv_linux_gregmap[] =
36526a53354Schristos   {
36626a53354Schristos     { 1, psr_regnum, 4 },
36726a53354Schristos     { 1, REGCACHE_MAP_SKIP, 4 }, /* isr */
36826a53354Schristos     { 1, ccr_regnum, 4 },
36926a53354Schristos     { 1, cccr_regnum, 4 },
37026a53354Schristos     { 1, lr_regnum, 4 },
37126a53354Schristos     { 1, lcr_regnum, 4 },
37226a53354Schristos     { 1, pc_regnum, 4 },
37326a53354Schristos     { 1, REGCACHE_MAP_SKIP, 4 }, /* __status */
37426a53354Schristos     { 1, REGCACHE_MAP_SKIP, 4 }, /* syscallno */
37526a53354Schristos     { 1, REGCACHE_MAP_SKIP, 4 }, /* orig_gr8 */
37626a53354Schristos     { 1, gner0_regnum, 4 },
37726a53354Schristos     { 1, gner1_regnum, 4 },
37826a53354Schristos     { 1, REGCACHE_MAP_SKIP, 8 }, /* iacc0 */
37926a53354Schristos     { 1, tbr_regnum, 4 },
38026a53354Schristos     { 31, first_gpr_regnum + 1, 4 }, /* gr1 ... gr31 */
38166e63ce3Schristos 
38266e63ce3Schristos     /* Technically, the loadmap addresses are not part of `pr_reg' as
38326a53354Schristos        found in the elf_prstatus struct.  The fields which communicate
38426a53354Schristos        the loadmap address appear (by design) immediately after
38526a53354Schristos        `pr_reg' though, and the BFD function elf32_frv_grok_prstatus()
38626a53354Schristos        has been implemented to include these fields in the register
38726a53354Schristos        section that it extracts from the core file.  So, for our
38826a53354Schristos        purposes, they may be viewed as registers.  */
38966e63ce3Schristos 
39026a53354Schristos     { 1, fdpic_loadmap_exec_regnum, 4 },
39126a53354Schristos     { 1, fdpic_loadmap_interp_regnum, 4 },
39226a53354Schristos     { 0 }
39326a53354Schristos   };
39466e63ce3Schristos 
39526a53354Schristos static const struct regcache_map_entry frv_linux_fpregmap[] =
39626a53354Schristos   {
39726a53354Schristos     { 64, first_fpr_regnum, 4 }, /* fr0 ... fr63 */
39826a53354Schristos     { 1, fner0_regnum, 4 },
39926a53354Schristos     { 1, fner1_regnum, 4 },
40026a53354Schristos     { 1, msr0_regnum, 4 },
40126a53354Schristos     { 1, msr1_regnum, 4 },
40226a53354Schristos     { 8, acc0_regnum, 4 },	/* acc0 ... acc7 */
40326a53354Schristos     { 1, accg0123_regnum, 4 },
40426a53354Schristos     { 1, accg4567_regnum, 4 },
40526a53354Schristos     { 1, fsr0_regnum, 4 },
40626a53354Schristos     { 0 }
40726a53354Schristos   };
40866e63ce3Schristos 
40966e63ce3Schristos /* Unpack an frv_elf_gregset_t into GDB's register cache.  */
41066e63ce3Schristos 
41166e63ce3Schristos static void
frv_linux_supply_gregset(const struct regset * regset,struct regcache * regcache,int regnum,const void * gregs,size_t len)41266e63ce3Schristos frv_linux_supply_gregset (const struct regset *regset,
41366e63ce3Schristos                           struct regcache *regcache,
41466e63ce3Schristos 			  int regnum, const void *gregs, size_t len)
41566e63ce3Schristos {
41666e63ce3Schristos   int regi;
41766e63ce3Schristos 
41866e63ce3Schristos   /* gr0 always contains 0.  Also, the kernel passes the TBR value in
41966e63ce3Schristos      this slot.  */
42007163879Schristos   regcache->raw_supply_zeroed (first_gpr_regnum);
42166e63ce3Schristos 
42226a53354Schristos   /* Fill gr32, ..., gr63 with zeros. */
42326a53354Schristos   for (regi = first_gpr_regnum + 32; regi <= last_gpr_regnum; regi++)
42407163879Schristos     regcache->raw_supply_zeroed (regi);
42566e63ce3Schristos 
42626a53354Schristos   regcache_supply_regset (regset, regcache, regnum, gregs, len);
42766e63ce3Schristos }
42866e63ce3Schristos 
42966e63ce3Schristos /* FRV Linux kernel register sets.  */
43066e63ce3Schristos 
43126a53354Schristos static const struct regset frv_linux_gregset =
43266e63ce3Schristos {
43326a53354Schristos   frv_linux_gregmap,
43426a53354Schristos   frv_linux_supply_gregset, regcache_collect_regset
43566e63ce3Schristos };
43666e63ce3Schristos 
43726a53354Schristos static const struct regset frv_linux_fpregset =
43866e63ce3Schristos {
43926a53354Schristos   frv_linux_fpregmap,
44026a53354Schristos   regcache_supply_regset, regcache_collect_regset
44166e63ce3Schristos };
44266e63ce3Schristos 
44326a53354Schristos static void
frv_linux_iterate_over_regset_sections(struct gdbarch * gdbarch,iterate_over_regset_sections_cb * cb,void * cb_data,const struct regcache * regcache)44426a53354Schristos frv_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
44526a53354Schristos 					iterate_over_regset_sections_cb *cb,
44626a53354Schristos 					void *cb_data,
44726a53354Schristos 					const struct regcache *regcache)
44866e63ce3Schristos {
44907163879Schristos   cb (".reg", sizeof (frv_elf_gregset_t), sizeof (frv_elf_gregset_t),
45007163879Schristos       &frv_linux_gregset, NULL, cb_data);
45107163879Schristos   cb (".reg2", sizeof (frv_elf_fpregset_t), sizeof (frv_elf_fpregset_t),
45207163879Schristos       &frv_linux_fpregset, NULL, cb_data);
45366e63ce3Schristos }
45466e63ce3Schristos 
45566e63ce3Schristos 
45666e63ce3Schristos static void
frv_linux_init_abi(struct gdbarch_info info,struct gdbarch * gdbarch)45766e63ce3Schristos frv_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
45866e63ce3Schristos {
45966e63ce3Schristos   linux_init_abi (info, gdbarch);
46066e63ce3Schristos 
46166e63ce3Schristos   /* Set the sigtramp frame sniffer.  */
46266e63ce3Schristos   frame_unwind_append_unwinder (gdbarch, &frv_linux_sigtramp_frame_unwind);
46366e63ce3Schristos 
46426a53354Schristos   set_gdbarch_iterate_over_regset_sections
46526a53354Schristos     (gdbarch, frv_linux_iterate_over_regset_sections);
46666e63ce3Schristos }
46766e63ce3Schristos 
46866e63ce3Schristos static enum gdb_osabi
frv_linux_elf_osabi_sniffer(bfd * abfd)46966e63ce3Schristos frv_linux_elf_osabi_sniffer (bfd *abfd)
47066e63ce3Schristos {
47166e63ce3Schristos   int elf_flags;
47266e63ce3Schristos 
47366e63ce3Schristos   elf_flags = elf_elfheader (abfd)->e_flags;
47466e63ce3Schristos 
47566e63ce3Schristos   /* Assume GNU/Linux if using the FDPIC ABI.  If/when another OS shows
47666e63ce3Schristos      up that uses this ABI, we'll need to start using .note sections
47766e63ce3Schristos      or some such.  */
47866e63ce3Schristos   if (elf_flags & EF_FRV_FDPIC)
47966e63ce3Schristos     return GDB_OSABI_LINUX;
48066e63ce3Schristos   else
48166e63ce3Schristos     return GDB_OSABI_UNKNOWN;
48266e63ce3Schristos }
48366e63ce3Schristos 
484*1424dfb3Schristos void _initialize_frv_linux_tdep ();
48566e63ce3Schristos void
_initialize_frv_linux_tdep()486*1424dfb3Schristos _initialize_frv_linux_tdep ()
48766e63ce3Schristos {
48866e63ce3Schristos   gdbarch_register_osabi (bfd_arch_frv, 0, GDB_OSABI_LINUX,
48966e63ce3Schristos 			  frv_linux_init_abi);
49066e63ce3Schristos   gdbarch_register_osabi_sniffer (bfd_arch_frv,
49166e63ce3Schristos 				  bfd_target_elf_flavour,
49266e63ce3Schristos 				  frv_linux_elf_osabi_sniffer);
49366e63ce3Schristos }
494