f25950740485c98a3096fc0dbe4dda2b1ac418df
[external/binutils.git] / gdb / sparcnbsd-tdep.c
1 /* Target-dependent code for SPARC systems running NetBSD.
2    Copyright 2002, 2003 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 "target.h"
26 #include "value.h"
27 #include "osabi.h"
28
29 #include "gdb_string.h"
30
31 #include "sparc-tdep.h"
32 #include "sparcnbsd-tdep.h"
33 #include "nbsd-tdep.h"
34
35 #include "solib-svr4.h"
36
37 #define REG32_OFFSET_PSR        (0 * 4)
38 #define REG32_OFFSET_PC         (1 * 4)
39 #define REG32_OFFSET_NPC        (2 * 4)
40 #define REG32_OFFSET_Y          (3 * 4)
41 #define REG32_OFFSET_GLOBAL     (4 * 4)
42 #define REG32_OFFSET_OUT        (12 * 4)
43
44 #define REG64_OFFSET_TSTATE     (0 * 8)
45 #define REG64_OFFSET_PC         (1 * 8)
46 #define REG64_OFFSET_NPC        (2 * 8)
47 #define REG64_OFFSET_Y          (3 * 8)
48 #define REG64_OFFSET_GLOBAL     (4 * 8)
49 #define REG64_OFFSET_OUT        (12 * 8)
50
51 void
52 sparcnbsd_supply_reg32 (char *regs, int regno)
53 {
54   int i;
55
56   if (regno == PS_REGNUM || regno == -1)
57     supply_register (PS_REGNUM, regs + REG32_OFFSET_PSR);
58
59   if (regno == PC_REGNUM || regno == -1)
60     supply_register (PC_REGNUM, regs + REG32_OFFSET_PC);
61
62   if (regno == DEPRECATED_NPC_REGNUM || regno == -1)
63     supply_register (DEPRECATED_NPC_REGNUM, regs + REG32_OFFSET_NPC);
64
65   if (regno == Y_REGNUM || regno == -1)
66     supply_register (Y_REGNUM, regs + REG32_OFFSET_Y);
67
68   if ((regno >= G0_REGNUM && regno <= G7_REGNUM) || regno == -1)
69     {
70       if (regno == G0_REGNUM || regno == -1)
71         supply_register (G0_REGNUM, NULL);      /* %g0 is always zero */
72       for (i = G1_REGNUM; i <= G7_REGNUM; i++)
73         {
74           if (regno == i || regno == -1)
75             supply_register (i, regs + REG32_OFFSET_GLOBAL +
76                              ((i - G0_REGNUM) * 4));
77         }
78     }
79
80   if ((regno >= O0_REGNUM && regno <= O7_REGNUM) || regno == -1)
81     {
82       for (i = O0_REGNUM; i <= O7_REGNUM; i++)
83         {
84           if (regno == i || regno == -1)
85             supply_register (i, regs + REG32_OFFSET_OUT +
86                              ((i - O0_REGNUM) * 4));
87         }
88     }
89
90   /* Inputs and Locals are stored onto the stack by by the kernel.  */
91   if ((regno >= L0_REGNUM && regno <= I7_REGNUM) || regno == -1)
92     {
93       CORE_ADDR sp = read_register (SP_REGNUM);
94       char buf[4];
95
96       for (i = L0_REGNUM; i <= I7_REGNUM; i++)
97         {
98           if (regno == i || regno == -1)
99             {
100               target_read_memory (sp + ((i - L0_REGNUM) * 4),
101                                   buf, sizeof (buf));
102               supply_register (i, buf);
103             }
104         }
105     }
106
107   /* FIXME: If we don't set these valid, read_register_bytes() rereads
108      all the regs every time it is called!  */
109   if (regno == WIM_REGNUM || regno == -1)
110     supply_register (WIM_REGNUM, NULL);
111   if (regno == TBR_REGNUM || regno == -1)
112     supply_register (TBR_REGNUM, NULL);
113   if (regno == CPS_REGNUM || regno == -1)
114     supply_register (CPS_REGNUM, NULL);
115 }
116
117 void
118 sparcnbsd_supply_reg64 (char *regs, int regno)
119 {
120   int i;
121   char buf[8];
122
123   if (regno == TSTATE_REGNUM || regno == -1)
124     supply_register (PS_REGNUM, regs + REG64_OFFSET_TSTATE);
125
126   if (regno == PC_REGNUM || regno == -1)
127     supply_register (PC_REGNUM, regs + REG64_OFFSET_PC);
128
129   if (regno == DEPRECATED_NPC_REGNUM || regno == -1)
130     supply_register (DEPRECATED_NPC_REGNUM, regs + REG64_OFFSET_NPC);
131
132   if (regno == Y_REGNUM || regno == -1)
133     {
134       memset (buf, 0, sizeof (buf));
135       memcpy (&buf[4], regs + REG64_OFFSET_Y, 4);
136       supply_register (Y_REGNUM, buf);
137     }
138
139   if ((regno >= G0_REGNUM && regno <= G7_REGNUM) || regno == -1)
140     {
141       if (regno == G0_REGNUM || regno == -1)
142         supply_register (G0_REGNUM, NULL);      /* %g0 is always zero */
143       for (i = G1_REGNUM; i <= G7_REGNUM; i++)
144         {
145           if (regno == i || regno == -1)
146             supply_register (i, regs + REG64_OFFSET_GLOBAL +
147                              ((i - G0_REGNUM) * 8));
148         }
149     }
150
151   if ((regno >= O0_REGNUM && regno <= O7_REGNUM) || regno == -1)
152     {
153       for (i = O0_REGNUM; i <= O7_REGNUM; i++)
154         {
155           if (regno == i || regno == -1)
156             supply_register (i, regs + REG64_OFFSET_OUT +
157                              ((i - O0_REGNUM) * 8));
158         }
159     }
160
161   /* Inputs and Locals are stored onto the stack by by the kernel.  */
162   if ((regno >= L0_REGNUM && regno <= I7_REGNUM) || regno == -1)
163     {
164       CORE_ADDR sp = read_register (SP_REGNUM);
165       char buf[8];
166
167       if (sp & 1)
168         {
169           /* Registers are 64-bit.  */
170           sp += 2047;
171
172           for (i = L0_REGNUM; i <= I7_REGNUM; i++)
173             {
174               if (regno == i || regno == -1)
175                 {
176                   target_read_memory (sp + ((i - L0_REGNUM) * 8),
177                                       buf, sizeof (buf));
178                   supply_register (i, buf);
179                 }
180             }
181         }
182       else
183         {
184           /* Registers are 32-bit.  Toss any sign-extension of the stack
185              pointer, clear out the top half of the temporary buffer, and
186              put the register value in the bottom half.  */
187
188           sp &= 0xffffffffUL;
189           memset (buf, 0, sizeof (buf));
190           for (i = L0_REGNUM; i <= I7_REGNUM; i++)
191             {
192               if (regno == i || regno == -1)
193                 {
194                   target_read_memory (sp + ((i - L0_REGNUM) * 4),
195                                       &buf[4], sizeof (buf));
196                   supply_register (i, buf);
197                 }
198             }
199         }
200     }
201
202   /* FIXME: If we don't set these valid, read_register_bytes() rereads
203      all the regs every time it is called!  */
204   if (regno == WIM_REGNUM || regno == -1)
205     supply_register (WIM_REGNUM, NULL);
206   if (regno == TBR_REGNUM || regno == -1)
207     supply_register (TBR_REGNUM, NULL);
208   if (regno == CPS_REGNUM || regno == -1)
209     supply_register (CPS_REGNUM, NULL);
210 }
211
212 void
213 sparcnbsd_fill_reg32 (char *regs, int regno)
214 {
215   int i;
216
217   if (regno == PS_REGNUM || regno == -1)
218     regcache_collect (PS_REGNUM, regs + REG32_OFFSET_PSR);
219
220   if (regno == PC_REGNUM || regno == -1)
221     regcache_collect (PC_REGNUM, regs + REG32_OFFSET_PC);
222
223   if (regno == DEPRECATED_NPC_REGNUM || regno == -1)
224     regcache_collect (DEPRECATED_NPC_REGNUM, regs + REG32_OFFSET_NPC);
225
226   if (regno == Y_REGNUM || regno == -1)
227     regcache_collect (Y_REGNUM, regs + REG32_OFFSET_Y);
228
229   if ((regno >= G0_REGNUM && regno <= G7_REGNUM) || regno == -1)
230     {
231       /* %g0 is always zero */
232       for (i = G1_REGNUM; i <= G7_REGNUM; i++)
233         {
234           if (regno == i || regno == -1)
235             regcache_collect (i, regs + REG32_OFFSET_GLOBAL +
236                               ((i - G0_REGNUM) * 4));
237         }
238     }
239
240   if ((regno >= O0_REGNUM && regno <= O7_REGNUM) || regno == -1)
241     {
242       for (i = O0_REGNUM; i <= O7_REGNUM; i++)
243         {
244           if (regno == i || regno == -1)
245             regcache_collect (i, regs + REG32_OFFSET_OUT +
246                               ((i - O0_REGNUM) * 4));
247         }
248     }
249
250   /* Responsibility for the stack regs is pushed off onto the caller.  */
251 }
252
253 void
254 sparcnbsd_fill_reg64 (char *regs, int regno)
255 {
256   int i;
257
258   if (regno == TSTATE_REGNUM || regno == -1)
259     regcache_collect (TSTATE_REGNUM, regs + REG64_OFFSET_TSTATE);
260
261   if (regno == PC_REGNUM || regno == -1)
262     regcache_collect (PC_REGNUM, regs + REG64_OFFSET_PC);
263
264   if (regno == DEPRECATED_NPC_REGNUM || regno == -1)
265     regcache_collect (DEPRECATED_NPC_REGNUM, regs + REG64_OFFSET_NPC);
266
267   if (regno == Y_REGNUM || regno == -1)
268     regcache_collect (Y_REGNUM, regs + REG64_OFFSET_Y);
269
270   if ((regno >= G0_REGNUM && regno <= G7_REGNUM) || regno == -1)
271     {
272       /* %g0 is always zero */
273       for (i = G1_REGNUM; i <= G7_REGNUM; i++)
274         {
275           if (regno == i || regno == -1)
276             regcache_collect (i, regs + REG64_OFFSET_GLOBAL +
277                               ((i - G0_REGNUM) * 4));
278         }
279     }
280
281   if ((regno >= O0_REGNUM && regno <= O7_REGNUM) || regno == -1)
282     {
283       for (i = O0_REGNUM; i <= O7_REGNUM; i++)
284         {
285           if (regno == i || regno == -1)
286             regcache_collect (i, regs + REG64_OFFSET_OUT +
287                               ((i - O0_REGNUM) * 4));
288         }
289     }
290
291   /* Responsibility for the stack regs is pushed off onto the caller.  */
292 }
293
294 void
295 sparcnbsd_supply_fpreg32 (char *fpregs, int regno)
296 {
297   int i;
298
299   for (i = 0; i <= 31; i++)
300     {
301       if (regno == (FP0_REGNUM + i) || regno == -1)
302         supply_register (FP0_REGNUM + i, fpregs + (i * 4));
303     }
304
305   if (regno == FPS_REGNUM || regno == -1)
306     supply_register (FPS_REGNUM, fpregs + (32 * 4));
307 }
308
309 void
310 sparcnbsd_supply_fpreg64 (char *fpregs, int regno)
311 {
312   int i;
313
314   for (i = 0; i <= 31; i++)
315     {
316       if (regno == (FP0_REGNUM + i) || regno == -1)
317         supply_register (FP0_REGNUM + i, fpregs + (i * 4));
318     }
319
320   for (; i <= 47; i++)
321     {
322       if (regno == (FP0_REGNUM + i) || regno == -1)
323         supply_register (FP0_REGNUM + i, fpregs + (32 * 4) + (i * 8));
324     }
325
326   if (regno == FPS_REGNUM || regno == -1)
327     supply_register (FPS_REGNUM, fpregs + (32 * 4) + (16 * 8));
328
329   /* XXX %gsr */
330 }
331
332 void
333 sparcnbsd_fill_fpreg32 (char *fpregs, int regno)
334 {
335   int i;
336
337   for (i = 0; i <= 31; i++)
338     {
339       if (regno == (FP0_REGNUM + i) || regno == -1)
340         regcache_collect (FP0_REGNUM + i, fpregs + (i * 4));
341     }
342
343   if (regno == FPS_REGNUM || regno == -1)
344     regcache_collect (FPS_REGNUM, fpregs + (32 * 4));
345 }
346
347 void
348 sparcnbsd_fill_fpreg64 (char *fpregs, int regno)
349 {
350   int i;
351
352   for (i = 0; i <= 31; i++)
353     {
354       if (regno == (FP0_REGNUM + i) || regno == -1)
355         regcache_collect (FP0_REGNUM + i, fpregs + (i * 4));
356     }
357
358   for (; i <= 47; i++)
359     {
360       if (regno == (FP0_REGNUM + i) || regno == -1)
361         regcache_collect (FP0_REGNUM + i, fpregs + (32 * 4) + (i * 8));
362     }
363
364   if (regno == FPS_REGNUM || regno == -1)
365     regcache_collect (FPS_REGNUM, fpregs + (32 * 4) + (16 * 8));
366
367   /* XXX %gsr */
368 }
369
370 /* Unlike other NetBSD implementations, the SPARC port historically used
371    .reg and .reg2 (see bfd/netbsd-core.c), and as such, we can share one
372    routine for a.out and ELF core files.  */
373 static void
374 fetch_core_registers (char *core_reg_sect, unsigned core_reg_size, int which,
375                       CORE_ADDR ignore)
376 {
377   int reg_size, fpreg_size;
378
379   if (gdbarch_ptr_bit (current_gdbarch) == 32)
380     {
381       reg_size = (20 * 4);
382       fpreg_size = (33 * 4);
383     }
384   else
385     {
386       reg_size = (20 * 8);
387       fpreg_size = (64 * 4)
388         + 8  /* fsr */
389         + 4  /* gsr */
390         + 4; /* pad */
391     }
392
393   switch (which)
394     {
395     case 0:  /* Integer registers */
396       if (core_reg_size != reg_size)
397         warning ("Wrong size register set in core file.");
398       else if (gdbarch_ptr_bit (current_gdbarch) == 32)
399         sparcnbsd_supply_reg32 (core_reg_sect, -1);
400       else
401         sparcnbsd_supply_reg64 (core_reg_sect, -1);
402       break;
403
404     case 2:  /* Floating pointer registers */
405       if (core_reg_size != fpreg_size)
406         warning ("Wrong size FP register set in core file.");
407       else if (gdbarch_ptr_bit (current_gdbarch) == 32)
408         sparcnbsd_supply_fpreg32 (core_reg_sect, -1);
409       else
410         sparcnbsd_supply_fpreg64 (core_reg_sect, -1);
411       break;
412
413     default:
414       /* Don't know what kind of register request this is; just ignore it.  */
415       break;
416     }
417 }
418
419 static struct core_fns sparcnbsd_core_fns =
420 {
421   bfd_target_unknown_flavour,           /* core_flavour */
422   default_check_format,                 /* check_format */
423   default_core_sniffer,                 /* core_sniffer */
424   fetch_core_registers,                 /* core_read_registers */
425   NULL
426 };
427
428 static struct core_fns sparcnbsd_elfcore_fns =
429 {
430   bfd_target_elf_flavour,               /* core_flavour */
431   default_check_format,                 /* check_format */
432   default_core_sniffer,                 /* core_sniffer */
433   fetch_core_registers,                 /* core_read_registers */
434   NULL
435 };
436
437 /* FIXME: Need PC_IN_SIGTRAMP() support, but NetBSD/sparc signal trampolines
438    aren't easily identified.  */
439
440 static int
441 sparcnbsd_get_longjmp_target_32 (CORE_ADDR *pc)
442 {
443   CORE_ADDR jb_addr;
444   char buf[4];
445
446   jb_addr = read_register (O0_REGNUM);
447
448   if (target_read_memory (jb_addr + 12, buf, sizeof (buf)))
449     return 0;
450
451   *pc = extract_unsigned_integer (buf, sizeof (buf));
452
453   return 1;
454 }
455
456 static int
457 sparcnbsd_get_longjmp_target_64 (CORE_ADDR *pc)
458 {
459   CORE_ADDR jb_addr;
460   char buf[8];
461
462   jb_addr = read_register (O0_REGNUM);
463
464   if (target_read_memory (jb_addr + 16, buf, sizeof (buf)))
465     return 0;
466
467   *pc = extract_unsigned_integer (buf, sizeof (buf));
468
469   return 1;
470 }
471
472 static int
473 sparcnbsd_aout_in_solib_call_trampoline (CORE_ADDR pc, char *name)
474 {
475   if (strcmp (name, "_DYNAMIC") == 0)
476     return 1;
477
478   return 0;
479 }
480
481 static void
482 sparcnbsd_init_abi_common (struct gdbarch_info info,
483                            struct gdbarch *gdbarch)
484 {
485   set_gdbarch_get_longjmp_target (gdbarch, gdbarch_ptr_bit (gdbarch) == 32 ?
486                                            sparcnbsd_get_longjmp_target_32 :
487                                            sparcnbsd_get_longjmp_target_64);
488 }
489
490 static void
491 sparcnbsd_init_abi_aout (struct gdbarch_info info,
492                          struct gdbarch *gdbarch)
493 {
494   sparcnbsd_init_abi_common (info, gdbarch);
495
496   set_gdbarch_in_solib_call_trampoline (gdbarch,
497                                      sparcnbsd_aout_in_solib_call_trampoline);
498 }
499
500 static void
501 sparcnbsd_init_abi_elf (struct gdbarch_info info,
502                         struct gdbarch *gdbarch)
503 {
504   sparcnbsd_init_abi_common (info, gdbarch);
505
506   set_gdbarch_pc_in_sigtramp (gdbarch, nbsd_pc_in_sigtramp);
507
508   set_solib_svr4_fetch_link_map_offsets (gdbarch,
509                                          gdbarch_ptr_bit (gdbarch) == 32 ?
510                                 nbsd_ilp32_solib_svr4_fetch_link_map_offsets :
511                                 nbsd_lp64_solib_svr4_fetch_link_map_offsets);
512 }
513
514 static enum gdb_osabi
515 sparcnbsd_aout_osabi_sniffer (bfd *abfd)
516 {
517   if (strcmp (bfd_get_target (abfd), "a.out-sparc-netbsd") == 0)
518     return GDB_OSABI_NETBSD_AOUT;
519
520   return GDB_OSABI_UNKNOWN;
521 }
522
523 void
524 _initialize_sparnbsd_tdep (void)
525 {
526   gdbarch_register_osabi_sniffer (bfd_arch_sparc, bfd_target_aout_flavour,
527                                   sparcnbsd_aout_osabi_sniffer);
528
529   gdbarch_register_osabi (bfd_arch_sparc, 0, GDB_OSABI_NETBSD_AOUT,
530                           sparcnbsd_init_abi_aout);
531   gdbarch_register_osabi (bfd_arch_sparc, 0, GDB_OSABI_NETBSD_ELF,
532                           sparcnbsd_init_abi_elf);
533
534   add_core_fns (&sparcnbsd_core_fns);
535   add_core_fns (&sparcnbsd_elfcore_fns);
536 }