]>
Commit | Line | Data |
---|---|---|
9abe5450 | 1 | /* PPC GNU/Linux native support. |
05f13b9c | 2 | Copyright 1988, 1989, 1991, 1992, 1994, 1996, 2000, 2001, 2002 |
b6ba6518 | 3 | Free Software Foundation, Inc. |
c877c8e6 KB |
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 | |
05f13b9c EZ |
19 | Foundation, Inc., 59 Temple Place - Suite 330, |
20 | Boston, MA 02111-1307, USA. */ | |
c877c8e6 KB |
21 | |
22 | #include "defs.h" | |
e162d11b | 23 | #include "gdb_string.h" |
c877c8e6 KB |
24 | #include "frame.h" |
25 | #include "inferior.h" | |
26 | #include "gdbcore.h" | |
4e052eda | 27 | #include "regcache.h" |
c877c8e6 KB |
28 | |
29 | #include <sys/types.h> | |
30 | #include <sys/param.h> | |
31 | #include <signal.h> | |
32 | #include <sys/user.h> | |
33 | #include <sys/ioctl.h> | |
34 | #include <sys/wait.h> | |
35 | #include <fcntl.h> | |
36 | #include <sys/procfs.h> | |
45229ea4 | 37 | #include <sys/ptrace.h> |
c877c8e6 | 38 | |
c60c0f5f MS |
39 | /* Prototypes for supply_gregset etc. */ |
40 | #include "gregset.h" | |
16333c4f | 41 | #include "ppc-tdep.h" |
c60c0f5f | 42 | |
45229ea4 EZ |
43 | #ifndef PT_READ_U |
44 | #define PT_READ_U PTRACE_PEEKUSR | |
45 | #endif | |
46 | #ifndef PT_WRITE_U | |
47 | #define PT_WRITE_U PTRACE_POKEUSR | |
48 | #endif | |
49 | ||
50 | /* Default the type of the ptrace transfer to int. */ | |
51 | #ifndef PTRACE_XFER_TYPE | |
52 | #define PTRACE_XFER_TYPE int | |
53 | #endif | |
54 | ||
9abe5450 EZ |
55 | /* Glibc's headers don't define PTRACE_GETVRREGS so we cannot use a |
56 | configure time check. Some older glibc's (for instance 2.2.1) | |
57 | don't have a specific powerpc version of ptrace.h, and fall back on | |
58 | a generic one. In such cases, sys/ptrace.h defines | |
59 | PTRACE_GETFPXREGS and PTRACE_SETFPXREGS to the same numbers that | |
60 | ppc kernel's asm/ptrace.h defines PTRACE_GETVRREGS and | |
61 | PTRACE_SETVRREGS to be. This also makes a configury check pretty | |
62 | much useless. */ | |
63 | ||
64 | /* These definitions should really come from the glibc header files, | |
65 | but Glibc doesn't know about the vrregs yet. */ | |
66 | #ifndef PTRACE_GETVRREGS | |
67 | #define PTRACE_GETVRREGS 18 | |
68 | #define PTRACE_SETVRREGS 19 | |
69 | #endif | |
70 | ||
71 | /* This oddity is because the Linux kernel defines elf_vrregset_t as | |
72 | an array of 33 16 bytes long elements. I.e. it leaves out vrsave. | |
73 | However the PTRACE_GETVRREGS and PTRACE_SETVRREGS requests return | |
74 | the vrsave as an extra 4 bytes at the end. I opted for creating a | |
75 | flat array of chars, so that it is easier to manipulate for gdb. | |
76 | ||
77 | There are 32 vector registers 16 bytes longs, plus a VSCR register | |
78 | which is only 4 bytes long, but is fetched as a 16 bytes | |
79 | quantity. Up to here we have the elf_vrregset_t structure. | |
80 | Appended to this there is space for the VRSAVE register: 4 bytes. | |
81 | Even though this vrsave register is not included in the regset | |
82 | typedef, it is handled by the ptrace requests. | |
83 | ||
84 | Note that GNU/Linux doesn't support little endian PPC hardware, | |
85 | therefore the offset at which the real value of the VSCR register | |
86 | is located will be always 12 bytes. | |
87 | ||
88 | The layout is like this (where x is the actual value of the vscr reg): */ | |
89 | ||
90 | /* *INDENT-OFF* */ | |
91 | /* | |
92 | |.|.|.|.|.....|.|.|.|.||.|.|.|x||.| | |
93 | <-------> <-------><-------><-> | |
94 | VR0 VR31 VSCR VRSAVE | |
95 | */ | |
96 | /* *INDENT-ON* */ | |
97 | ||
98 | #define SIZEOF_VRREGS 33*16+4 | |
99 | ||
100 | typedef char gdb_vrregset_t[SIZEOF_VRREGS]; | |
101 | ||
102 | /* For runtime check of ptrace support for VRREGS. */ | |
103 | int have_ptrace_getvrregs = 1; | |
104 | ||
c877c8e6 | 105 | int |
fba45db2 | 106 | kernel_u_size (void) |
c877c8e6 KB |
107 | { |
108 | return (sizeof (struct user)); | |
109 | } | |
110 | ||
16333c4f EZ |
111 | /* *INDENT-OFF* */ |
112 | /* registers layout, as presented by the ptrace interface: | |
113 | PT_R0, PT_R1, PT_R2, PT_R3, PT_R4, PT_R5, PT_R6, PT_R7, | |
114 | PT_R8, PT_R9, PT_R10, PT_R11, PT_R12, PT_R13, PT_R14, PT_R15, | |
115 | PT_R16, PT_R17, PT_R18, PT_R19, PT_R20, PT_R21, PT_R22, PT_R23, | |
116 | PT_R24, PT_R25, PT_R26, PT_R27, PT_R28, PT_R29, PT_R30, PT_R31, | |
117 | PT_FPR0, PT_FPR0 + 2, PT_FPR0 + 4, PT_FPR0 + 6, PT_FPR0 + 8, PT_FPR0 + 10, PT_FPR0 + 12, PT_FPR0 + 14, | |
118 | PT_FPR0 + 16, PT_FPR0 + 18, PT_FPR0 + 20, PT_FPR0 + 22, PT_FPR0 + 24, PT_FPR0 + 26, PT_FPR0 + 28, PT_FPR0 + 30, | |
119 | PT_FPR0 + 32, PT_FPR0 + 34, PT_FPR0 + 36, PT_FPR0 + 38, PT_FPR0 + 40, PT_FPR0 + 42, PT_FPR0 + 44, PT_FPR0 + 46, | |
120 | PT_FPR0 + 48, PT_FPR0 + 50, PT_FPR0 + 52, PT_FPR0 + 54, PT_FPR0 + 56, PT_FPR0 + 58, PT_FPR0 + 60, PT_FPR0 + 62, | |
121 | PT_NIP, PT_MSR, PT_CCR, PT_LNK, PT_CTR, PT_XER, PT_MQ */ | |
122 | /* *INDENT_ON * */ | |
c877c8e6 | 123 | |
45229ea4 EZ |
124 | static int |
125 | ppc_register_u_addr (int regno) | |
c877c8e6 | 126 | { |
16333c4f | 127 | int u_addr = -1; |
dc5cfeb6 | 128 | struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); |
16333c4f EZ |
129 | |
130 | /* General purpose registers occupy 1 slot each in the buffer */ | |
dc5cfeb6 | 131 | if (regno >= tdep->ppc_gp0_regnum && regno <= tdep->ppc_gplast_regnum ) |
45229ea4 | 132 | u_addr = ((PT_R0 + regno) * 4); |
16333c4f EZ |
133 | |
134 | /* Floating point regs: 2 slots each */ | |
135 | if (regno >= FP0_REGNUM && regno <= FPLAST_REGNUM) | |
45229ea4 | 136 | u_addr = ((PT_FPR0 + (regno - FP0_REGNUM) * 2) * 4); |
16333c4f EZ |
137 | |
138 | /* UISA special purpose registers: 1 slot each */ | |
139 | if (regno == PC_REGNUM) | |
45229ea4 | 140 | u_addr = PT_NIP * 4; |
dc5cfeb6 | 141 | if (regno == tdep->ppc_lr_regnum) |
45229ea4 | 142 | u_addr = PT_LNK * 4; |
dc5cfeb6 | 143 | if (regno == tdep->ppc_cr_regnum) |
45229ea4 | 144 | u_addr = PT_CCR * 4; |
dc5cfeb6 | 145 | if (regno == tdep->ppc_xer_regnum) |
45229ea4 | 146 | u_addr = PT_XER * 4; |
dc5cfeb6 | 147 | if (regno == tdep->ppc_ctr_regnum) |
45229ea4 | 148 | u_addr = PT_CTR * 4; |
dc5cfeb6 | 149 | if (regno == tdep->ppc_mq_regnum) |
45229ea4 | 150 | u_addr = PT_MQ * 4; |
dc5cfeb6 | 151 | if (regno == tdep->ppc_ps_regnum) |
45229ea4 | 152 | u_addr = PT_MSR * 4; |
e3f36dbd KB |
153 | if (regno == tdep->ppc_fpscr_regnum) |
154 | u_addr = PT_FPSCR * 4; | |
16333c4f EZ |
155 | |
156 | return u_addr; | |
c877c8e6 KB |
157 | } |
158 | ||
45229ea4 EZ |
159 | static int |
160 | ppc_ptrace_cannot_fetch_store_register (int regno) | |
161 | { | |
162 | return (ppc_register_u_addr (regno) == -1); | |
163 | } | |
164 | ||
9abe5450 EZ |
165 | /* The Linux kernel ptrace interface for AltiVec registers uses the |
166 | registers set mechanism, as opposed to the interface for all the | |
167 | other registers, that stores/fetches each register individually. */ | |
168 | static void | |
169 | fetch_altivec_register (int tid, int regno) | |
170 | { | |
171 | int ret; | |
172 | int offset = 0; | |
173 | gdb_vrregset_t regs; | |
174 | struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); | |
175 | int vrregsize = REGISTER_RAW_SIZE (tdep->ppc_vr0_regnum); | |
176 | ||
177 | ret = ptrace (PTRACE_GETVRREGS, tid, 0, ®s); | |
178 | if (ret < 0) | |
179 | { | |
180 | if (errno == EIO) | |
181 | { | |
182 | have_ptrace_getvrregs = 0; | |
183 | return; | |
184 | } | |
185 | perror_with_name ("Unable to fetch AltiVec register"); | |
186 | } | |
187 | ||
188 | /* VSCR is fetched as a 16 bytes quantity, but it is really 4 bytes | |
189 | long on the hardware. We deal only with the lower 4 bytes of the | |
190 | vector. VRSAVE is at the end of the array in a 4 bytes slot, so | |
191 | there is no need to define an offset for it. */ | |
192 | if (regno == (tdep->ppc_vrsave_regnum - 1)) | |
193 | offset = vrregsize - REGISTER_RAW_SIZE (tdep->ppc_vrsave_regnum); | |
194 | ||
195 | supply_register (regno, | |
196 | regs + (regno - tdep->ppc_vr0_regnum) * vrregsize + offset); | |
197 | } | |
198 | ||
45229ea4 | 199 | static void |
05f13b9c | 200 | fetch_register (int tid, int regno) |
45229ea4 EZ |
201 | { |
202 | /* This isn't really an address. But ptrace thinks of it as one. */ | |
203 | char mess[128]; /* For messages */ | |
204 | register int i; | |
205 | unsigned int offset; /* Offset of registers within the u area. */ | |
206 | char *buf = alloca (MAX_REGISTER_RAW_SIZE); | |
45229ea4 EZ |
207 | CORE_ADDR regaddr = ppc_register_u_addr (regno); |
208 | ||
9abe5450 EZ |
209 | if (altivec_register_p (regno)) |
210 | { | |
211 | /* If this is the first time through, or if it is not the first | |
212 | time through, and we have comfirmed that there is kernel | |
213 | support for such a ptrace request, then go and fetch the | |
214 | register. */ | |
215 | if (have_ptrace_getvrregs) | |
216 | { | |
217 | fetch_altivec_register (tid, regno); | |
218 | return; | |
219 | } | |
220 | /* If we have discovered that there is no ptrace support for | |
221 | AltiVec registers, fall through and return zeroes, because | |
222 | regaddr will be -1 in this case. */ | |
223 | } | |
224 | ||
45229ea4 EZ |
225 | if (regaddr == -1) |
226 | { | |
227 | memset (buf, '\0', REGISTER_RAW_SIZE (regno)); /* Supply zeroes */ | |
228 | supply_register (regno, buf); | |
229 | return; | |
230 | } | |
231 | ||
45229ea4 EZ |
232 | for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE)) |
233 | { | |
234 | errno = 0; | |
235 | *(PTRACE_XFER_TYPE *) & buf[i] = ptrace (PT_READ_U, tid, | |
236 | (PTRACE_ARG3_TYPE) regaddr, 0); | |
237 | regaddr += sizeof (PTRACE_XFER_TYPE); | |
238 | if (errno != 0) | |
239 | { | |
240 | sprintf (mess, "reading register %s (#%d)", | |
241 | REGISTER_NAME (regno), regno); | |
242 | perror_with_name (mess); | |
243 | } | |
244 | } | |
245 | supply_register (regno, buf); | |
246 | } | |
247 | ||
9abe5450 EZ |
248 | static void |
249 | supply_vrregset (gdb_vrregset_t *vrregsetp) | |
250 | { | |
251 | int i; | |
252 | struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); | |
253 | int num_of_vrregs = tdep->ppc_vrsave_regnum - tdep->ppc_vr0_regnum + 1; | |
254 | int vrregsize = REGISTER_RAW_SIZE (tdep->ppc_vr0_regnum); | |
255 | int offset = vrregsize - REGISTER_RAW_SIZE (tdep->ppc_vrsave_regnum); | |
256 | ||
257 | for (i = 0; i < num_of_vrregs; i++) | |
258 | { | |
259 | /* The last 2 registers of this set are only 32 bit long, not | |
260 | 128. However an offset is necessary only for VSCR because it | |
261 | occupies a whole vector, while VRSAVE occupies a full 4 bytes | |
262 | slot. */ | |
263 | if (i == (num_of_vrregs - 2)) | |
264 | supply_register (tdep->ppc_vr0_regnum + i, | |
265 | *vrregsetp + i * vrregsize + offset); | |
266 | else | |
267 | supply_register (tdep->ppc_vr0_regnum + i, *vrregsetp + i * vrregsize); | |
268 | } | |
269 | } | |
270 | ||
271 | static void | |
272 | fetch_altivec_registers (int tid) | |
273 | { | |
274 | int ret; | |
275 | gdb_vrregset_t regs; | |
276 | ||
277 | ret = ptrace (PTRACE_GETVRREGS, tid, 0, ®s); | |
278 | if (ret < 0) | |
279 | { | |
280 | if (errno == EIO) | |
281 | { | |
282 | have_ptrace_getvrregs = 0; | |
283 | return; | |
284 | } | |
285 | perror_with_name ("Unable to fetch AltiVec registers"); | |
286 | } | |
287 | supply_vrregset (®s); | |
288 | } | |
289 | ||
45229ea4 | 290 | static void |
05f13b9c | 291 | fetch_ppc_registers (int tid) |
45229ea4 EZ |
292 | { |
293 | int i; | |
9abe5450 EZ |
294 | struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); |
295 | ||
e3f36dbd | 296 | for (i = 0; i <= tdep->ppc_fpscr_regnum; i++) |
05f13b9c | 297 | fetch_register (tid, i); |
e3f36dbd KB |
298 | if (tdep->ppc_mq_regnum != -1) |
299 | fetch_register (tid, tdep->ppc_mq_regnum); | |
9abe5450 EZ |
300 | if (have_ptrace_getvrregs) |
301 | if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1) | |
302 | fetch_altivec_registers (tid); | |
45229ea4 EZ |
303 | } |
304 | ||
305 | /* Fetch registers from the child process. Fetch all registers if | |
306 | regno == -1, otherwise fetch all general registers or all floating | |
307 | point registers depending upon the value of regno. */ | |
308 | void | |
309 | fetch_inferior_registers (int regno) | |
310 | { | |
9abe5450 | 311 | /* Overload thread id onto process id */ |
05f13b9c EZ |
312 | int tid = TIDGET (inferior_ptid); |
313 | ||
314 | /* No thread id, just use process id */ | |
315 | if (tid == 0) | |
316 | tid = PIDGET (inferior_ptid); | |
317 | ||
9abe5450 | 318 | if (regno == -1) |
05f13b9c | 319 | fetch_ppc_registers (tid); |
45229ea4 | 320 | else |
05f13b9c | 321 | fetch_register (tid, regno); |
45229ea4 EZ |
322 | } |
323 | ||
324 | /* Store one register. */ | |
9abe5450 EZ |
325 | static void |
326 | store_altivec_register (int tid, int regno) | |
327 | { | |
328 | int ret; | |
329 | int offset = 0; | |
330 | gdb_vrregset_t regs; | |
331 | struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); | |
332 | int vrregsize = REGISTER_RAW_SIZE (tdep->ppc_vr0_regnum); | |
333 | ||
334 | ret = ptrace (PTRACE_GETVRREGS, tid, 0, ®s); | |
335 | if (ret < 0) | |
336 | { | |
337 | if (errno == EIO) | |
338 | { | |
339 | have_ptrace_getvrregs = 0; | |
340 | return; | |
341 | } | |
342 | perror_with_name ("Unable to fetch AltiVec register"); | |
343 | } | |
344 | ||
345 | /* VSCR is fetched as a 16 bytes quantity, but it is really 4 bytes | |
346 | long on the hardware. */ | |
347 | if (regno == (tdep->ppc_vrsave_regnum - 1)) | |
348 | offset = vrregsize - REGISTER_RAW_SIZE (tdep->ppc_vrsave_regnum); | |
349 | ||
350 | regcache_collect (regno, | |
351 | regs + (regno - tdep->ppc_vr0_regnum) * vrregsize + offset); | |
352 | ||
353 | ret = ptrace (PTRACE_SETVRREGS, tid, 0, ®s); | |
354 | if (ret < 0) | |
355 | perror_with_name ("Unable to store AltiVec register"); | |
356 | } | |
357 | ||
45229ea4 | 358 | static void |
05f13b9c | 359 | store_register (int tid, int regno) |
45229ea4 EZ |
360 | { |
361 | /* This isn't really an address. But ptrace thinks of it as one. */ | |
362 | CORE_ADDR regaddr = ppc_register_u_addr (regno); | |
363 | char mess[128]; /* For messages */ | |
364 | register int i; | |
365 | unsigned int offset; /* Offset of registers within the u area. */ | |
45229ea4 EZ |
366 | char *buf = alloca (MAX_REGISTER_RAW_SIZE); |
367 | ||
9abe5450 | 368 | if (altivec_register_p (regno)) |
45229ea4 | 369 | { |
9abe5450 | 370 | store_altivec_register (tid, regno); |
45229ea4 EZ |
371 | return; |
372 | } | |
373 | ||
9abe5450 EZ |
374 | if (regaddr == -1) |
375 | return; | |
376 | ||
45229ea4 EZ |
377 | regcache_collect (regno, buf); |
378 | for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE)) | |
379 | { | |
380 | errno = 0; | |
381 | ptrace (PT_WRITE_U, tid, (PTRACE_ARG3_TYPE) regaddr, | |
382 | *(PTRACE_XFER_TYPE *) & buf[i]); | |
383 | regaddr += sizeof (PTRACE_XFER_TYPE); | |
e3f36dbd KB |
384 | |
385 | if (errno == EIO | |
386 | && regno == gdbarch_tdep (current_gdbarch)->ppc_fpscr_regnum) | |
387 | { | |
388 | /* Some older kernel versions don't allow fpscr to be written. */ | |
389 | continue; | |
390 | } | |
391 | ||
45229ea4 EZ |
392 | if (errno != 0) |
393 | { | |
394 | sprintf (mess, "writing register %s (#%d)", | |
395 | REGISTER_NAME (regno), regno); | |
396 | perror_with_name (mess); | |
397 | } | |
398 | } | |
399 | } | |
400 | ||
9abe5450 EZ |
401 | static void |
402 | fill_vrregset (gdb_vrregset_t *vrregsetp) | |
403 | { | |
404 | int i; | |
405 | struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); | |
406 | int num_of_vrregs = tdep->ppc_vrsave_regnum - tdep->ppc_vr0_regnum + 1; | |
407 | int vrregsize = REGISTER_RAW_SIZE (tdep->ppc_vr0_regnum); | |
408 | int offset = vrregsize - REGISTER_RAW_SIZE (tdep->ppc_vrsave_regnum); | |
409 | ||
410 | for (i = 0; i < num_of_vrregs; i++) | |
411 | { | |
412 | /* The last 2 registers of this set are only 32 bit long, not | |
413 | 128, but only VSCR is fetched as a 16 bytes quantity. */ | |
414 | if (i == (num_of_vrregs - 2)) | |
415 | regcache_collect (tdep->ppc_vr0_regnum + i, | |
416 | *vrregsetp + i * vrregsize + offset); | |
417 | else | |
418 | regcache_collect (tdep->ppc_vr0_regnum + i, *vrregsetp + i * vrregsize); | |
419 | } | |
420 | } | |
421 | ||
422 | static void | |
423 | store_altivec_registers (int tid) | |
424 | { | |
425 | int ret; | |
426 | gdb_vrregset_t regs; | |
427 | ||
428 | ret = ptrace (PTRACE_GETVRREGS, tid, 0, (int) ®s); | |
429 | if (ret < 0) | |
430 | { | |
431 | if (errno == EIO) | |
432 | { | |
433 | have_ptrace_getvrregs = 0; | |
434 | return; | |
435 | } | |
436 | perror_with_name ("Couldn't get AltiVec registers"); | |
437 | } | |
438 | ||
439 | fill_vrregset (®s); | |
440 | ||
441 | if (ptrace (PTRACE_SETVRREGS, tid, 0, (int) ®s) < 0) | |
442 | perror_with_name ("Couldn't write AltiVec registers"); | |
443 | } | |
444 | ||
45229ea4 | 445 | static void |
05f13b9c | 446 | store_ppc_registers (int tid) |
45229ea4 EZ |
447 | { |
448 | int i; | |
9abe5450 | 449 | struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); |
45229ea4 | 450 | |
e3f36dbd | 451 | for (i = 0; i <= tdep->ppc_fpscr_regnum; i++) |
05f13b9c | 452 | store_register (tid, i); |
e3f36dbd KB |
453 | if (tdep->ppc_mq_regnum != -1) |
454 | store_register (tid, tdep->ppc_mq_regnum); | |
9abe5450 EZ |
455 | if (have_ptrace_getvrregs) |
456 | if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1) | |
457 | store_altivec_registers (tid); | |
45229ea4 EZ |
458 | } |
459 | ||
460 | void | |
461 | store_inferior_registers (int regno) | |
462 | { | |
05f13b9c EZ |
463 | /* Overload thread id onto process id */ |
464 | int tid = TIDGET (inferior_ptid); | |
465 | ||
466 | /* No thread id, just use process id */ | |
467 | if (tid == 0) | |
468 | tid = PIDGET (inferior_ptid); | |
469 | ||
45229ea4 | 470 | if (regno >= 0) |
05f13b9c | 471 | store_register (tid, regno); |
45229ea4 | 472 | else |
05f13b9c | 473 | store_ppc_registers (tid); |
45229ea4 EZ |
474 | } |
475 | ||
50c9bd31 | 476 | void |
8ae45c11 | 477 | supply_gregset (gdb_gregset_t *gregsetp) |
c877c8e6 | 478 | { |
2fda4977 | 479 | ppc_linux_supply_gregset ((char *) gregsetp); |
c877c8e6 KB |
480 | } |
481 | ||
fdb28ac4 | 482 | void |
8ae45c11 | 483 | fill_gregset (gdb_gregset_t *gregsetp, int regno) |
fdb28ac4 KB |
484 | { |
485 | int regi; | |
2ac44c70 | 486 | elf_greg_t *regp = (elf_greg_t *) gregsetp; |
dc5cfeb6 | 487 | struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); |
fdb28ac4 | 488 | |
fdb28ac4 KB |
489 | for (regi = 0; regi < 32; regi++) |
490 | { | |
16333c4f EZ |
491 | if ((regno == -1) || regno == regi) |
492 | regcache_collect (regi, regp + PT_R0 + regi); | |
fdb28ac4 KB |
493 | } |
494 | ||
16333c4f EZ |
495 | if ((regno == -1) || regno == PC_REGNUM) |
496 | regcache_collect (PC_REGNUM, regp + PT_NIP); | |
05f13b9c | 497 | if ((regno == -1) || regno == tdep->ppc_lr_regnum) |
dc5cfeb6 | 498 | regcache_collect (tdep->ppc_lr_regnum, regp + PT_LNK); |
05f13b9c | 499 | if ((regno == -1) || regno == tdep->ppc_cr_regnum) |
dc5cfeb6 | 500 | regcache_collect (tdep->ppc_cr_regnum, regp + PT_CCR); |
05f13b9c | 501 | if ((regno == -1) || regno == tdep->ppc_xer_regnum) |
dc5cfeb6 | 502 | regcache_collect (tdep->ppc_xer_regnum, regp + PT_XER); |
05f13b9c | 503 | if ((regno == -1) || regno == tdep->ppc_ctr_regnum) |
dc5cfeb6 | 504 | regcache_collect (tdep->ppc_ctr_regnum, regp + PT_CTR); |
e3f36dbd KB |
505 | if (((regno == -1) || regno == tdep->ppc_mq_regnum) |
506 | && (tdep->ppc_mq_regnum != -1)) | |
dc5cfeb6 | 507 | regcache_collect (tdep->ppc_mq_regnum, regp + PT_MQ); |
05f13b9c | 508 | if ((regno == -1) || regno == tdep->ppc_ps_regnum) |
dc5cfeb6 | 509 | regcache_collect (tdep->ppc_ps_regnum, regp + PT_MSR); |
fdb28ac4 KB |
510 | } |
511 | ||
50c9bd31 | 512 | void |
8ae45c11 | 513 | supply_fpregset (gdb_fpregset_t * fpregsetp) |
c877c8e6 | 514 | { |
2fda4977 | 515 | ppc_linux_supply_fpregset ((char *) fpregsetp); |
c877c8e6 | 516 | } |
fdb28ac4 | 517 | |
9abe5450 EZ |
518 | /* Given a pointer to a floating point register set in /proc format |
519 | (fpregset_t *), update the register specified by REGNO from gdb's | |
520 | idea of the current floating point register set. If REGNO is -1, | |
521 | update them all. */ | |
fdb28ac4 | 522 | void |
8ae45c11 | 523 | fill_fpregset (gdb_fpregset_t *fpregsetp, int regno) |
fdb28ac4 KB |
524 | { |
525 | int regi; | |
e3f36dbd | 526 | struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); |
fdb28ac4 KB |
527 | |
528 | for (regi = 0; regi < 32; regi++) | |
529 | { | |
530 | if ((regno == -1) || (regno == FP0_REGNUM + regi)) | |
f00d3753 | 531 | regcache_collect (FP0_REGNUM + regi, (char *) (*fpregsetp + regi)); |
fdb28ac4 | 532 | } |
e3f36dbd KB |
533 | if ((regno == -1) || regno == tdep->ppc_fpscr_regnum) |
534 | regcache_collect (tdep->ppc_fpscr_regnum, (char *) (*fpregsetp + regi)); | |
fdb28ac4 | 535 | } |