OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [gdb/] [arm-linux-nat.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 104 markom
/* 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
extern int arm_apcs_32;
32
 
33
#define         typeNone                0x00
34
#define         typeSingle              0x01
35
#define         typeDouble              0x02
36
#define         typeExtended            0x03
37
#define         FPWORDS                 28
38
#define         CPSR_REGNUM             16
39
 
40
typedef union tagFPREG
41
  {
42
    unsigned int fSingle;
43
    unsigned int fDouble[2];
44
    unsigned int fExtended[3];
45
  }
46
FPREG;
47
 
48
typedef struct tagFPA11
49
  {
50
    FPREG fpreg[8];             /* 8 floating point registers */
51
    unsigned int fpsr;          /* floating point status register */
52
    unsigned int fpcr;          /* floating point control register */
53
    unsigned char fType[8];     /* type of floating point value held in
54
                                   floating point registers.  */
55
    int initflag;               /* NWFPE initialization flag.  */
56
  }
57
FPA11;
58
 
59
/* The following variables are used to determine the version of the
60
   underlying Linux operating system.  Examples:
61
 
62
   Linux 2.0.35                 Linux 2.2.12
63
   os_version = 0x00020023      os_version = 0x0002020c
64
   os_major = 2                 os_major = 2
65
   os_minor = 0                 os_minor = 2
66
   os_release = 35              os_release = 12
67
 
68
   Note: os_version = (os_major << 16) | (os_minor << 8) | os_release
69
 
70
   These are initialized using get_linux_version() from
71
   _initialize_arm_linux_nat().  */
72
 
73
static unsigned int os_version, os_major, os_minor, os_release;
74
 
75
/* On Linux, threads are implemented as pseudo-processes, in which
76
   case we may be tracing more than one process at a time.  In that
77
   case, inferior_pid will contain the main process ID and the
78
   individual thread (process) ID mashed together.  These macros are
79
   used to separate them out.  These definitions should be overridden
80
   if thread support is included.  */
81
 
82
#if !defined (PIDGET)   /* Default definition for PIDGET/TIDGET.  */
83
#define PIDGET(PID)     PID
84
#define TIDGET(PID)     0
85
#endif
86
 
87
int
88
get_thread_id (int inferior_pid)
89
{
90
  int tid = TIDGET (inferior_pid);
91
  if (0 == tid) tid = inferior_pid;
92
  return tid;
93
}
94
#define GET_THREAD_ID(PID)      get_thread_id ((PID));
95
 
96
static void
97
fetch_nwfpe_single (unsigned int fn, FPA11 * fpa11)
98
{
99
  unsigned int mem[3];
100
 
101
  mem[0] = fpa11->fpreg[fn].fSingle;
102
  mem[1] = 0;
103
  mem[2] = 0;
104
  supply_register (F0_REGNUM + fn, (char *) &mem[0]);
105
}
106
 
107
static void
108
fetch_nwfpe_double (unsigned int fn, FPA11 * fpa11)
109
{
110
  unsigned int mem[3];
111
 
112
  mem[0] = fpa11->fpreg[fn].fDouble[1];
113
  mem[1] = fpa11->fpreg[fn].fDouble[0];
114
  mem[2] = 0;
115
  supply_register (F0_REGNUM + fn, (char *) &mem[0]);
116
}
117
 
118
static void
119
fetch_nwfpe_none (unsigned int fn)
120
{
121
  unsigned int mem[3] =
122
  {0, 0, 0};
123
 
124
  supply_register (F0_REGNUM + fn, (char *) &mem[0]);
125
}
126
 
127
static void
128
fetch_nwfpe_extended (unsigned int fn, FPA11 * fpa11)
129
{
130
  unsigned int mem[3];
131
 
132
  mem[0] = fpa11->fpreg[fn].fExtended[0]; /* sign & exponent */
133
  mem[1] = fpa11->fpreg[fn].fExtended[2];       /* ls bits */
134
  mem[2] = fpa11->fpreg[fn].fExtended[1];       /* ms bits */
135
  supply_register (F0_REGNUM + fn, (char *) &mem[0]);
136
}
137
 
