xref: /openbsd-src/gnu/usr.bin/binutils/gdb/ia64-linux-nat.c (revision 11efff7f3ac2b3cfeff0c0cddc14294d9b3aca4f)
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