This commit was generated by cvs2svn to track changes on a CVS vendor
[external/binutils.git] / gdb / sparc64nbsd-nat.c
1 /* Native-dependent code for UltraSPARC systems running NetBSD.
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 "inferior.h"
24 #include "regcache.h"
25
26 #include "sparcnbsd-tdep.h"
27
28 #include <sys/types.h>
29 #include <sys/ptrace.h>
30 #include <machine/reg.h>
31
32 /* NOTE: We don't bother with any of the deferred_store nonsense; it
33    makes things a lot more complicated than they need to be.  */
34
35 /* Determine if PT_GETREGS fetches this register.  */
36 static int
37 getregs_supplies (int regno)
38 {
39   /* FIXME: PS_REGNUM for 32-bit code.  */
40   return (regno == TSTATE_REGNUM
41           || regno == PC_REGNUM
42           || regno == NPC_REGNUM
43           || regno == Y_REGNUM
44           || (regno >= G0_REGNUM && regno <= G7_REGNUM)
45           || (regno >= O0_REGNUM && regno <= O7_REGNUM)
46           /* stack regs (handled by sparcnbsd_supply_reg)  */
47           || (regno >= L0_REGNUM && regno <= I7_REGNUM));
48 }
49
50 /* Determine if PT_GETFPREGS fetches this register.  */
51 static int
52 getfpregs_supplies (int regno)
53 {
54   return ((regno >= FP0_REGNUM && regno <= (FP0_REGNUM + 47))
55           || regno == FPS_REGNUM);
56 }
57
58 void
59 fetch_inferior_registers (int regno)
60 {
61   /* We don't use deferred stores.  */
62   if (deferred_stores)
63     internal_error (__FILE__, __LINE__,
64                     "fetch_inferior_registers: deferred stores pending");
65
66   if (regno == -1 || getregs_supplies (regno))
67     {
68       union {
69         struct reg32 regs32;
70         struct reg64 regs64;
71       } regs;
72
73       if (ptrace (PT_GETREGS, PIDGET (inferior_ptid),
74                   (PTRACE_ARG3_TYPE) &regs, 0) == -1)
75         perror_with_name ("Couldn't get registers");
76
77       if (gdbarch_ptr_bit (current_gdbarch) == 32)
78         sparcnbsd_supply_reg32 ((char *) &regs.regs32, regno);
79       else
80         sparcnbsd_supply_reg64 ((char *) &regs.regs64, regno);
81       if (regno != -1)
82         return;
83     }
84
85   if (regno == -1 || getfpregs_supplies (regno))
86     {
87       union {
88         struct fpreg32 fpregs32;
89         struct fpreg64 fpregs64;
90       } fpregs;
91
92       if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
93                   (PTRACE_ARG3_TYPE) &fpregs, 0) == -1)
94         perror_with_name ("Couldn't get floating point registers");
95
96       if (gdbarch_ptr_bit (current_gdbarch) == 32)
97         sparcnbsd_supply_fpreg32 ((char *) &fpregs.fpregs32, regno);
98       else
99         sparcnbsd_supply_fpreg64 ((char *) &fpregs.fpregs64, regno);
100       if (regno != -1)
101         return;
102     }
103 }
104
105 void
106 store_inferior_registers (int regno)
107 {
108   /* We don't use deferred stores.  */
109   if (deferred_stores)
110     internal_error (__FILE__, __LINE__,
111                     "store_inferior_registers: deferred stores pending");
112
113   if (regno == -1 || getregs_supplies (regno))
114     {
115       union {
116         struct reg32 regs32;
117         struct reg64 regs64;
118       } regs;
119
120       if (ptrace (PT_GETREGS, PIDGET (inferior_ptid),
121                   (PTRACE_ARG3_TYPE) &regs, 0) == -1)
122         perror_with_name ("Couldn't get registers");
123
124       if (gdbarch_ptr_bit (current_gdbarch) == 32)
125         sparcnbsd_fill_reg32 ((char *) &regs.regs32, regno);
126       else
127         sparcnbsd_fill_reg64 ((char *) &regs.regs64, regno);
128
129       if (ptrace (PT_SETREGS, PIDGET (inferior_ptid),
130                   (PTRACE_ARG3_TYPE) &regs, 0) == -1)
131         perror_with_name ("Couldn't write registers");
132
133       /* Deal with the stack regs.  */
134       if (regno == -1 || regno == SP_REGNUM
135           || (regno >= L0_REGNUM && regno <= I7_REGNUM))
136         {
137           CORE_ADDR sp = read_register (SP_REGNUM);
138           int i;
139           char buf[8];
140
141           if (sp & 1)
142             {
143               /* Registers are 64-bit.  */
144               sp += 2047;
145
146               for (i = L0_REGNUM; i <= I7_REGNUM; i++)
147                 {
148                   if (regno == -1 || regno == SP_REGNUM || regno == i)
149                     {
150                       regcache_collect (i, buf);
151                       target_write_memory (sp + ((i - L0_REGNUM) * 8),
152                                            buf, sizeof (buf));
153                     }
154                 }
155             }
156           else
157             {
158               /* Registers are 32-bit.  Toss any sign-extension of the stack
159                  pointer.
160
161                  FIXME: We don't currently handle 32-bit code in a binary
162                  that indicated LP64.  Do we have to care about that?  */
163               if (gdbarch_ptr_bit (current_gdbarch) != 32)
164                 internal_error
165                     (__FILE__, __LINE__,
166                     "store_inferior_registers: 32-bit code in 64-bit inferior");
167
168               sp &= 0xffffffffUL;
169               for (i = L0_REGNUM; i <= I7_REGNUM; i++)
170                 {
171                   if (regno == -1 || regno == SP_REGNUM || regno == i)
172                     {
173                       regcache_collect (i, buf);
174                       target_write_memory (sp + ((i - L0_REGNUM) * 4), buf, 4);
175                     }
176                 }
177             }
178         }
179
180       if (regno != -1)
181         return;
182     }
183
184   if (regno == -1 || getfpregs_supplies (regno))
185     {
186       union {
187         struct fpreg32 fpregs32;
188         struct fpreg64 fpregs64;
189       } fpregs;
190
191       if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
192                   (PTRACE_ARG3_TYPE) &fpregs, 0) == -1)
193         perror_with_name ("Couldn't get floating point registers");
194
195       if (gdbarch_ptr_bit (current_gdbarch) == 32)
196         sparcnbsd_fill_fpreg32 ((char *) &fpregs.fpregs32, regno);
197       else
198         sparcnbsd_fill_fpreg64 ((char *) &fpregs.fpregs64, regno);
199       
200       if (ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
201                   (PTRACE_ARG3_TYPE) &fpregs, 0) == -1)
202         perror_with_name ("Couldn't write floating point registers");
203
204       if (regno != -1)
205         return;
206     }
207 }