1b725ae77Skettenis /* Functions specific to running gdb native on IA-64 running
2b725ae77Skettenis GNU/Linux.
3b725ae77Skettenis
4*11efff7fSkettenis Copyright 1999, 2000, 2001, 2002, 2003, 2004
5*11efff7fSkettenis Free Software Foundation, Inc.
6b725ae77Skettenis
7b725ae77Skettenis This file is part of GDB.
8b725ae77Skettenis
9b725ae77Skettenis This program is free software; you can redistribute it and/or modify
10b725ae77Skettenis it under the terms of the GNU General Public License as published by
11b725ae77Skettenis the Free Software Foundation; either version 2 of the License, or
12b725ae77Skettenis (at your option) any later version.
13b725ae77Skettenis
14b725ae77Skettenis This program is distributed in the hope that it will be useful,
15b725ae77Skettenis but WITHOUT ANY WARRANTY; without even the implied warranty of
16b725ae77Skettenis MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17b725ae77Skettenis GNU General Public License for more details.
18b725ae77Skettenis
19b725ae77Skettenis You should have received a copy of the GNU General Public License
20b725ae77Skettenis along with this program; if not, write to the Free Software
21b725ae77Skettenis Foundation, Inc., 59 Temple Place - Suite 330,
22b725ae77Skettenis Boston, MA 02111-1307, USA. */
23b725ae77Skettenis
24b725ae77Skettenis #include "defs.h"
25b725ae77Skettenis #include "gdb_string.h"
26b725ae77Skettenis #include "inferior.h"
27b725ae77Skettenis #include "target.h"
28b725ae77Skettenis #include "gdbcore.h"
29b725ae77Skettenis #include "regcache.h"
30b725ae77Skettenis
31b725ae77Skettenis #include <signal.h>
32b725ae77Skettenis #include <sys/ptrace.h>
33b725ae77Skettenis #include "gdb_wait.h"
34b725ae77Skettenis #ifdef HAVE_SYS_REG_H
35b725ae77Skettenis #include <sys/reg.h>
36b725ae77Skettenis #endif
37b725ae77Skettenis #include <sys/syscall.h>
38b725ae77Skettenis #include <sys/user.h>
39b725ae77Skettenis
40b725ae77Skettenis #include <asm/ptrace_offsets.h>
41b725ae77Skettenis #include <sys/procfs.h>
42b725ae77Skettenis
43b725ae77Skettenis /* Prototypes for supply_gregset etc. */
44b725ae77Skettenis #include "gregset.h"
45b725ae77Skettenis
46b725ae77Skettenis /* These must match the order of the register names.
47b725ae77Skettenis
48b725ae77Skettenis Some sort of lookup table is needed because the offsets associated
49b725ae77Skettenis with the registers are all over the board. */
50b725ae77Skettenis
51b725ae77Skettenis static int u_offsets[] =
52b725ae77Skettenis {
53b725ae77Skettenis /* general registers */
54b725ae77Skettenis -1, /* gr0 not available; i.e, it's always zero */
55b725ae77Skettenis PT_R1,
56b725ae77Skettenis PT_R2,
57b725ae77Skettenis PT_R3,
58b725ae77Skettenis PT_R4,
59b725ae77Skettenis PT_R5,
60b725ae77Skettenis PT_R6,
61b725ae77Skettenis PT_R7,
62b725ae77Skettenis PT_R8,
63b725ae77Skettenis PT_R9,
64b725ae77Skettenis PT_R10,
65b725ae77Skettenis PT_R11,
66b725ae77Skettenis PT_R12,
67b725ae77Skettenis PT_R13,
68b725ae77Skettenis PT_R14,
69b725ae77Skettenis PT_R15,
70b725ae77Skettenis PT_R16,
71b725ae77Skettenis PT_R17,
72b725ae77Skettenis PT_R18,
73b725ae77Skettenis PT_R19,
74b725ae77Skettenis PT_R20,
75b725ae77Skettenis PT_R21,
76b725ae77Skettenis PT_R22,
77b725ae77Skettenis PT_R23,
78b725ae77Skettenis PT_R24,
79b725ae77Skettenis PT_R25,
80b725ae77Skettenis PT_R26,
81b725ae77Skettenis PT_R27,
82b725ae77Skettenis PT_R28,
83b725ae77Skettenis PT_R29,
84b725ae77Skettenis PT_R30,
85b725ae77Skettenis PT_R31,
86b725ae77Skettenis /* gr32 through gr127 not directly available via the ptrace interface */
87b725ae77Skettenis -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
88b725ae77Skettenis -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
89b725ae77Skettenis -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
90b725ae77Skettenis -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
91b725ae77Skettenis -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
92b725ae77Skettenis -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
93b725ae77Skettenis /* Floating point registers */
94b725ae77Skettenis -1, -1, /* f0 and f1 not available (f0 is +0.0 and f1 is +1.0) */
95b725ae77Skettenis PT_F2,
96b725ae77Skettenis PT_F3,
97b725ae77Skettenis PT_F4,
98b725ae77Skettenis PT_F5,
99b725ae77Skettenis PT_F6,
100b725ae77Skettenis PT_F7,
101b725ae77Skettenis PT_F8,
102b725ae77Skettenis PT_F9,
103b725ae77Skettenis PT_F10,
104b725ae77Skettenis PT_F11,
105b725ae77Skettenis PT_F12,
106b725ae77Skettenis PT_F13,
107b725ae77Skettenis PT_F14,
108b725ae77Skettenis PT_F15,
109b725ae77Skettenis PT_F16,
110b725ae77Skettenis PT_F17,
111b725ae77Skettenis PT_F18,
112b725ae77Skettenis PT_F19,
113b725ae77Skettenis PT_F20,
114b725ae77Skettenis PT_F21,
115b725ae77Skettenis PT_F22,
116b725ae77Skettenis PT_F23,
117b725ae77Skettenis PT_F24,
118b725ae77Skettenis PT_F25,
119b725ae77Skettenis PT_F26,
120b725ae77Skettenis PT_F27,
121b725ae77Skettenis PT_F28,
122b725ae77Skettenis PT_F29,
123b725ae77Skettenis PT_F30,
124b725ae77Skettenis PT_F31,
125b725ae77Skettenis PT_F32,
126b725ae77Skettenis PT_F33,
127b725ae77Skettenis PT_F34,
128b725ae77Skettenis PT_F35,
129b725ae77Skettenis PT_F36,
130b725ae77Skettenis PT_F37,
131b725ae77Skettenis PT_F38,
132b725ae77Skettenis PT_F39,
133b725ae77Skettenis PT_F40,
134b725ae77Skettenis PT_F41,
135b725ae77Skettenis PT_F42,
136b725ae77Skettenis PT_F43,
137b725ae77Skettenis PT_F44,
138b725ae77Skettenis PT_F45,
139b725ae77Skettenis PT_F46,
140b725ae77Skettenis PT_F47,
141b725ae77Skettenis PT_F48,
142b725ae77Skettenis PT_F49,
143b725ae77Skettenis PT_F50,
144b725ae77Skettenis PT_F51,
145b725ae77Skettenis PT_F52,
146b725ae77Skettenis PT_F53,
147b725ae77Skettenis PT_F54,
148b725ae77Skettenis PT_F55,
149b725ae77Skettenis PT_F56,
150b725ae77Skettenis PT_F57,
151b725ae77Skettenis PT_F58,
152b725ae77Skettenis PT_F59,
153b725ae77Skettenis PT_F60,
154b725ae77Skettenis PT_F61,
155b725ae77Skettenis PT_F62,
156b725ae77Skettenis PT_F63,
157b725ae77Skettenis PT_F64,
158b725ae77Skettenis PT_F65,
159b725ae77Skettenis PT_F66,
160b725ae77Skettenis PT_F67,
161b725ae77Skettenis PT_F68,
162b725ae77Skettenis PT_F69,
163b725ae77Skettenis PT_F70,
164b725ae77Skettenis PT_F71,
165b725ae77Skettenis PT_F72,
166b725ae77Skettenis PT_F73,
167b725ae77Skettenis PT_F74,
168b725ae77Skettenis PT_F75,
169b725ae77Skettenis PT_F76,
170b725ae77Skettenis PT_F77,
171b725ae77Skettenis PT_F78,
172b725ae77Skettenis PT_F79,
173b725ae77Skettenis PT_F80,
174b725ae77Skettenis PT_F81,
175b725ae77Skettenis PT_F82,
176b725ae77Skettenis PT_F83,
177b725ae77Skettenis PT_F84,
178b725ae77Skettenis PT_F85,
179b725ae77Skettenis PT_F86,
180b725ae77Skettenis PT_F87,
181b725ae77Skettenis PT_F88,
182b725ae77Skettenis PT_F89,
183b725ae77Skettenis PT_F90,
184b725ae77Skettenis PT_F91,
185b725ae77Skettenis PT_F92,
186b725ae77Skettenis PT_F93,
187b725ae77Skettenis PT_F94,
188b725ae77Skettenis PT_F95,
189b725ae77Skettenis PT_F96,
190b725ae77Skettenis PT_F97,
191b725ae77Skettenis PT_F98,
192b725ae77Skettenis PT_F99,
193b725ae77Skettenis PT_F100,
194b725ae77Skettenis PT_F101,
195b725ae77Skettenis PT_F102,
196b725ae77Skettenis PT_F103,
197b725ae77Skettenis PT_F104,
198b725ae77Skettenis PT_F105,
199b725ae77Skettenis PT_F106,
200b725ae77Skettenis PT_F107,
201b725ae77Skettenis PT_F108,
202b725ae77Skettenis PT_F109,
203b725ae77Skettenis PT_F110,
204b725ae77Skettenis PT_F111,
205b725ae77Skettenis PT_F112,
206b725ae77Skettenis PT_F113,
207b725ae77Skettenis PT_F114,
208b725ae77Skettenis PT_F115,
209b725ae77Skettenis PT_F116,
210b725ae77Skettenis PT_F117,
211b725ae77Skettenis PT_F118,
212b725ae77Skettenis PT_F119,
213b725ae77Skettenis PT_F120,
214b725ae77Skettenis PT_F121,
215b725ae77Skettenis PT_F122,
216b725ae77Skettenis PT_F123,
217b725ae77Skettenis PT_F124,
218b725ae77Skettenis PT_F125,
219b725ae77Skettenis PT_F126,
220b725ae77Skettenis PT_F127,
221b725ae77Skettenis /* predicate registers - we don't fetch these individually */
222b725ae77Skettenis -1, -1, -1, -1, -1, -1, -1, -1,
223b725ae77Skettenis -1, -1, -1, -1, -1, -1, -1, -1,
224b725ae77Skettenis -1, -1, -1, -1, -1, -1, -1, -1,
225b725ae77Skettenis -1, -1, -1, -1, -1, -1, -1, -1,
226b725ae77Skettenis -1, -1, -1, -1, -1, -1, -1, -1,
227b725ae77Skettenis -1, -1, -1, -1, -1, -1, -1, -1,
228b725ae77Skettenis -1, -1, -1, -1, -1, -1, -1, -1,
229b725ae77Skettenis -1, -1, -1, -1, -1, -1, -1, -1,
230b725ae77Skettenis /* branch registers */
231b725ae77Skettenis PT_B0,
232b725ae77Skettenis PT_B1,
233b725ae77Skettenis PT_B2,
234b725ae77Skettenis PT_B3,
235b725ae77Skettenis PT_B4,
236b725ae77Skettenis PT_B5,
237b725ae77Skettenis PT_B6,
238b725ae77Skettenis PT_B7,
239b725ae77Skettenis /* virtual frame pointer and virtual return address pointer */
240b725ae77Skettenis -1, -1,
241b725ae77Skettenis /* other registers */
242b725ae77Skettenis PT_PR,
243b725ae77Skettenis PT_CR_IIP, /* ip */
244b725ae77Skettenis PT_CR_IPSR, /* psr */
245b725ae77Skettenis PT_CFM, /* cfm */
246b725ae77Skettenis /* kernel registers not visible via ptrace interface (?) */
247b725ae77Skettenis -1, -1, -1, -1, -1, -1, -1, -1,
248b725ae77Skettenis /* hole */
249b725ae77Skettenis -1, -1, -1, -1, -1, -1, -1, -1,
250b725ae77Skettenis PT_AR_RSC,
251b725ae77Skettenis PT_AR_BSP,
252b725ae77Skettenis PT_AR_BSPSTORE,
253b725ae77Skettenis PT_AR_RNAT,
254b725ae77Skettenis -1,
255b725ae77Skettenis -1, /* Not available: FCR, IA32 floating control register */
256b725ae77Skettenis -1, -1,
257b725ae77Skettenis -1, /* Not available: EFLAG */
258b725ae77Skettenis -1, /* Not available: CSD */
259b725ae77Skettenis -1, /* Not available: SSD */
260b725ae77Skettenis -1, /* Not available: CFLG */
261b725ae77Skettenis -1, /* Not available: FSR */
262b725ae77Skettenis -1, /* Not available: FIR */
263b725ae77Skettenis -1, /* Not available: FDR */
264b725ae77Skettenis -1,
265b725ae77Skettenis PT_AR_CCV,
266b725ae77Skettenis -1, -1, -1,
267b725ae77Skettenis PT_AR_UNAT,
268b725ae77Skettenis -1, -1, -1,
269b725ae77Skettenis PT_AR_FPSR,
270b725ae77Skettenis -1, -1, -1,
271b725ae77Skettenis -1, /* Not available: ITC */
272b725ae77Skettenis -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
273b725ae77Skettenis -1, -1, -1, -1, -1, -1, -1, -1, -1,
274b725ae77Skettenis PT_AR_PFS,
275b725ae77Skettenis PT_AR_LC,
276b725ae77Skettenis -1, /* Not available: EC, the Epilog Count register */
277b725ae77Skettenis -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
278b725ae77Skettenis -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
279b725ae77Skettenis -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
280b725ae77Skettenis -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
281b725ae77Skettenis -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
282b725ae77Skettenis -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
283b725ae77Skettenis -1,
284b725ae77Skettenis /* nat bits - not fetched directly; instead we obtain these bits from
285b725ae77Skettenis either rnat or unat or from memory. */
286b725ae77Skettenis -1, -1, -1, -1, -1, -1, -1, -1,
287b725ae77Skettenis -1, -1, -1, -1, -1, -1, -1, -1,
288b725ae77Skettenis -1, -1, -1, -1, -1, -1, -1, -1,
289b725ae77Skettenis -1, -1, -1, -1, -1, -1, -1, -1,
290b725ae77Skettenis -1, -1, -1, -1, -1, -1, -1, -1,
291b725ae77Skettenis -1, -1, -1, -1, -1, -1, -1, -1,
292b725ae77Skettenis -1, -1, -1, -1, -1, -1, -1, -1,
293b725ae77Skettenis -1, -1, -1, -1, -1, -1, -1, -1,
294b725ae77Skettenis -1, -1, -1, -1, -1, -1, -1, -1,
295b725ae77Skettenis -1, -1, -1, -1, -1, -1, -1, -1,
296b725ae77Skettenis -1, -1, -1, -1, -1, -1, -1, -1,
297b725ae77Skettenis -1, -1, -1, -1, -1, -1, -1, -1,
298b725ae77Skettenis -1, -1, -1, -1, -1, -1, -1, -1,
299b725ae77Skettenis -1, -1, -1, -1, -1, -1, -1, -1,
300b725ae77Skettenis -1, -1, -1, -1, -1, -1, -1, -1,
301b725ae77Skettenis -1, -1, -1, -1, -1, -1, -1, -1,
302b725ae77Skettenis };
303b725ae77Skettenis
304b725ae77Skettenis CORE_ADDR
register_addr(int regno,CORE_ADDR blockend)305b725ae77Skettenis register_addr (int regno, CORE_ADDR blockend)
306b725ae77Skettenis {
307b725ae77Skettenis CORE_ADDR addr;
308b725ae77Skettenis
309b725ae77Skettenis if (regno < 0 || regno >= NUM_REGS)
310b725ae77Skettenis error ("Invalid register number %d.", regno);
311b725ae77Skettenis
312b725ae77Skettenis if (u_offsets[regno] == -1)
313b725ae77Skettenis addr = 0;
314b725ae77Skettenis else
315b725ae77Skettenis addr = (CORE_ADDR) u_offsets[regno];
316b725ae77Skettenis
317b725ae77Skettenis return addr;
318b725ae77Skettenis }
319b725ae77Skettenis
ia64_cannot_fetch_register(regno)320b725ae77Skettenis int ia64_cannot_fetch_register (regno)
321b725ae77Skettenis int regno;
322b725ae77Skettenis {
323b725ae77Skettenis return regno < 0 || regno >= NUM_REGS || u_offsets[regno] == -1;
324b725ae77Skettenis }
325b725ae77Skettenis
ia64_cannot_store_register(regno)326b725ae77Skettenis int ia64_cannot_store_register (regno)
327b725ae77Skettenis int regno;
328b725ae77Skettenis {
329b725ae77Skettenis /* Rationale behind not permitting stores to bspstore...
330b725ae77Skettenis
331b725ae77Skettenis The IA-64 architecture provides bspstore and bsp which refer
332b725ae77Skettenis memory locations in the RSE's backing store. bspstore is the
333b725ae77Skettenis next location which will be written when the RSE needs to write
334b725ae77Skettenis to memory. bsp is the address at which r32 in the current frame
335b725ae77Skettenis would be found if it were written to the backing store.
336b725ae77Skettenis
337b725ae77Skettenis The IA-64 architecture provides read-only access to bsp and
338b725ae77Skettenis read/write access to bspstore (but only when the RSE is in
339b725ae77Skettenis the enforced lazy mode). It should be noted that stores
340b725ae77Skettenis to bspstore also affect the value of bsp. Changing bspstore
341b725ae77Skettenis does not affect the number of dirty entries between bspstore
342b725ae77Skettenis and bsp, so changing bspstore by N words will also cause bsp
343b725ae77Skettenis to be changed by (roughly) N as well. (It could be N-1 or N+1
344b725ae77Skettenis depending upon where the NaT collection bits fall.)
345b725ae77Skettenis
346b725ae77Skettenis OTOH, the Linux kernel provides read/write access to bsp (and
347b725ae77Skettenis currently read/write access to bspstore as well). But it
348b725ae77Skettenis is definitely the case that if you change one, the other
349b725ae77Skettenis will change at the same time. It is more useful to gdb to
350b725ae77Skettenis be able to change bsp. So in order to prevent strange and
351b725ae77Skettenis undesirable things from happening when a dummy stack frame
352b725ae77Skettenis is popped (after calling an inferior function), we allow
353b725ae77Skettenis bspstore to be read, but not written. (Note that popping
354b725ae77Skettenis a (generic) dummy stack frame causes all registers that
355b725ae77Skettenis were previously read from the inferior process to be written
356b725ae77Skettenis back.) */
357b725ae77Skettenis
358b725ae77Skettenis return regno < 0 || regno >= NUM_REGS || u_offsets[regno] == -1
359b725ae77Skettenis || regno == IA64_BSPSTORE_REGNUM;
360b725ae77Skettenis }
361b725ae77Skettenis
362b725ae77Skettenis void
supply_gregset(gregset_t * gregsetp)363b725ae77Skettenis supply_gregset (gregset_t *gregsetp)
364b725ae77Skettenis {
365b725ae77Skettenis int regi;
366b725ae77Skettenis greg_t *regp = (greg_t *) gregsetp;
367b725ae77Skettenis
368b725ae77Skettenis for (regi = IA64_GR0_REGNUM; regi <= IA64_GR31_REGNUM; regi++)
369b725ae77Skettenis {
370*11efff7fSkettenis regcache_raw_supply (current_regcache, regi,
371*11efff7fSkettenis (char *) (regp + (regi - IA64_GR0_REGNUM)));
372b725ae77Skettenis }
373b725ae77Skettenis
374b725ae77Skettenis /* FIXME: NAT collection bits are at index 32; gotta deal with these
375b725ae77Skettenis somehow... */
376b725ae77Skettenis
377*11efff7fSkettenis regcache_raw_supply (current_regcache, IA64_PR_REGNUM, (char *) (regp + 33));
378b725ae77Skettenis
379b725ae77Skettenis for (regi = IA64_BR0_REGNUM; regi <= IA64_BR7_REGNUM; regi++)
380b725ae77Skettenis {
381*11efff7fSkettenis regcache_raw_supply (current_regcache, regi,
382*11efff7fSkettenis (char *) (regp + 34 + (regi - IA64_BR0_REGNUM)));
383b725ae77Skettenis }
384b725ae77Skettenis
385*11efff7fSkettenis regcache_raw_supply (current_regcache, IA64_IP_REGNUM,
386*11efff7fSkettenis (char *) (regp + 42));
387*11efff7fSkettenis regcache_raw_supply (current_regcache, IA64_CFM_REGNUM,
388*11efff7fSkettenis (char *) (regp + 43));
389*11efff7fSkettenis regcache_raw_supply (current_regcache, IA64_PSR_REGNUM,
390*11efff7fSkettenis (char *) (regp + 44));
391*11efff7fSkettenis regcache_raw_supply (current_regcache, IA64_RSC_REGNUM,
392*11efff7fSkettenis (char *) (regp + 45));
393*11efff7fSkettenis regcache_raw_supply (current_regcache, IA64_BSP_REGNUM,
394*11efff7fSkettenis (char *) (regp + 46));
395*11efff7fSkettenis regcache_raw_supply (current_regcache, IA64_BSPSTORE_REGNUM,
396*11efff7fSkettenis (char *) (regp + 47));
397*11efff7fSkettenis regcache_raw_supply (current_regcache, IA64_RNAT_REGNUM,
398*11efff7fSkettenis (char *) (regp + 48));
399*11efff7fSkettenis regcache_raw_supply (current_regcache, IA64_CCV_REGNUM,
400*11efff7fSkettenis (char *) (regp + 49));
401*11efff7fSkettenis regcache_raw_supply (current_regcache, IA64_UNAT_REGNUM,
402*11efff7fSkettenis (char *) (regp + 50));
403*11efff7fSkettenis regcache_raw_supply (current_regcache, IA64_FPSR_REGNUM,
404*11efff7fSkettenis (char *) (regp + 51));
405*11efff7fSkettenis regcache_raw_supply (current_regcache, IA64_PFS_REGNUM,
406*11efff7fSkettenis (char *) (regp + 52));
407*11efff7fSkettenis regcache_raw_supply (current_regcache, IA64_LC_REGNUM,
408*11efff7fSkettenis (char *) (regp + 53));
409*11efff7fSkettenis regcache_raw_supply (current_regcache, IA64_EC_REGNUM,
410*11efff7fSkettenis (char *) (regp + 54));
411b725ae77Skettenis }
412b725ae77Skettenis
413b725ae77Skettenis void
fill_gregset(gregset_t * gregsetp,int regno)414b725ae77Skettenis fill_gregset (gregset_t *gregsetp, int regno)
415b725ae77Skettenis {
416b725ae77Skettenis int regi;
417b725ae77Skettenis greg_t *regp = (greg_t *) gregsetp;
418b725ae77Skettenis
419b725ae77Skettenis #define COPY_REG(_idx_,_regi_) \
420b725ae77Skettenis if ((regno == -1) || regno == _regi_) \
421*11efff7fSkettenis regcache_raw_collect (current_regcache, _regi_, regp + _idx_)
422b725ae77Skettenis
423b725ae77Skettenis for (regi = IA64_GR0_REGNUM; regi <= IA64_GR31_REGNUM; regi++)
424b725ae77Skettenis {
425b725ae77Skettenis COPY_REG (regi - IA64_GR0_REGNUM, regi);
426b725ae77Skettenis }
427b725ae77Skettenis
428b725ae77Skettenis /* FIXME: NAT collection bits at index 32? */
429b725ae77Skettenis
430b725ae77Skettenis COPY_REG (33, IA64_PR_REGNUM);
431b725ae77Skettenis
432b725ae77Skettenis for (regi = IA64_BR0_REGNUM; regi <= IA64_BR7_REGNUM; regi++)
433b725ae77Skettenis {
434b725ae77Skettenis COPY_REG (34 + (regi - IA64_BR0_REGNUM), regi);
435b725ae77Skettenis }
436b725ae77Skettenis
437b725ae77Skettenis COPY_REG (42, IA64_IP_REGNUM);
438b725ae77Skettenis COPY_REG (43, IA64_CFM_REGNUM);
439b725ae77Skettenis COPY_REG (44, IA64_PSR_REGNUM);
440b725ae77Skettenis COPY_REG (45, IA64_RSC_REGNUM);
441b725ae77Skettenis COPY_REG (46, IA64_BSP_REGNUM);
442b725ae77Skettenis COPY_REG (47, IA64_BSPSTORE_REGNUM);
443b725ae77Skettenis COPY_REG (48, IA64_RNAT_REGNUM);
444b725ae77Skettenis COPY_REG (49, IA64_CCV_REGNUM);
445b725ae77Skettenis COPY_REG (50, IA64_UNAT_REGNUM);
446b725ae77Skettenis COPY_REG (51, IA64_FPSR_REGNUM);
447b725ae77Skettenis COPY_REG (52, IA64_PFS_REGNUM);
448b725ae77Skettenis COPY_REG (53, IA64_LC_REGNUM);
449b725ae77Skettenis COPY_REG (54, IA64_EC_REGNUM);
450b725ae77Skettenis }
451b725ae77Skettenis
452b725ae77Skettenis /* Given a pointer to a floating point register set in /proc format
453b725ae77Skettenis (fpregset_t *), unpack the register contents and supply them as gdb's
454b725ae77Skettenis idea of the current floating point register values. */
455b725ae77Skettenis
456b725ae77Skettenis void
supply_fpregset(fpregset_t * fpregsetp)457b725ae77Skettenis supply_fpregset (fpregset_t *fpregsetp)
458b725ae77Skettenis {
459b725ae77Skettenis int regi;
460b725ae77Skettenis char *from;
461b725ae77Skettenis
462b725ae77Skettenis for (regi = IA64_FR0_REGNUM; regi <= IA64_FR127_REGNUM; regi++)
463b725ae77Skettenis {
464b725ae77Skettenis from = (char *) &((*fpregsetp)[regi - IA64_FR0_REGNUM]);
465*11efff7fSkettenis regcache_raw_supply (current_regcache, regi, from);
466b725ae77Skettenis }
467b725ae77Skettenis }
468b725ae77Skettenis
469b725ae77Skettenis /* Given a pointer to a floating point register set in /proc format
470b725ae77Skettenis (fpregset_t *), update the register specified by REGNO from gdb's idea
471b725ae77Skettenis of the current floating point register set. If REGNO is -1, update
472b725ae77Skettenis them all. */
473b725ae77Skettenis
474b725ae77Skettenis void
fill_fpregset(fpregset_t * fpregsetp,int regno)475b725ae77Skettenis fill_fpregset (fpregset_t *fpregsetp, int regno)
476b725ae77Skettenis {
477b725ae77Skettenis int regi;
478b725ae77Skettenis
479b725ae77Skettenis for (regi = IA64_FR0_REGNUM; regi <= IA64_FR127_REGNUM; regi++)
480b725ae77Skettenis {
481b725ae77Skettenis if ((regno == -1) || (regno == regi))
482*11efff7fSkettenis regcache_raw_collect (current_regcache, regi,
483*11efff7fSkettenis &((*fpregsetp)[regi - IA64_FR0_REGNUM]));
484b725ae77Skettenis }
485b725ae77Skettenis }
486b725ae77Skettenis
487b725ae77Skettenis #define IA64_PSR_DB (1UL << 24)
488b725ae77Skettenis #define IA64_PSR_DD (1UL << 39)
489b725ae77Skettenis
490b725ae77Skettenis static void
enable_watchpoints_in_psr(ptid_t ptid)491b725ae77Skettenis enable_watchpoints_in_psr (ptid_t ptid)
492b725ae77Skettenis {
493b725ae77Skettenis CORE_ADDR psr;
494b725ae77Skettenis
495b725ae77Skettenis psr = read_register_pid (IA64_PSR_REGNUM, ptid);
496b725ae77Skettenis if (!(psr & IA64_PSR_DB))
497b725ae77Skettenis {
498b725ae77Skettenis psr |= IA64_PSR_DB; /* Set the db bit - this enables hardware
499b725ae77Skettenis watchpoints and breakpoints. */
500b725ae77Skettenis write_register_pid (IA64_PSR_REGNUM, psr, ptid);
501b725ae77Skettenis }
502b725ae77Skettenis }
503b725ae77Skettenis
504b725ae77Skettenis static long
fetch_debug_register(ptid_t ptid,int idx)505b725ae77Skettenis fetch_debug_register (ptid_t ptid, int idx)
506b725ae77Skettenis {
507b725ae77Skettenis long val;
508b725ae77Skettenis int tid;
509b725ae77Skettenis
510b725ae77Skettenis tid = TIDGET (ptid);
511b725ae77Skettenis if (tid == 0)
512b725ae77Skettenis tid = PIDGET (ptid);
513b725ae77Skettenis
514*11efff7fSkettenis val = ptrace (PT_READ_U, tid, (PTRACE_TYPE_ARG3) (PT_DBR + 8 * idx), 0);
515b725ae77Skettenis
516b725ae77Skettenis return val;
517b725ae77Skettenis }
518b725ae77Skettenis
519b725ae77Skettenis static void
store_debug_register(ptid_t ptid,int idx,long val)520b725ae77Skettenis store_debug_register (ptid_t ptid, int idx, long val)
521b725ae77Skettenis {
522b725ae77Skettenis int tid;
523b725ae77Skettenis
524b725ae77Skettenis tid = TIDGET (ptid);
525b725ae77Skettenis if (tid == 0)
526b725ae77Skettenis tid = PIDGET (ptid);
527b725ae77Skettenis
528*11efff7fSkettenis (void) ptrace (PT_WRITE_U, tid, (PTRACE_TYPE_ARG3) (PT_DBR + 8 * idx), val);
529b725ae77Skettenis }
530b725ae77Skettenis
531b725ae77Skettenis static void
fetch_debug_register_pair(ptid_t ptid,int idx,long * dbr_addr,long * dbr_mask)532b725ae77Skettenis fetch_debug_register_pair (ptid_t ptid, int idx, long *dbr_addr, long *dbr_mask)
533b725ae77Skettenis {
534b725ae77Skettenis if (dbr_addr)
535b725ae77Skettenis *dbr_addr = fetch_debug_register (ptid, 2 * idx);
536b725ae77Skettenis if (dbr_mask)
537b725ae77Skettenis *dbr_mask = fetch_debug_register (ptid, 2 * idx + 1);
538b725ae77Skettenis }
539b725ae77Skettenis
540b725ae77Skettenis static void
store_debug_register_pair(ptid_t ptid,int idx,long * dbr_addr,long * dbr_mask)541b725ae77Skettenis store_debug_register_pair (ptid_t ptid, int idx, long *dbr_addr, long *dbr_mask)
542b725ae77Skettenis {
543b725ae77Skettenis if (dbr_addr)
544b725ae77Skettenis store_debug_register (ptid, 2 * idx, *dbr_addr);
545b725ae77Skettenis if (dbr_mask)
546b725ae77Skettenis store_debug_register (ptid, 2 * idx + 1, *dbr_mask);
547b725ae77Skettenis }
548b725ae77Skettenis
549b725ae77Skettenis static int
is_power_of_2(int val)550b725ae77Skettenis is_power_of_2 (int val)
551b725ae77Skettenis {
552b725ae77Skettenis int i, onecount;
553b725ae77Skettenis
554b725ae77Skettenis onecount = 0;
555b725ae77Skettenis for (i = 0; i < 8 * sizeof (val); i++)
556b725ae77Skettenis if (val & (1 << i))
557b725ae77Skettenis onecount++;
558b725ae77Skettenis
559b725ae77Skettenis return onecount <= 1;
560b725ae77Skettenis }
561b725ae77Skettenis
562b725ae77Skettenis int
ia64_linux_insert_watchpoint(ptid_t ptid,CORE_ADDR addr,int len,int rw)563b725ae77Skettenis ia64_linux_insert_watchpoint (ptid_t ptid, CORE_ADDR addr, int len, int rw)
564b725ae77Skettenis {
565b725ae77Skettenis int idx;
566b725ae77Skettenis long dbr_addr, dbr_mask;
567b725ae77Skettenis int max_watchpoints = 4;
568b725ae77Skettenis
569b725ae77Skettenis if (len <= 0 || !is_power_of_2 (len))
570b725ae77Skettenis return -1;
571b725ae77Skettenis
572b725ae77Skettenis for (idx = 0; idx < max_watchpoints; idx++)
573b725ae77Skettenis {
574b725ae77Skettenis fetch_debug_register_pair (ptid, idx, NULL, &dbr_mask);
575b725ae77Skettenis if ((dbr_mask & (0x3UL << 62)) == 0)
576b725ae77Skettenis {
577b725ae77Skettenis /* Exit loop if both r and w bits clear */
578b725ae77Skettenis break;
579b725ae77Skettenis }
580b725ae77Skettenis }
581b725ae77Skettenis
582b725ae77Skettenis if (idx == max_watchpoints)
583b725ae77Skettenis return -1;
584b725ae77Skettenis
585b725ae77Skettenis dbr_addr = (long) addr;
586b725ae77Skettenis dbr_mask = (~(len - 1) & 0x00ffffffffffffffL); /* construct mask to match */
587b725ae77Skettenis dbr_mask |= 0x0800000000000000L; /* Only match privilege level 3 */
588b725ae77Skettenis switch (rw)
589b725ae77Skettenis {
590b725ae77Skettenis case hw_write:
591b725ae77Skettenis dbr_mask |= (1L << 62); /* Set w bit */
592b725ae77Skettenis break;
593b725ae77Skettenis case hw_read:
594b725ae77Skettenis dbr_mask |= (1L << 63); /* Set r bit */
595b725ae77Skettenis break;
596b725ae77Skettenis case hw_access:
597b725ae77Skettenis dbr_mask |= (3L << 62); /* Set both r and w bits */
598b725ae77Skettenis break;
599b725ae77Skettenis default:
600b725ae77Skettenis return -1;
601b725ae77Skettenis }
602b725ae77Skettenis
603b725ae77Skettenis store_debug_register_pair (ptid, idx, &dbr_addr, &dbr_mask);
604b725ae77Skettenis enable_watchpoints_in_psr (ptid);
605b725ae77Skettenis
606b725ae77Skettenis return 0;
607b725ae77Skettenis }
608b725ae77Skettenis
609b725ae77Skettenis int
ia64_linux_remove_watchpoint(ptid_t ptid,CORE_ADDR addr,int len)610b725ae77Skettenis ia64_linux_remove_watchpoint (ptid_t ptid, CORE_ADDR addr, int len)
611b725ae77Skettenis {
612b725ae77Skettenis int idx;
613b725ae77Skettenis long dbr_addr, dbr_mask;
614b725ae77Skettenis int max_watchpoints = 4;
615b725ae77Skettenis
616b725ae77Skettenis if (len <= 0 || !is_power_of_2 (len))
617b725ae77Skettenis return -1;
618b725ae77Skettenis
619b725ae77Skettenis for (idx = 0; idx < max_watchpoints; idx++)
620b725ae77Skettenis {
621b725ae77Skettenis fetch_debug_register_pair (ptid, idx, &dbr_addr, &dbr_mask);
622b725ae77Skettenis if ((dbr_mask & (0x3UL << 62)) && addr == (CORE_ADDR) dbr_addr)
623b725ae77Skettenis {
624b725ae77Skettenis dbr_addr = 0;
625b725ae77Skettenis dbr_mask = 0;
626b725ae77Skettenis store_debug_register_pair (ptid, idx, &dbr_addr, &dbr_mask);
627b725ae77Skettenis return 0;
628b725ae77Skettenis }
629b725ae77Skettenis }
630b725ae77Skettenis return -1;
631b725ae77Skettenis }
632b725ae77Skettenis
633*11efff7fSkettenis int
ia64_linux_stopped_data_address(CORE_ADDR * addr_p)634*11efff7fSkettenis ia64_linux_stopped_data_address (CORE_ADDR *addr_p)
635b725ae77Skettenis {
636b725ae77Skettenis CORE_ADDR psr;
637b725ae77Skettenis int tid;
638b725ae77Skettenis struct siginfo siginfo;
639*11efff7fSkettenis ptid_t ptid = inferior_ptid;
640b725ae77Skettenis
641b725ae77Skettenis tid = TIDGET(ptid);
642b725ae77Skettenis if (tid == 0)
643b725ae77Skettenis tid = PIDGET (ptid);
644b725ae77Skettenis
645b725ae77Skettenis errno = 0;
646*11efff7fSkettenis ptrace (PTRACE_GETSIGINFO, tid, (PTRACE_TYPE_ARG3) 0, &siginfo);
647b725ae77Skettenis
648b725ae77Skettenis if (errno != 0 || siginfo.si_signo != SIGTRAP ||
649b725ae77Skettenis (siginfo.si_code & 0xffff) != 0x0004 /* TRAP_HWBKPT */)
650b725ae77Skettenis return 0;
651b725ae77Skettenis
652b725ae77Skettenis psr = read_register_pid (IA64_PSR_REGNUM, ptid);
653b725ae77Skettenis psr |= IA64_PSR_DD; /* Set the dd bit - this will disable the watchpoint
654b725ae77Skettenis for the next instruction */
655b725ae77Skettenis write_register_pid (IA64_PSR_REGNUM, psr, ptid);
656b725ae77Skettenis
657*11efff7fSkettenis *addr_p = (CORE_ADDR)siginfo.si_addr;
658*11efff7fSkettenis return 1;
659*11efff7fSkettenis }
660*11efff7fSkettenis
661*11efff7fSkettenis int
ia64_linux_stopped_by_watchpoint(void)662*11efff7fSkettenis ia64_linux_stopped_by_watchpoint (void)
663*11efff7fSkettenis {
664*11efff7fSkettenis CORE_ADDR addr;
665*11efff7fSkettenis return ia64_linux_stopped_data_address (&addr);
666b725ae77Skettenis }
667b725ae77Skettenis
668b725ae77Skettenis LONGEST
ia64_linux_xfer_unwind_table(struct target_ops * ops,enum target_object object,const char * annex,void * readbuf,const void * writebuf,ULONGEST offset,LONGEST len)669b725ae77Skettenis ia64_linux_xfer_unwind_table (struct target_ops *ops,
670b725ae77Skettenis enum target_object object,
671b725ae77Skettenis const char *annex,
672b725ae77Skettenis void *readbuf, const void *writebuf,
673b725ae77Skettenis ULONGEST offset, LONGEST len)
674b725ae77Skettenis {
675b725ae77Skettenis return syscall (__NR_getunwind, readbuf, len);
676b725ae77Skettenis }
677