* Contribute CGEN simulator build support code.
[binutils-gdb.git] / gdb / arm-linux-nat.c
blob7c8e04b18858d309d80a9fdc66f1d335d27dd547
1 /* GNU/Linux on ARM native support.
2 Copyright 1999, 2000 Free Software Foundation, Inc.
4 This file is part of GDB.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 #include "defs.h"
22 #include "inferior.h"
23 #include "gdbcore.h"
24 #include "gdb_string.h"
26 #include <sys/user.h>
27 #include <sys/ptrace.h>
28 #include <sys/utsname.h>
29 #include <sys/procfs.h>
31 /* Prototypes for supply_gregset etc. */
32 #include "gregset.h"
34 extern int arm_apcs_32;
36 #define typeNone 0x00
37 #define typeSingle 0x01
38 #define typeDouble 0x02
39 #define typeExtended 0x03
40 #define FPWORDS 28
41 #define CPSR_REGNUM 16
43 typedef union tagFPREG
45 unsigned int fSingle;
46 unsigned int fDouble[2];
47 unsigned int fExtended[3];
49 FPREG;
51 typedef struct tagFPA11
53 FPREG fpreg[8]; /* 8 floating point registers */
54 unsigned int fpsr; /* floating point status register */
55 unsigned int fpcr; /* floating point control register */
56 unsigned char fType[8]; /* type of floating point value held in
57 floating point registers. */
58 int initflag; /* NWFPE initialization flag. */
60 FPA11;
62 /* The following variables are used to determine the version of the
63 underlying Linux operating system. Examples:
65 Linux 2.0.35 Linux 2.2.12
66 os_version = 0x00020023 os_version = 0x0002020c
67 os_major = 2 os_major = 2
68 os_minor = 0 os_minor = 2
69 os_release = 35 os_release = 12
71 Note: os_version = (os_major << 16) | (os_minor << 8) | os_release
73 These are initialized using get_linux_version() from
74 _initialize_arm_linux_nat(). */
76 static unsigned int os_version, os_major, os_minor, os_release;
78 /* On Linux, threads are implemented as pseudo-processes, in which
79 case we may be tracing more than one process at a time. In that
80 case, inferior_pid will contain the main process ID and the
81 individual thread (process) ID mashed together. These macros are
82 used to separate them out. These definitions should be overridden
83 if thread support is included. */
85 #if !defined (PIDGET) /* Default definition for PIDGET/TIDGET. */
86 #define PIDGET(PID) PID
87 #define TIDGET(PID) 0
88 #endif
90 int
91 get_thread_id (int inferior_pid)
93 int tid = TIDGET (inferior_pid);
94 if (0 == tid) tid = inferior_pid;
95 return tid;
97 #define GET_THREAD_ID(PID) get_thread_id ((PID));
99 static void
100 fetch_nwfpe_single (unsigned int fn, FPA11 * fpa11)
102 unsigned int mem[3];
104 mem[0] = fpa11->fpreg[fn].fSingle;
105 mem[1] = 0;
106 mem[2] = 0;
107 supply_register (F0_REGNUM + fn, (char *) &mem[0]);
110 static void
111 fetch_nwfpe_double (unsigned int fn, FPA11 * fpa11)
113 unsigned int mem[3];
115 mem[0] = fpa11->fpreg[fn].fDouble[1];
116 mem[1] = fpa11->fpreg[fn].fDouble[0];
117 mem[2] = 0;
118 supply_register (F0_REGNUM + fn, (char *) &mem[0]);
121 static void
122 fetch_nwfpe_none (unsigned int fn)
124 unsigned int mem[3] =
125 {0, 0, 0};
127 supply_register (F0_REGNUM + fn, (char *) &mem[0]);
130 static void
131 fetch_nwfpe_extended (unsigned int fn, FPA11 * fpa11)
133 unsigned int mem[3];
135 mem[0] = fpa11->fpreg[fn].fExtended[0]; /* sign & exponent */
136 mem[1] = fpa11->fpreg[fn].fExtended[2]; /* ls bits */
137 mem[2] = fpa11->fpreg[fn].fExtended[1]; /* ms bits */
138 supply_register (F0_REGNUM + fn, (char *) &mem[0]);
141 static void
142 fetch_nwfpe_register (int regno, FPA11 * fpa11)
144 int fn = regno - F0_REGNUM;
146 switch (fpa11->fType[fn])
148 case typeSingle:
149 fetch_nwfpe_single (fn, fpa11);
150 break;
152 case typeDouble:
153 fetch_nwfpe_double (fn, fpa11);
154 break;
156 case typeExtended:
157 fetch_nwfpe_extended (fn, fpa11);
158 break;
160 default:
161 fetch_nwfpe_none (fn);
165 static void
166 store_nwfpe_single (unsigned int fn, FPA11 * fpa11)
168 unsigned int mem[3];
170 read_register_gen (F0_REGNUM + fn, (char *) &mem[0]);
171 fpa11->fpreg[fn].fSingle = mem[0];
172 fpa11->fType[fn] = typeSingle;
175 static void
176 store_nwfpe_double (unsigned int fn, FPA11 * fpa11)
178 unsigned int mem[3];
180 read_register_gen (F0_REGNUM + fn, (char *) &mem[0]);
181 fpa11->fpreg[fn].fDouble[1] = mem[0];
182 fpa11->fpreg[fn].fDouble[0] = mem[1];
183 fpa11->fType[fn] = typeDouble;
186 void
187 store_nwfpe_extended (unsigned int fn, FPA11 * fpa11)
189 unsigned int mem[3];
191 read_register_gen (F0_REGNUM + fn, (char *) &mem[0]);
192 fpa11->fpreg[fn].fExtended[0] = mem[0]; /* sign & exponent */
193 fpa11->fpreg[fn].fExtended[2] = mem[1]; /* ls bits */
194 fpa11->fpreg[fn].fExtended[1] = mem[2]; /* ms bits */
195 fpa11->fType[fn] = typeDouble;
198 void
199 store_nwfpe_register (int regno, FPA11 * fpa11)
201 if (register_valid[regno])
203 unsigned int fn = regno - F0_REGNUM;
204 switch (fpa11->fType[fn])
206 case typeSingle:
207 store_nwfpe_single (fn, fpa11);
208 break;
210 case typeDouble:
211 store_nwfpe_double (fn, fpa11);
212 break;
214 case typeExtended:
215 store_nwfpe_extended (fn, fpa11);
216 break;
222 /* Get the value of a particular register from the floating point
223 state of the process and store it into registers[]. */
225 static void
226 fetch_fpregister (int regno)
228 int ret, tid;
229 FPA11 fp;
231 /* Get the thread id for the ptrace call. */
232 tid = GET_THREAD_ID (inferior_pid);
234 /* Read the floating point state. */
235 ret = ptrace (PT_GETFPREGS, tid, 0, &fp);
236 if (ret < 0)
238 warning ("Unable to fetch floating point register.");
239 return;
242 /* Fetch fpsr. */
243 if (FPS_REGNUM == regno)
244 supply_register (FPS_REGNUM, (char *) &fp.fpsr);
246 /* Fetch the floating point register. */
247 if (regno >= F0_REGNUM && regno <= F7_REGNUM)
249 int fn = regno - F0_REGNUM;
251 switch (fp.fType[fn])
253 case typeSingle:
254 fetch_nwfpe_single (fn, &fp);
255 break;
257 case typeDouble:
258 fetch_nwfpe_double (fn, &fp);
259 break;
261 case typeExtended:
262 fetch_nwfpe_extended (fn, &fp);
263 break;
265 default:
266 fetch_nwfpe_none (fn);
271 /* Get the whole floating point state of the process and store it
272 into registers[]. */
274 static void
275 fetch_fpregs (void)
277 int ret, regno, tid;
278 FPA11 fp;
280 /* Get the thread id for the ptrace call. */
281 tid = GET_THREAD_ID (inferior_pid);
283 /* Read the floating point state. */
284 ret = ptrace (PT_GETFPREGS, tid, 0, &fp);
285 if (ret < 0)
287 warning ("Unable to fetch the floating point registers.");
288 return;
291 /* Fetch fpsr. */
292 supply_register (FPS_REGNUM, (char *) &fp.fpsr);
294 /* Fetch the floating point registers. */
295 for (regno = F0_REGNUM; regno <= F7_REGNUM; regno++)
297 int fn = regno - F0_REGNUM;
299 switch (fp.fType[fn])
301 case typeSingle:
302 fetch_nwfpe_single (fn, &fp);
303 break;
305 case typeDouble:
306 fetch_nwfpe_double (fn, &fp);
307 break;
309 case typeExtended:
310 fetch_nwfpe_extended (fn, &fp);
311 break;
313 default:
314 fetch_nwfpe_none (fn);
319 /* Save a particular register into the floating point state of the
320 process using the contents from registers[]. */
322 static void
323 store_fpregister (int regno)
325 int ret, tid;
326 FPA11 fp;
328 /* Get the thread id for the ptrace call. */
329 tid = GET_THREAD_ID (inferior_pid);
331 /* Read the floating point state. */
332 ret = ptrace (PT_GETFPREGS, tid, 0, &fp);
333 if (ret < 0)
335 warning ("Unable to fetch the floating point registers.");
336 return;
339 /* Store fpsr. */
340 if (FPS_REGNUM == regno && register_valid[FPS_REGNUM])
341 read_register_gen (FPS_REGNUM, (char *) &fp.fpsr);
343 /* Store the floating point register. */
344 if (regno >= F0_REGNUM && regno <= F7_REGNUM)
346 store_nwfpe_register (regno, &fp);
349 ret = ptrace (PTRACE_SETFPREGS, tid, 0, &fp);
350 if (ret < 0)
352 warning ("Unable to store floating point register.");
353 return;
357 /* Save the whole floating point state of the process using
358 the contents from registers[]. */
360 static void
361 store_fpregs (void)
363 int ret, regno, tid;
364 FPA11 fp;
366 /* Get the thread id for the ptrace call. */
367 tid = GET_THREAD_ID (inferior_pid);
369 /* Read the floating point state. */
370 ret = ptrace (PT_GETFPREGS, tid, 0, &fp);
371 if (ret < 0)
373 warning ("Unable to fetch the floating point registers.");
374 return;
377 /* Store fpsr. */
378 if (register_valid[FPS_REGNUM])
379 read_register_gen (FPS_REGNUM, (char *) &fp.fpsr);
381 /* Store the floating point registers. */
382 for (regno = F0_REGNUM; regno <= F7_REGNUM; regno++)
384 fetch_nwfpe_register (regno, &fp);
387 ret = ptrace (PTRACE_SETFPREGS, tid, 0, &fp);
388 if (ret < 0)
390 warning ("Unable to store floating point registers.");
391 return;
395 /* Fetch a general register of the process and store into
396 registers[]. */
398 static void
399 fetch_register (int regno)
401 int ret, tid;
402 struct pt_regs regs;
404 /* Get the thread id for the ptrace call. */
405 tid = GET_THREAD_ID (inferior_pid);
407 ret = ptrace (PTRACE_GETREGS, tid, 0, &regs);
408 if (ret < 0)
410 warning ("Unable to fetch general register.");
411 return;
414 if (regno >= A1_REGNUM && regno < PC_REGNUM)
415 supply_register (regno, (char *) &regs.uregs[regno]);
417 if (PS_REGNUM == regno)
419 if (arm_apcs_32)
420 supply_register (PS_REGNUM, (char *) &regs.uregs[CPSR_REGNUM]);
421 else
422 supply_register (PS_REGNUM, (char *) &regs.uregs[PC_REGNUM]);
425 if (PC_REGNUM == regno)
427 regs.uregs[PC_REGNUM] = ADDR_BITS_REMOVE (regs.uregs[PC_REGNUM]);
428 supply_register (PC_REGNUM, (char *) &regs.uregs[PC_REGNUM]);
432 /* Fetch all general registers of the process and store into
433 registers[]. */
435 static void
436 fetch_regs (void)
438 int ret, regno, tid;
439 struct pt_regs regs;
441 /* Get the thread id for the ptrace call. */
442 tid = GET_THREAD_ID (inferior_pid);
444 ret = ptrace (PTRACE_GETREGS, tid, 0, &regs);
445 if (ret < 0)
447 warning ("Unable to fetch general registers.");
448 return;
451 for (regno = A1_REGNUM; regno < PC_REGNUM; regno++)
452 supply_register (regno, (char *) &regs.uregs[regno]);
454 if (arm_apcs_32)
455 supply_register (PS_REGNUM, (char *) &regs.uregs[CPSR_REGNUM]);
456 else
457 supply_register (PS_REGNUM, (char *) &regs.uregs[PC_REGNUM]);
459 regs.uregs[PC_REGNUM] = ADDR_BITS_REMOVE (regs.uregs[PC_REGNUM]);
460 supply_register (PC_REGNUM, (char *) &regs.uregs[PC_REGNUM]);
463 /* Store all general registers of the process from the values in
464 registers[]. */
466 static void
467 store_register (int regno)
469 int ret, tid;
470 struct pt_regs regs;
472 if (!register_valid[regno])
473 return;
475 /* Get the thread id for the ptrace call. */
476 tid = GET_THREAD_ID (inferior_pid);
478 /* Get the general registers from the process. */
479 ret = ptrace (PTRACE_GETREGS, tid, 0, &regs);
480 if (ret < 0)
482 warning ("Unable to fetch general registers.");
483 return;
486 if (regno >= A1_REGNUM && regno <= PC_REGNUM)
487 read_register_gen (regno, (char *) &regs.uregs[regno]);
489 ret = ptrace (PTRACE_SETREGS, tid, 0, &regs);
490 if (ret < 0)
492 warning ("Unable to store general register.");
493 return;
497 static void
498 store_regs (void)
500 int ret, regno, tid;
501 struct pt_regs regs;
503 /* Get the thread id for the ptrace call. */
504 tid = GET_THREAD_ID (inferior_pid);
506 /* Fetch the general registers. */
507 ret = ptrace (PTRACE_GETREGS, tid, 0, &regs);
508 if (ret < 0)
510 warning ("Unable to fetch general registers.");
511 return;
514 for (regno = A1_REGNUM; regno <= PC_REGNUM; regno++)
516 if (register_valid[regno])
517 read_register_gen (regno, (char *) &regs.uregs[regno]);
520 ret = ptrace (PTRACE_SETREGS, tid, 0, &regs);
522 if (ret < 0)
524 warning ("Unable to store general registers.");
525 return;
529 /* Fetch registers from the child process. Fetch all registers if
530 regno == -1, otherwise fetch all general registers or all floating
531 point registers depending upon the value of regno. */
533 void
534 fetch_inferior_registers (int regno)
536 if (-1 == regno)
538 fetch_regs ();
539 fetch_fpregs ();
541 else
543 if (regno < F0_REGNUM || regno > FPS_REGNUM)
544 fetch_register (regno);
546 if (regno >= F0_REGNUM && regno <= FPS_REGNUM)
547 fetch_fpregister (regno);
551 /* Store registers back into the inferior. Store all registers if
552 regno == -1, otherwise store all general registers or all floating
553 point registers depending upon the value of regno. */
555 void
556 store_inferior_registers (int regno)
558 if (-1 == regno)
560 store_regs ();
561 store_fpregs ();
563 else
565 if ((regno < F0_REGNUM) || (regno > FPS_REGNUM))
566 store_register (regno);
568 if ((regno >= F0_REGNUM) && (regno <= FPS_REGNUM))
569 store_fpregister (regno);
573 /* Fill register regno (if it is a general-purpose register) in
574 *gregsetp with the appropriate value from GDB's register array.
575 If regno is -1, do this for all registers. */
577 void
578 fill_gregset (gregset_t *gregsetp, int regno)
580 if (-1 == regno)
582 int regnum;
583 for (regnum = A1_REGNUM; regnum <= PC_REGNUM; regnum++)
584 if (register_valid[regnum])
585 read_register_gen (regnum, (char *) &(*gregsetp)[regnum]);
587 else if (regno >= A1_REGNUM && regno <= PC_REGNUM)
589 if (register_valid[regno])
590 read_register_gen (regno, (char *) &(*gregsetp)[regno]);
593 if (PS_REGNUM == regno || -1 == regno)
595 if (register_valid[regno] || -1 == regno)
597 if (arm_apcs_32)
598 read_register_gen (PS_REGNUM, (char *) &(*gregsetp)[CPSR_REGNUM]);
599 else
600 read_register_gen (PC_REGNUM, (char *) &(*gregsetp)[PC_REGNUM]);
606 /* Fill GDB's register array with the general-purpose register values
607 in *gregsetp. */
609 void
610 supply_gregset (gregset_t *gregsetp)
612 int regno, reg_pc;
614 for (regno = A1_REGNUM; regno < PC_REGNUM; regno++)
615 supply_register (regno, (char *) &(*gregsetp)[regno]);
617 if (arm_apcs_32)
618 supply_register (PS_REGNUM, (char *) &(*gregsetp)[CPSR_REGNUM]);
619 else
620 supply_register (PS_REGNUM, (char *) &(*gregsetp)[PC_REGNUM]);
622 reg_pc = ADDR_BITS_REMOVE ((CORE_ADDR)(*gregsetp)[PC_REGNUM]);
623 supply_register (PC_REGNUM, (char *) &reg_pc);
626 /* Fill register regno (if it is a floating-point register) in
627 *fpregsetp with the appropriate value from GDB's register array.
628 If regno is -1, do this for all registers. */
630 void
631 fill_fpregset (fpregset_t *fpregsetp, int regno)
633 FPA11 *fp = (FPA11 *) fpregsetp;
635 if (-1 == regno)
637 int regnum;
638 for (regnum = F0_REGNUM; regnum <= F7_REGNUM; regnum++)
639 store_nwfpe_register (regnum, fp);
641 else if (regno >= F0_REGNUM && regno <= F7_REGNUM)
643 store_nwfpe_register (regno, fp);
644 return;
647 /* Store fpsr. */
648 if (register_valid[FPS_REGNUM])
649 if (FPS_REGNUM == regno || -1 == regno)
650 read_register_gen (FPS_REGNUM, (char *) &fp->fpsr);
653 /* Fill GDB's register array with the floating-point register values
654 in *fpregsetp. */
656 void
657 supply_fpregset (fpregset_t *fpregsetp)
659 int regno;
660 FPA11 *fp = (FPA11 *) fpregsetp;
662 /* Fetch fpsr. */
663 supply_register (FPS_REGNUM, (char *) &fp->fpsr);
665 /* Fetch the floating point registers. */
666 for (regno = F0_REGNUM; regno <= F7_REGNUM; regno++)
668 fetch_nwfpe_register (regno, fp);
673 arm_linux_kernel_u_size (void)
675 return (sizeof (struct user));
678 static unsigned int
679 get_linux_version (unsigned int *vmajor,
680 unsigned int *vminor,
681 unsigned int *vrelease)
683 struct utsname info;
684 char *pmajor, *pminor, *prelease, *tail;
686 if (-1 == uname (&info))
688 warning ("Unable to determine Linux version.");
689 return -1;
692 pmajor = strtok (info.release, ".");
693 pminor = strtok (NULL, ".");
694 prelease = strtok (NULL, ".");
696 *vmajor = (unsigned int) strtoul (pmajor, &tail, 0);
697 *vminor = (unsigned int) strtoul (pminor, &tail, 0);
698 *vrelease = (unsigned int) strtoul (prelease, &tail, 0);
700 return ((*vmajor << 16) | (*vminor << 8) | *vrelease);
703 void
704 _initialize_arm_linux_nat (void)
706 os_version = get_linux_version (&os_major, &os_minor, &os_release);