138
static void
139
fetch_nwfpe_register (int regno, FPA11 * fpa11)
140
{
141
   int fn = regno - F0_REGNUM;
142
 
143
   switch (fpa11->fType[fn])
144
     {
145
     case typeSingle:
146
       fetch_nwfpe_single (fn, fpa11);
147
       break;
148
 
149
     case typeDouble:
150
       fetch_nwfpe_double (fn, fpa11);
151
       break;
152
 
153
     case typeExtended:
154
       fetch_nwfpe_extended (fn, fpa11);
155
       break;
156
 
157
     default:
158
       fetch_nwfpe_none (fn);
159
     }
160
}
161
 
162
static void
163
store_nwfpe_single (unsigned int fn, FPA11 * fpa11)
164
{
165
  unsigned int mem[3];
166
 
167
  read_register_gen (F0_REGNUM + fn, (char *) &mem[0]);
168
  fpa11->fpreg[fn].fSingle = mem[0];
169
  fpa11->fType[fn] = typeSingle;
170
}
171
 
172
static void
173
store_nwfpe_double (unsigned int fn, FPA11 * fpa11)
174
{
175
  unsigned int mem[3];
176
 
177
  read_register_gen (F0_REGNUM + fn, (char *) &mem[0]);
178
  fpa11->fpreg[fn].fDouble[1] = mem[0];
179
  fpa11->fpreg[fn].fDouble[0] = mem[1];
180
  fpa11->fType[fn] = typeDouble;
181
}
182
 
183
void
184
store_nwfpe_extended (unsigned int fn, FPA11 * fpa11)
185
{
186
  unsigned int mem[3];
187
 
188
  read_register_gen (F0_REGNUM + fn, (char *) &mem[0]);
189
  fpa11->fpreg[fn].fExtended[0] = mem[0]; /* sign & exponent */
190
  fpa11->fpreg[fn].fExtended[2] = mem[1];       /* ls bits */
191
  fpa11->fpreg[fn].fExtended[1] = mem[2];       /* ms bits */
192
  fpa11->fType[fn] = typeDouble;
193
}
194
 
195
void
196
store_nwfpe_register (int regno, FPA11 * fpa11)
197
{
198
  if (register_valid[regno])
199
    {
200
       unsigned int fn = regno - F0_REGNUM;
201
       switch (fpa11->fType[fn])
202
         {
203
         case typeSingle:
204
           store_nwfpe_single (fn, fpa11);
205
           break;
206
 
207
         case typeDouble:
208
           store_nwfpe_double (fn, fpa11);
209
           break;
210
 
211
         case typeExtended:
212
           store_nwfpe_extended (fn, fpa11);
213
           break;
214
         }
215
    }
216
}
217
 
218
 
219
/* Get the value of a particular register from the floating point
220
   state of the process and store it into registers[].  */
221
 
222
static void
223
fetch_fpregister (int regno)
224
{
225
  int ret, tid;
226
  FPA11 fp;
227
 
228
  /* Get the thread id for the ptrace call.  */
229
  tid = GET_THREAD_ID (inferior_pid);
230
 
231
  /* Read the floating point state.  */
232
  ret = ptrace (PT_GETFPREGS, tid, 0, &fp);
233
  if (ret < 0)
234
    {
235
      warning ("Unable to fetch floating point register.");
236
      return;
237
    }
238
 
239
  /* Fetch fpsr.  */
240
  if (FPS_REGNUM == regno)
241
    supply_register (FPS_REGNUM, (char *) &fp.fpsr);
242
 
243
  /* Fetch the floating point register.  */
244
  if (regno >= F0_REGNUM && regno <= F7_REGNUM)
245
    {
246
      int fn = regno - F0_REGNUM;
247
 
248
      switch (fp.fType[fn])
249
        {
250
        case typeSingle:
251
          fetch_nwfpe_single (fn, &fp);
252
          break;
253
 
254
        case typeDouble:
255
            fetch_nwfpe_double (fn, &fp);
256
          break;
257
 
258
        case typeExtended:
259
            fetch_nwfpe_extended (fn, &fp);
260
          break;
261
 
262
        default:
263
            fetch_nwfpe_none (fn);
264
        }
265
    }
266
}
267
 
