d2f042a16a7801d94299f9f7489c7f502b440820
[external/binutils.git] / gdb / shnbsd-tdep.c
1 /* Target-dependent code for SuperH running NetBSD, for GDB.
2    Copyright 2002 Free Software Foundation, Inc.
3    Contributed by Wasabi Systems, Inc.
4
5    This file is part of GDB.
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 59 Temple Place - Suite 330,
20    Boston, MA 02111-1307, USA.  */
21
22 #include "defs.h"
23 #include "gdbcore.h"
24 #include "regcache.h"
25 #include "value.h"
26
27 #include "solib-svr4.h"
28
29 #include "nbsd-tdep.h"
30 #include "sh-tdep.h"
31 #include "shnbsd-tdep.h"
32
33 /* Convert an r0-r15 register number into an offset into a ptrace
34    register structure.  */
35 static const int regmap[] =
36 {
37   (20 * 4),     /* r0 */
38   (19 * 4),     /* r1 */
39   (18 * 4),     /* r2 */ 
40   (17 * 4),     /* r3 */ 
41   (16 * 4),     /* r4 */
42   (15 * 4),     /* r5 */
43   (14 * 4),     /* r6 */
44   (13 * 4),     /* r7 */
45   (12 * 4),     /* r8 */ 
46   (11 * 4),     /* r9 */
47   (10 * 4),     /* r10 */
48   ( 9 * 4),     /* r11 */
49   ( 8 * 4),     /* r12 */
50   ( 7 * 4),     /* r13 */
51   ( 6 * 4),     /* r14 */
52   ( 5 * 4),     /* r15 */
53 };
54
55 #define SIZEOF_STRUCT_REG (21 * 4)
56
57 void
58 shnbsd_supply_reg (char *regs, int regno)
59 {
60   int i;
61
62   if (regno == PC_REGNUM || regno == -1)
63     supply_register (PC_REGNUM, regs + (0 * 4));
64
65   if (regno == SR_REGNUM || regno == -1)
66     supply_register (SR_REGNUM, regs + (1 * 4));
67
68   if (regno == PR_REGNUM || regno == -1)
69     supply_register (PR_REGNUM, regs + (2 * 4));
70
71   if (regno == MACH_REGNUM || regno == -1)
72     supply_register (MACH_REGNUM, regs + (3 * 4));
73
74   if (regno == MACL_REGNUM || regno == -1)
75     supply_register (MACL_REGNUM, regs + (4 * 4));
76
77   if ((regno >= R0_REGNUM && regno <= (R0_REGNUM + 15)) || regno == -1)
78     {
79       for (i = R0_REGNUM; i <= (R0_REGNUM + 15); i++)
80         if (regno == i || regno == -1)
81           supply_register (i, regs + regmap[i - R0_REGNUM]);
82     }
83 }
84
85 void
86 shnbsd_fill_reg (char *regs, int regno)
87 {
88   int i;
89
90   if (regno == PC_REGNUM || regno == -1)
91     regcache_collect (PC_REGNUM, regs + (0 * 4));
92
93   if (regno == SR_REGNUM || regno == -1)
94     regcache_collect (SR_REGNUM, regs + (1 * 4));
95
96   if (regno == PR_REGNUM || regno == -1)
97     regcache_collect (PR_REGNUM, regs + (2 * 4));
98
99   if (regno == MACH_REGNUM || regno == -1)
100     regcache_collect (MACH_REGNUM, regs + (3 * 4));
101
102   if (regno == MACL_REGNUM || regno == -1)
103     regcache_collect (MACL_REGNUM, regs + (4 * 4));
104
105   if ((regno >= R0_REGNUM && regno <= (R0_REGNUM + 15)) || regno == -1)
106     {
107       for (i = R0_REGNUM; i <= (R0_REGNUM + 15); i++)
108         if (regno == i || regno == -1)
109           regcache_collect (i, regs + regmap[i - R0_REGNUM]);
110     }
111 }
112
113 static void
114 fetch_core_registers (char *core_reg_sect, unsigned core_reg_size,
115                       int which, CORE_ADDR ignore)
116 {
117   /* We get everything from the .reg section.  */
118   if (which != 0)
119     return;
120
121   if (core_reg_size < SIZEOF_STRUCT_REG)
122     {
123       warning ("Wrong size register set in core file.");
124       return;
125     }
126
127   /* Integer registers.  */
128   shnbsd_supply_reg (core_reg_sect, -1);
129 }
130
131 static void
132 fetch_elfcore_registers (char *core_reg_sect, unsigned core_reg_size,
133                          int which, CORE_ADDR ignore)
134 {
135   switch (which)
136     {
137     case 0:  /* Integer registers.  */
138       if (core_reg_size != SIZEOF_STRUCT_REG)
139         warning ("Wrong size register set in core file.");
140       else
141         shnbsd_supply_reg (core_reg_sect, -1);
142       break;
143
144     default:
145       /* Don't know what kind of register request this is; just ignore it.  */
146       break;
147     }
148 }
149
150 static struct core_fns shnbsd_core_fns =
151 {
152   bfd_target_unknown_flavour,           /* core_flavour */
153   default_check_format,                 /* check_format */
154   default_core_sniffer,                 /* core_sniffer */
155   fetch_core_registers,                 /* core_read_registers */
156   NULL                                  /* next */
157 };
158
159 static struct core_fns shnbsd_elfcore_fns =
160 {
161   bfd_target_elf_flavour,               /* core_flavour */
162   default_check_format,                 /* check_format */
163   default_core_sniffer,                 /* core_sniffer */
164   fetch_elfcore_registers,              /* core_read_registers */
165   NULL                                  /* next */
166 };
167
168 static int
169 shnbsd_pc_in_sigtramp (CORE_ADDR pc, char *func_name)
170 {
171   /* FIXME: Need to add support for kernel-provided signal trampolines.  */
172   return (nbsd_pc_in_sigtramp (pc, func_name));
173 }
174
175 static void
176 shnbsd_init_abi (struct gdbarch_info info,
177                   struct gdbarch *gdbarch)
178 {
179   set_gdbarch_pc_in_sigtramp (gdbarch, shnbsd_pc_in_sigtramp);
180
181   set_solib_svr4_fetch_link_map_offsets (gdbarch,
182                                 nbsd_ilp32_solib_svr4_fetch_link_map_offsets);
183 }
184
185 void
186 _initialize_shnbsd_tdep (void)
187 {
188   add_core_fns (&shnbsd_core_fns);
189   add_core_fns (&shnbsd_elfcore_fns);
190
191   gdbarch_register_osabi (bfd_arch_sh, 0, GDB_OSABI_NETBSD_ELF,
192                           shnbsd_init_abi);
193 }