This commit was generated by cvs2svn to track changes on a CVS vendor
[platform/upstream/binutils.git] / gdb / arm-linux-nat.c
1 /* GNU/Linux on ARM native support.
2    Copyright 1999, 2000 Free Software Foundation, Inc.
3
4    This file is part of GDB.
5
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.
10
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.
15
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.  */
20
21 #include "defs.h"
22 #include "inferior.h"
23 #include "gdbcore.h"
24 #include "gdb_string.h"
25
26 #include <sys/user.h>
27 #include <sys/ptrace.h>
28 #include <sys/utsname.h>
29 #include <sys/procfs.h>
30
31 /* Prototypes for supply_gregset etc. */
32 #include "gregset.h"
33
34 extern int arm_apcs_32;
35
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
42
43 typedef union tagFPREG
44   {
45     unsigned int fSingle;
46     unsigned int fDouble[2];
47     unsigned int fExtended[3];
48   }
49 FPREG;
50
51 typedef struct tagFPA11
52   {
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.  */
59   }
60 FPA11;
61
62 /* The following variables are used to determine the version of the
63    underlying Linux operating system.  Examples:
64
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
70
71    Note: os_version = (os_major << 16) | (os_minor << 8) | os_release
72
73    These are initialized using get_linux_version() from
74    _initialize_arm_linux_nat().  */
75
76 static unsigned int os_version, os_major, os_minor, os_release;
77
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.  */
84
85 #if !defined (PIDGET)   /* Default definition for PIDGET/TIDGET.  */
86 #define PIDGET(PID)     PID
87 #define TIDGET(PID)     0
88 #endif
89
90 int
91 get_thread_id (int inferior_pid)
92 {
93   int tid = TIDGET (inferior_pid);
94   if (0 == tid) tid = inferior_pid;
95   return tid;
96 }
97 #define GET_THREAD_ID(PID)      get_thread_id ((PID));
98
99 static void
100 fetch_nwfpe_single (unsigned int fn, FPA11 * fpa11)
101 {
102   unsigned int mem[3];
103
104   mem[0] = fpa11->fpreg[fn].fSingle;
105   mem[1] = 0;
106   mem[2] = 0;
107   supply_register (F0_REGNUM + fn, (char *) &mem[0]);
108 }
109
110 static void
111 fetch_nwfpe_double (unsigned int fn, FPA11 * fpa11)
112 {
113   unsigned int mem[3];
114
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]);
119 }
120
121 static void
122 fetch_nwfpe_none (unsigned int fn)
123 {
124   unsigned int mem[3] =
125   {0, 0, 0};
126
127   supply_register (F0_REGNUM + fn, (char *) &mem[0]);
128 }
129
130 static void
131 fetch_nwfpe_extended (unsigned int fn, FPA11 * fpa11)
132 {
133   unsigned int mem[3];
134
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]);
139 }
140
141 static void
142 fetch_nwfpe_register (int regno, FPA11 * fpa11)
143 {
144    int fn = regno - F0_REGNUM;
145
146    switch (fpa11->fType[fn])
147      {
148      case typeSingle:
149        fetch_nwfpe_single (fn, fpa11);
150        break;
151
152      case typeDouble:
153        fetch_nwfpe_double (fn, fpa11);
154        break;
155
156      case typeExtended:
157        fetch_nwfpe_extended (fn, fpa11);
158        break;
159
160      default:
161        fetch_nwfpe_none (fn);
162      }
163 }
164
165 static void
166 store_nwfpe_single (unsigned int fn, FPA11 * fpa11)
167 {
168   unsigned int mem[3];
169
170   read_register_gen (F0_REGNUM + fn, (char *) &mem[0]);
171   fpa11->fpreg[fn].fSingle = mem[0];
172   fpa11->fType[fn] = typeSingle;
173 }
174
175 static void
176 store_nwfpe_double (unsigned int fn, FPA11 * fpa11)
177 {
178   unsigned int mem[3];
179
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;
184 }
185
186 void
187 store_nwfpe_extended (unsigned int fn, FPA11 * fpa11)
188 {
189   unsigned int mem[3];
190
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;
196 }
197
198 void
199 store_nwfpe_register (int regno, FPA11 * fpa11)
200 {
201   if (register_valid[regno])
202     {
203        unsigned int fn = regno - F0_REGNUM;
204        switch (fpa11->fType[fn])
205          {
206          case typeSingle:
207            store_nwfpe_single (fn, fpa11);
208            break;
209
210          case typeDouble:
211            store_nwfpe_double (fn, fpa11);
212            break;
213
214          case typeExtended:
215            store_nwfpe_extended (fn, fpa11);
216            break;
217          }
218     }
219 }
220
221
222 /* Get the value of a particular register from the floating point
223    state of the process and store it into registers[].  */
224
225 static void
226 fetch_fpregister (int regno)
227 {
228   int ret, tid;
229   FPA11 fp;
230   
231   /* Get the thread id for the ptrace call.  */
232   tid = GET_THREAD_ID (inferior_pid);
233
234   /* Read the floating point state.  */
235   ret = ptrace (PT_GETFPREGS, tid, 0, &fp);
236   if (ret < 0)
237     {
238       warning ("Unable to fetch floating point register.");
239       return;
240     }
241
242   /* Fetch fpsr.  */
243   if (FPS_REGNUM == regno)
244     supply_register (FPS_REGNUM, (char *) &fp.fpsr);
245
246   /* Fetch the floating point register.  */
247   if (regno >= F0_REGNUM && regno <= F7_REGNUM)
248     {
249       int fn = regno - F0_REGNUM;
250
251       switch (fp.fType[fn])
252         {
253         case typeSingle:
254           fetch_nwfpe_single (fn, &fp);
255           break;
256
257         case typeDouble:
258             fetch_nwfpe_double (fn, &fp);
259           break;
260
261         case typeExtended:
262             fetch_nwfpe_extended (fn, &fp);
263           break;
264
265         default:
266             fetch_nwfpe_none (fn);
267         }
268     }
269 }
270
271 /* Get the whole floating point state of the process and store it
272    into registers[].  */
273
274 static void
275 fetch_fpregs (void)
276 {
277   int ret, regno, tid;
278   FPA11 fp;
279
280   /* Get the thread id for the ptrace call.  */
281   tid = GET_THREAD_ID (inferior_pid);
282   
283   /* Read the floating point state.  */
284   ret = ptrace (PT_GETFPREGS, tid, 0, &fp);
285   if (ret < 0)
286     {
287       warning ("Unable to fetch the floating point registers.");
288       return;
289     }
290
291   /* Fetch fpsr.  */
292   supply_register (FPS_REGNUM, (char *) &fp.fpsr);
293
294   /* Fetch the floating point registers.  */
295   for (regno = F0_REGNUM; regno <= F7_REGNUM; regno++)
296     {
297       int fn = regno - F0_REGNUM;
298
299       switch (fp.fType[fn])
300         {
301         case typeSingle:
302           fetch_nwfpe_single (fn, &fp);
303           break;
304
305         case typeDouble:
306           fetch_nwfpe_double (fn, &fp);
307           break;
308
309         case typeExtended:
310           fetch_nwfpe_extended (fn, &fp);
311           break;
312
313         default:
314           fetch_nwfpe_none (fn);
315         }
316     }
317 }
318
319 /* Save a particular register into the floating point state of the
320    process using the contents from registers[].  */
321
322 static void
323 store_fpregister (int regno)
324 {
325   int ret, tid;
326   FPA11 fp;
327
328   /* Get the thread id for the ptrace call.  */
329   tid = GET_THREAD_ID (inferior_pid);
330   
331   /* Read the floating point state.  */
332   ret = ptrace (PT_GETFPREGS, tid, 0, &fp);
333   if (ret < 0)
334     {
335       warning ("Unable to fetch the floating point registers.");
336       return;
337     }
338
339   /* Store fpsr.  */
340   if (FPS_REGNUM == regno && register_valid[FPS_REGNUM])
341     read_register_gen (FPS_REGNUM, (char *) &fp.fpsr);
342
343   /* Store the floating point register.  */
344   if (regno >= F0_REGNUM && regno <= F7_REGNUM)
345     {
346       store_nwfpe_register (regno, &fp);
347     }
348
349   ret = ptrace (PTRACE_SETFPREGS, tid, 0, &fp);
350   if (ret < 0)
351     {
352       warning ("Unable to store floating point register.");
353       return;
354     }
355 }
356
357 /* Save the whole floating point state of the process using
358    the contents from registers[].  */
359
360 static void
361 store_fpregs (void)
362 {
363   int ret, regno, tid;
364   FPA11 fp;
365
366   /* Get the thread id for the ptrace call.  */
367   tid = GET_THREAD_ID (inferior_pid);
368   
369   /* Read the floating point state.  */
370   ret = ptrace (PT_GETFPREGS, tid, 0, &fp);
371   if (ret < 0)
372     {
373       warning ("Unable to fetch the floating point registers.");
374       return;
375     }
376
377   /* Store fpsr.  */
378   if (register_valid[FPS_REGNUM])
379     read_register_gen (FPS_REGNUM, (char *) &fp.fpsr);
380
381   /* Store the floating point registers.  */
382   for (regno = F0_REGNUM; regno <= F7_REGNUM; regno++)
383     {
384       fetch_nwfpe_register (regno, &fp);
385     }
386
387   ret = ptrace (PTRACE_SETFPREGS, tid, 0, &fp);
388   if (ret < 0)
389     {
390       warning ("Unable to store floating point registers.");
391       return;
392     }
393 }
394
395 /* Fetch a general register of the process and store into
396    registers[].  */
397
398 static void
399 fetch_register (int regno)
400 {
401   int ret, tid;
402   struct pt_regs regs;
403
404   /* Get the thread id for the ptrace call.  */
405   tid = GET_THREAD_ID (inferior_pid);
406   
407   ret = ptrace (PTRACE_GETREGS, tid, 0, &regs);
408   if (ret < 0)
409     {
410       warning ("Unable to fetch general register.");
411       return;
412     }
413
414   if (regno >= A1_REGNUM && regno < PC_REGNUM)
415     supply_register (regno, (char *) &regs.uregs[regno]);
416
417   if (PS_REGNUM == regno)
418     {
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]);
423     }
424     
425   if (PC_REGNUM == regno)
426     { 
427       regs.uregs[PC_REGNUM] = ADDR_BITS_REMOVE (regs.uregs[PC_REGNUM]);
428       supply_register (PC_REGNUM, (char *) &regs.uregs[PC_REGNUM]);
429     }
430 }
431
432 /* Fetch all general registers of the process and store into
433    registers[].  */
434
435 static void
436 fetch_regs (void)
437 {
438   int ret, regno, tid;
439   struct pt_regs regs;
440
441   /* Get the thread id for the ptrace call.  */
442   tid = GET_THREAD_ID (inferior_pid);
443   
444   ret = ptrace (PTRACE_GETREGS, tid, 0, &regs);
445   if (ret < 0)
446     {
447       warning ("Unable to fetch general registers.");
448       return;
449     }
450
451   for (regno = A1_REGNUM; regno < PC_REGNUM; regno++)
452     supply_register (regno, (char *) &regs.uregs[regno]);
453
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]);
458
459   regs.uregs[PC_REGNUM] = ADDR_BITS_REMOVE (regs.uregs[PC_REGNUM]);
460   supply_register (PC_REGNUM, (char *) &regs.uregs[PC_REGNUM]);
461 }
462
463 /* Store all general registers of the process from the values in
464    registers[].  */
465
466 static void
467 store_register (int regno)
468 {
469   int ret, tid;
470   struct pt_regs regs;
471   
472   if (!register_valid[regno])
473     return;
474
475   /* Get the thread id for the ptrace call.  */
476   tid = GET_THREAD_ID (inferior_pid);
477   
478   /* Get the general registers from the process.  */
479   ret = ptrace (PTRACE_GETREGS, tid, 0, &regs);
480   if (ret < 0)
481     {
482       warning ("Unable to fetch general registers.");
483       return;
484     }
485
486   if (regno >= A1_REGNUM && regno <= PC_REGNUM)
487     read_register_gen (regno, (char *) &regs.uregs[regno]);
488
489   ret = ptrace (PTRACE_SETREGS, tid, 0, &regs);
490   if (ret < 0)
491     {
492       warning ("Unable to store general register.");
493       return;
494     }
495 }
496
497 static void
498 store_regs (void)
499 {
500   int ret, regno, tid;
501   struct pt_regs regs;
502
503   /* Get the thread id for the ptrace call.  */
504   tid = GET_THREAD_ID (inferior_pid);
505   
506   /* Fetch the general registers.  */
507   ret = ptrace (PTRACE_GETREGS, tid, 0, &regs);
508   if (ret < 0)
509     {
510       warning ("Unable to fetch general registers.");
511       return;
512     }
513
514   for (regno = A1_REGNUM; regno <= PC_REGNUM; regno++)
515     {
516       if (register_valid[regno])
517         read_register_gen (regno, (char *) &regs.uregs[regno]);
518     }
519
520   ret = ptrace (PTRACE_SETREGS, tid, 0, &regs);
521
522   if (ret < 0)
523     {
524       warning ("Unable to store general registers.");
525       return;
526     }
527 }
528
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.  */
532
533 void
534 fetch_inferior_registers (int regno)
535 {
536   if (-1 == regno)
537     {
538       fetch_regs ();
539       fetch_fpregs ();
540     }
541   else 
542     {
543       if (regno < F0_REGNUM || regno > FPS_REGNUM)
544         fetch_register (regno);
545
546       if (regno >= F0_REGNUM && regno <= FPS_REGNUM)
547         fetch_fpregister (regno);
548     }
549 }
550
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.  */
554
555 void
556 store_inferior_registers (int regno)
557 {
558   if (-1 == regno)
559     {
560       store_regs ();
561       store_fpregs ();
562     }
563   else
564     {
565       if ((regno < F0_REGNUM) || (regno > FPS_REGNUM))
566         store_register (regno);
567
568       if ((regno >= F0_REGNUM) && (regno <= FPS_REGNUM))
569         store_fpregister (regno);
570     }
571 }
572
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.  */
576
577 void
578 fill_gregset (gregset_t *gregsetp, int regno)
579 {
580   if (-1 == regno)
581     {
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]);
586     }
587   else if (regno >= A1_REGNUM && regno <= PC_REGNUM)
588     {
589       if (register_valid[regno])
590         read_register_gen (regno, (char *) &(*gregsetp)[regno]);
591     }
592
593   if (PS_REGNUM == regno || -1 == regno)
594     {
595       if (register_valid[regno] || -1 == regno)
596         {
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]);
601         }
602     }
603         
604 }
605
606 /* Fill GDB's register array with the general-purpose register values
607    in *gregsetp.  */
608
609 void
610 supply_gregset (gregset_t *gregsetp)
611 {
612   int regno, reg_pc;
613
614   for (regno = A1_REGNUM; regno < PC_REGNUM; regno++)
615     supply_register (regno, (char *) &(*gregsetp)[regno]);
616
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]);
621
622   reg_pc = ADDR_BITS_REMOVE ((CORE_ADDR)(*gregsetp)[PC_REGNUM]);
623   supply_register (PC_REGNUM, (char *) &reg_pc);
624 }
625
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.  */
629
630 void
631 fill_fpregset (fpregset_t *fpregsetp, int regno)
632 {
633   FPA11 *fp = (FPA11 *) fpregsetp;
634   
635   if (-1 == regno)
636     {
637        int regnum;
638        for (regnum = F0_REGNUM; regnum <= F7_REGNUM; regnum++)
639          store_nwfpe_register (regnum, fp);
640     }
641   else if (regno >= F0_REGNUM && regno <= F7_REGNUM)
642     {
643       store_nwfpe_register (regno, fp);
644       return;
645     }
646
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);
651 }
652
653 /* Fill GDB's register array with the floating-point register values
654    in *fpregsetp.  */
655
656 void
657 supply_fpregset (fpregset_t *fpregsetp)
658 {
659   int regno;
660   FPA11 *fp = (FPA11 *) fpregsetp;
661
662   /* Fetch fpsr.  */
663   supply_register (FPS_REGNUM, (char *) &fp->fpsr);
664
665   /* Fetch the floating point registers.  */
666   for (regno = F0_REGNUM; regno <= F7_REGNUM; regno++)
667     {
668       fetch_nwfpe_register (regno, fp);
669     }
670 }
671
672 int
673 arm_linux_kernel_u_size (void)
674 {
675   return (sizeof (struct user));
676 }
677
678 static unsigned int
679 get_linux_version (unsigned int *vmajor,
680                    unsigned int *vminor,
681                    unsigned int *vrelease)
682 {
683   struct utsname info;
684   char *pmajor, *pminor, *prelease, *tail;
685
686   if (-1 == uname (&info))
687     {
688       warning ("Unable to determine Linux version.");
689       return -1;
690     }
691
692   pmajor = strtok (info.release, ".");
693   pminor = strtok (NULL, ".");
694   prelease = strtok (NULL, ".");
695
696   *vmajor = (unsigned int) strtoul (pmajor, &tail, 0);
697   *vminor = (unsigned int) strtoul (pminor, &tail, 0);
698   *vrelease = (unsigned int) strtoul (prelease, &tail, 0);
699
700   return ((*vmajor << 16) | (*vminor << 8) | *vrelease);
701 }
702
703 void
704 _initialize_arm_linux_nat (void)
705 {
706   os_version = get_linux_version (&os_major, &os_minor, &os_release);
707 }