268
/* Get the whole floating point state of the process and store it
269
   into registers[].  */
270
 
271
static void
272
fetch_fpregs (void)
273
{
274
  int ret, regno, tid;
275
  FPA11 fp;
276
 
277
  /* Get the thread id for the ptrace call.  */
278
  tid = GET_THREAD_ID (inferior_pid);
279
 
280
  /* Read the floating point state.  */
281
  ret = ptrace (PT_GETFPREGS, tid, 0, &fp);
282
  if (ret < 0)
283
    {
284
      warning ("Unable to fetch the floating point registers.");
285
      return;
286
    }
287
 
288
  /* Fetch fpsr.  */
289
  supply_register (FPS_REGNUM, (char *) &fp.fpsr);
290
 
291
  /* Fetch the floating point registers.  */
292
  for (regno = F0_REGNUM; regno <= F7_REGNUM; regno++)
293
    {
294
      int fn = regno - F0_REGNUM;
295
 
296
      switch (fp.fType[fn])
297
        {
298
        case typeSingle:
299
          fetch_nwfpe_single (fn, &fp);
300
          break;
301
 
302
        case typeDouble:
303
          fetch_nwfpe_double (fn, &fp);
304
          break;
305
 
306
        case typeExtended:
307
          fetch_nwfpe_extended (fn, &fp);
308
          break;
309
 
310
        default:
311
          fetch_nwfpe_none (fn);
312
        }
313
    }
314
}
315
 
316
/* Save a particular register into the floating point state of the
317
   process using the contents from registers[].  */
318
 
319
static void
320
store_fpregister (int regno)
321
{
322
  int ret, tid;
323
  FPA11 fp;
324
 
325
  /* Get the thread id for the ptrace call.  */
326
  tid = GET_THREAD_ID (inferior_pid);
327
 
328
  /* Read the floating point state.  */
329
  ret = ptrace (PT_GETFPREGS, tid, 0, &fp);
330
  if (ret < 0)
331
    {
332
      warning ("Unable to fetch the floating point registers.");
333
      return;
334
    }
335
 
336
  /* Store fpsr.  */
337
  if (FPS_REGNUM == regno && register_valid[FPS_REGNUM])
338
    read_register_gen (FPS_REGNUM, (char *) &fp.fpsr);
339
 
340
  /* Store the floating point register.  */
341
  if (regno >= F0_REGNUM && regno <= F7_REGNUM)
342
    {
343
      store_nwfpe_register (regno, &fp);
344
    }
345
 
346
  ret = ptrace (PTRACE_SETFPREGS, tid, 0, &fp);
347
  if (ret < 0)
348
    {
349
      warning ("Unable to store floating point register.");
350
      return;
351
    }
352
}
353
 
354
/* Save the whole floating point state of the process using
355
   the contents from registers[].  */
356
 
