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

Subversion Repositories or1k

[/] [or1k/] [tags/] [start/] [insight/] [gdb/] [arm-linux-nat.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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