357
static void
358
store_fpregs (void)
359
{
360
  int ret, regno, tid;
361
  FPA11 fp;
362
 
363
  /* Get the thread id for the ptrace call.  */
364
  tid = GET_THREAD_ID (inferior_pid);
365
 
366
  /* Read the floating point state.  */
367
  ret = ptrace (PT_GETFPREGS, tid, 0, &fp);
368
  if (ret < 0)
369
    {
370
      warning ("Unable to fetch the floating point registers.");
371
      return;
372
    }
373
 
374
  /* Store fpsr.  */
375
  if (register_valid[FPS_REGNUM])
376
    read_register_gen (FPS_REGNUM, (char *) &fp.fpsr);
377
 
378
  /* Store the floating point registers.  */
379
  for (regno = F0_REGNUM; regno <= F7_REGNUM; regno++)
380
    {
381
      fetch_nwfpe_register (regno, &fp);
382
    }
383
 
384
  ret = ptrace (PTRACE_SETFPREGS, tid, 0, &fp);
385
  if (ret < 0)
386
    {
387
      warning ("Unable to store floating point registers.");
388
      return;
389
    }
390
}
391
 
392
/* Fetch a general register of the process and store into
393
   registers[].  */
394
 
395
static void
396
fetch_register (int regno)
397
{
398
  int ret, tid;
399
  struct pt_regs regs;
400
 
401
  /* Get the thread id for the ptrace call.  */
402
  tid = GET_THREAD_ID (inferior_pid);
403
 
404
  ret = ptrace (PTRACE_GETREGS, tid, 0, &regs);
405
  if (ret < 0)
406
    {
407
      warning ("Unable to fetch general register.");
408
      return;
409
    }
410
 
411
  if (regno >= A1_REGNUM && regno < PC_REGNUM)
412
    supply_register (regno, (char *) &regs.uregs[regno]);
413
 
414
  if (PS_REGNUM == regno)
415
    {
416
      if (arm_apcs_32)
417
        supply_register (PS_REGNUM, (char *) &regs.uregs[CPSR_REGNUM]);
418
      else
419
        supply_register (PS_REGNUM, (char *) &regs.uregs[PC_REGNUM]);
420
    }
421
 
422
  if (PC_REGNUM == regno)
423
    {
424
      regs.uregs[PC_REGNUM] = ADDR_BITS_REMOVE (regs.uregs[PC_REGNUM]);
425
      supply_register (PC_REGNUM, (char *) &regs.uregs[PC_REGNUM]);
426
    }
427
}
428
 
429
/* Fetch all general registers of the process and store into
430
   registers[].  */
431
 
432
static void
433
fetch_regs (void)
434
{
435
  int ret, regno, tid;
436
  struct pt_regs regs;
437
 
438
  /* Get the thread id for the ptrace call.  */
439
  tid = GET_THREAD_ID (inferior_pid);
440
 
441
  ret = ptrace (PTRACE_GETREGS, tid, 0, &regs);
442
  if (ret < 0)
443
    {
444
      warning ("Unable to fetch general registers.");
445
      return;
446
    }
447
 
448
  for (regno = A1_REGNUM; regno < PC_REGNUM; regno++)
449
    supply_register (regno, (char *) &regs.uregs[regno]);
450
 
451
  if (arm_apcs_32)
452
    supply_register (PS_REGNUM, (char *) &regs.uregs[CPSR_REGNUM]);
453
  else
454
    supply_register (PS_REGNUM, (char *) &regs.uregs[PC_REGNUM]);
455
 
456
  regs.uregs[PC_REGNUM] = ADDR_BITS_REMOVE (regs.uregs[PC_REGNUM]);
457
  supply_register (PC_REGNUM, (char *) &regs.uregs[PC_REGNUM]);
458
}
459
 
460
/* Store all general registers of the process from the values in
461
   registers[].  */
462
 
463
static void
464
store_register (int regno)
465
{
466
  int ret, tid;
467
  struct pt_regs regs;
468
 
469
  if (!register_valid[regno])
470
    return;
471
 
472
  /* Get the thread id for the ptrace call.  */
473
  tid = GET_THREAD_ID (inferior_pid);
474
 
475
  /* Get the general registers from the process.  */
476
  ret = ptrace (PTRACE_GETREGS, tid, 0, &regs);
477
  if (ret < 0)
478
    {
479
      warning ("Unable to fetch general registers.");
480
      return;
481
    }
482
 
483
  if (regno >= A1_REGNUM && regno <= PC_REGNUM)
484
    read_register_gen (regno, (char *) &regs.uregs[regno]);
485
 
486
  ret = ptrace (PTRACE_SETREGS, tid, 0, &regs);
487
  if (ret < 0)
488
    {
489
      warning ("Unable to store general register.");
490
      return;
491
    }
492
}
493
 
494
static void
495
store_regs (void)
496
{
497
  int ret, regno, tid;
498
  struct pt_regs regs;
499
 
500
  /* Get the thread id for the ptrace call.  */
501
  tid = GET_THREAD_ID (inferior_pid);
502
 
503
  /* Fetch the general registers.  */
504
  ret = ptrace (PTRACE_GETREGS, tid, 0, &regs);
505
  if (ret < 0)
506
    {
507
      warning ("Unable to fetch general registers.");
508
      return;
509
    }
510
 
511
  for (regno = A1_REGNUM; regno <= PC_REGNUM; regno++)
512
    {
513
      if (register_valid[regno])
514
        read_register_gen (regno, (char *) &regs.uregs[regno]);
515
    }
516
 
517
  ret = ptrace (PTRACE_SETREGS, tid, 0, &regs);
518
 
519
  if (ret < 0)
520
    {
521
      warning ("Unable to store general registers.");
522
      return;
523
    }
524
}
525
 
526
/* Fetch registers from the child process.  Fetch all registers if
527
   regno == -1, otherwise fetch all general registers or all floating
528
   point registers depending upon the value of regno.  */
529
 
530
void
531
fetch_inferior_registers (int regno)
532
{
533
  if (-1 == regno)
534
    {
535
      fetch_regs ();
536
      fetch_fpregs ();
537
    }
538
  else
539
    {
540
      if (regno < F0_REGNUM || regno > FPS_REGNUM)
541
        fetch_register (regno);
542
 
543
      if (regno >= F0_REGNUM && regno <= FPS_REGNUM)
544
        fetch_fpregister (regno);
545
    }
546
}
547
 
548
/* Store registers back into the inferior.  Store all registers if
549
   regno == -1, otherwise store all general registers or all floating
550
   point registers depending upon the value of regno.  */
551
 
552
void
553
store_inferior_registers (int regno)
554
{
555
  if (-1 == regno)
556
    {
557
      store_regs ();
558
      store_fpregs ();
559
    }
560
  else
561
    {
562
      if ((regno < F0_REGNUM) || (regno > FPS_REGNUM))
563
        store_register (regno);
564
 
565
      if ((regno >= F0_REGNUM) && (regno <= FPS_REGNUM))
566
        store_fpregister (regno);
567
    }
568
}
569
 
570
/* Fill register regno (if it is a general-purpose register) in
571
   *gregsetp with the appropriate value from GDB's register array.
572
   If regno is -1, do this for all registers.  */
573
 
574
void
575
fill_gregset (gregset_t *gregsetp, int regno)
576
{
577
  if (-1 == regno)
578
    {
579
      int regnum;
580
      for (regnum = A1_REGNUM; regnum <= PC_REGNUM; regnum++)
581
        if (register_valid[regnum])
582
          read_register_gen (regnum, (char *) &(*gregsetp)[regnum]);
583
    }
584
  else if (regno >= A1_REGNUM && regno <= PC_REGNUM)
585
    {
586
      if (register_valid[regno])
587
        read_register_gen (regno, (char *) &(*gregsetp)[regno]);
588
    }
589
 
590
  if (PS_REGNUM == regno || -1 == regno)
591
    {
592
      if (register_valid[regno] || -1 == regno)
593
        {
594
          if (arm_apcs_32)
595
            read_register_gen (PS_REGNUM, (char *) &(*gregsetp)[CPSR_REGNUM]);
596
          else
597
            read_register_gen (PC_REGNUM, (char *) &(*gregsetp)[PC_REGNUM]);
598
        }
599
    }
600
 
601
}
602
 
603
/* Fill GDB's register array with the general-purpose register values
604
   in *gregsetp.  */
605
 
606
void
607
supply_gregset (gregset_t *gregsetp)
608
{
609
  int regno, reg_pc;
610
 
611
  for (regno = A1_REGNUM; regno < PC_REGNUM; regno++)
612
    supply_register (regno, (char *) &(*gregsetp)[regno]);
613
 
614
  if (arm_apcs_32)
615
    supply_register (PS_REGNUM, (char *) &(*gregsetp)[CPSR_REGNUM]);
616
  else
617
    supply_register (PS_REGNUM, (char *) &(*gregsetp)[PC_REGNUM]);
618
 
619
  reg_pc = ADDR_BITS_REMOVE ((CORE_ADDR)(*gregsetp)[PC_REGNUM]);
620
  supply_register (PC_REGNUM, (char *) &reg_pc);
621
}
622
 
623
/* Fill register regno (if it is a floating-point register) in
624
   *fpregsetp with the appropriate value from GDB's register array.
625
   If regno is -1, do this for all registers.  */
626
 
627
void
628
fill_fpregset (fpregset_t *fpregsetp, int regno)
629
{
630
  FPA11 *fp = (FPA11 *) fpregsetp;
631
 
632
  if (-1 == regno)
633
    {
634
       int regnum;
635
       for (regnum = F0_REGNUM; regnum <= F7_REGNUM; regnum++)
636
         store_nwfpe_register (regnum, fp);
637
    }
638
  else if (regno >= F0_REGNUM && regno <= F7_REGNUM)
639
    {
640
      store_nwfpe_register (regno, fp);
641
      return;
642
    }
643
 
644
  /* Store fpsr.  */
645
  if (register_valid[FPS_REGNUM])
646
    if (FPS_REGNUM == regno || -1 == regno)
647
      read_register_gen (FPS_REGNUM, (char *) &fp->fpsr);
648
}
649
 
650
/* Fill GDB's register array with the floating-point register values
651
   in *fpregsetp.  */
652
 
653
void
654
supply_fpregset (fpregset_t *fpregsetp)
655
{
656
  int regno;
657
  FPA11 *fp = (FPA11 *) fpregsetp;
658
 
659
  /* Fetch fpsr.  */
660
  supply_register (FPS_REGNUM, (char *) &fp->fpsr);
661
 
662
  /* Fetch the floating point registers.  */
663
  for (regno = F0_REGNUM; regno <= F7_REGNUM; regno++)
664
    {
665
      fetch_nwfpe_register (regno, fp);
666
    }
667
}
668
 
669
int
670
arm_linux_kernel_u_size (void)
671
{
672
  return (sizeof (struct user));
673
}
674
 
675
static unsigned int
676
get_linux_version (unsigned int *vmajor,
677
                   unsigned int *vminor,
678
                   unsigned int *vrelease)
679
{
680
  struct utsname info;
681
  char *pmajor, *pminor, *prelease, *tail;
682
 
683
  if (-1 == uname (&info))
684
    {
685
      warning ("Unable to determine Linux version.");
686
      return -1;
687
    }
688
 
689
  pmajor = strtok (info.release, ".");
690
  pminor = strtok (NULL, ".");
691
  prelease = strtok (NULL, ".");
692
 
693
  *vmajor = (unsigned int) strtoul (pmajor, &tail, 0);
694
  *vminor = (unsigned int) strtoul (pminor, &tail, 0);
695
  *vrelease = (unsigned int) strtoul (prelease, &tail, 0);
696
 
697
  return ((*vmajor << 16) | (*vminor << 8) | *vrelease);
698
}
699
 
700
void
701
_initialize_arm_linux_nat (void)
702
{
703
  os_version = get_linux_version (&os_major, &os_minor, &os_release);
704
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.