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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-7.1/] [gdb/] [gdbserver/] [linux-s390-low.c] - Blame information for rev 280

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

Line No. Rev Author Line
1 227 jeremybenn
/* GNU/Linux S/390 specific low level interface, for the remote server
2
   for GDB.
3
   Copyright (C) 2001, 2002, 2005, 2006, 2007, 2008, 2009, 2010
4
   Free Software Foundation, Inc.
5
 
6
   This file is part of GDB.
7
 
8
   This program is free software; you can redistribute it and/or modify
9
   it under the terms of the GNU General Public License as published by
10
   the Free Software Foundation; either version 3 of the License, or
11
   (at your option) any later version.
12
 
13
   This program is distributed in the hope that it will be useful,
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
   GNU General Public License for more details.
17
 
18
   You should have received a copy of the GNU General Public License
19
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20
 
21
/* This file is used for both 31-bit and 64-bit S/390 systems.  */
22
 
23
#include "server.h"
24
#include "linux-low.h"
25
 
26
#include <asm/ptrace.h>
27
#include <elf.h>
28
 
29
#ifndef HWCAP_S390_HIGH_GPRS
30
#define HWCAP_S390_HIGH_GPRS 512
31
#endif
32
 
33
/* Defined in auto-generated file s390-linux32.c.  */
34
void init_registers_s390_linux32 (void);
35
/* Defined in auto-generated file s390-linux64.c.  */
36
void init_registers_s390_linux64 (void);
37
/* Defined in auto-generated file s390x-linux64.c.  */
38
void init_registers_s390x_linux64 (void);
39
 
40
#define s390_num_regs 51
41
 
42
static int s390_regmap[] = {
43
  PT_PSWMASK, PT_PSWADDR,
44
 
45
  PT_GPR0, PT_GPR1, PT_GPR2, PT_GPR3,
46
  PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
47
  PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
48
  PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15,
49
 
50
  PT_ACR0, PT_ACR1, PT_ACR2, PT_ACR3,
51
  PT_ACR4, PT_ACR5, PT_ACR6, PT_ACR7,
52
  PT_ACR8, PT_ACR9, PT_ACR10, PT_ACR11,
53
  PT_ACR12, PT_ACR13, PT_ACR14, PT_ACR15,
54
 
55
  PT_FPC,
56
 
57
#ifndef __s390x__
58
  PT_FPR0_HI, PT_FPR1_HI, PT_FPR2_HI, PT_FPR3_HI,
59
  PT_FPR4_HI, PT_FPR5_HI, PT_FPR6_HI, PT_FPR7_HI,
60
  PT_FPR8_HI, PT_FPR9_HI, PT_FPR10_HI, PT_FPR11_HI,
61
  PT_FPR12_HI, PT_FPR13_HI, PT_FPR14_HI, PT_FPR15_HI,
62
#else
63
  PT_FPR0, PT_FPR1, PT_FPR2, PT_FPR3,
64
  PT_FPR4, PT_FPR5, PT_FPR6, PT_FPR7,
65
  PT_FPR8, PT_FPR9, PT_FPR10, PT_FPR11,
66
  PT_FPR12, PT_FPR13, PT_FPR14, PT_FPR15,
67
#endif
68
};
69
 
70
#ifdef __s390x__
71
#define s390_num_regs_3264 67
72
 
73
static int s390_regmap_3264[] = {
74
  PT_PSWMASK, PT_PSWADDR,
75
 
76
  PT_GPR0, PT_GPR0, PT_GPR1, PT_GPR1, PT_GPR2, PT_GPR2, PT_GPR3, PT_GPR3,
77
  PT_GPR4, PT_GPR4, PT_GPR5, PT_GPR5, PT_GPR6, PT_GPR6, PT_GPR7, PT_GPR7,
78
  PT_GPR8, PT_GPR8, PT_GPR9, PT_GPR9, PT_GPR10, PT_GPR10, PT_GPR11, PT_GPR11,
79
  PT_GPR12, PT_GPR12, PT_GPR13, PT_GPR13, PT_GPR14, PT_GPR14, PT_GPR15, PT_GPR15,
80
 
81
  PT_ACR0, PT_ACR1, PT_ACR2, PT_ACR3,
82
  PT_ACR4, PT_ACR5, PT_ACR6, PT_ACR7,
83
  PT_ACR8, PT_ACR9, PT_ACR10, PT_ACR11,
84
  PT_ACR12, PT_ACR13, PT_ACR14, PT_ACR15,
85
 
86
  PT_FPC,
87
 
88
  PT_FPR0, PT_FPR1, PT_FPR2, PT_FPR3,
89
  PT_FPR4, PT_FPR5, PT_FPR6, PT_FPR7,
90
  PT_FPR8, PT_FPR9, PT_FPR10, PT_FPR11,
91
  PT_FPR12, PT_FPR13, PT_FPR14, PT_FPR15,
92
};
93
#endif
94
 
95
 
96
static int
97
s390_cannot_fetch_register (int regno)
98
{
99
  return 0;
100
}
101
 
102
static int
103
s390_cannot_store_register (int regno)
104
{
105
  return 0;
106
}
107
 
108
static void
109
s390_collect_ptrace_register (struct regcache *regcache, int regno, char *buf)
110
{
111
  int size = register_size (regno);
112
  if (size < sizeof (long))
113
    {
114
      int regaddr = the_low_target.regmap[regno];
115
 
116
      memset (buf, 0, sizeof (long));
117
 
118
      if ((regno ^ 1) < the_low_target.num_regs
119
          && the_low_target.regmap[regno ^ 1] == regaddr)
120
        {
121
          collect_register (regcache, regno & ~1, buf);
122
          collect_register (regcache, (regno & ~1) + 1,
123
                            buf + sizeof (long) - size);
124
        }
125
      else if (regaddr == PT_PSWADDR
126
               || (regaddr >= PT_GPR0 && regaddr <= PT_GPR15))
127
        collect_register (regcache, regno, buf + sizeof (long) - size);
128
      else
129
        collect_register (regcache, regno, buf);
130
 
131
      /* When debugging a 32-bit inferior on a 64-bit host, make sure
132
         the 31-bit addressing mode bit is set in the PSW mask.  */
133
      if (regaddr == PT_PSWMASK)
134
        buf[size] |= 0x80;
135
    }
136
  else
137
    collect_register (regcache, regno, buf);
138
}
139
 
140
static void
141
s390_supply_ptrace_register (struct regcache *regcache, int regno, const char *buf)
142
{
143
  int size = register_size (regno);
144
  if (size < sizeof (long))
145
    {
146
      int regaddr = the_low_target.regmap[regno];
147
 
148
      if ((regno ^ 1) < the_low_target.num_regs
149
          && the_low_target.regmap[regno ^ 1] == regaddr)
150
        {
151
          supply_register (regcache, regno & ~1, buf);
152
          supply_register (regcache, (regno & ~1) + 1,
153
                           buf + sizeof (long) - size);
154
        }
155
      else if (regaddr == PT_PSWADDR
156
               || (regaddr >= PT_GPR0 && regaddr <= PT_GPR15))
157
        supply_register (regcache, regno, buf + sizeof (long) - size);
158
      else
159
        supply_register (regcache, regno, buf);
160
    }
161
  else
162
    supply_register (regcache, regno, buf);
163
}
164
 
165
/* Provide only a fill function for the general register set.  ps_lgetregs
166
   will use this for NPTL support.  */
167
 
168
static void s390_fill_gregset (struct regcache *regcache, void *buf)
169
{
170
  int i;
171
 
172
  for (i = 0; i < the_low_target.num_regs; i++)
173
    {
174
      if (the_low_target.regmap[i] < PT_PSWMASK
175
          || the_low_target.regmap[i] > PT_ACR15)
176
        continue;
177
 
178
      s390_collect_ptrace_register (regcache, i, (char *) buf
179
                                       + the_low_target.regmap[i]);
180
    }
181
}
182
 
183
struct regset_info target_regsets[] = {
184
  { 0, 0, 0, GENERAL_REGS, s390_fill_gregset, NULL },
185
  { 0, 0, -1, -1, NULL, NULL }
186
};
187
 
188
 
189
static const unsigned char s390_breakpoint[] = { 0, 1 };
190
#define s390_breakpoint_len 2
191
 
192
static CORE_ADDR
193
s390_get_pc (struct regcache *regcache)
194
{
195
  if (register_size (0) == 4)
196
    {
197
      unsigned int pc;
198
      collect_register_by_name (regcache, "pswa", &pc);
199
#ifndef __s390x__
200
      pc &= 0x7fffffff;
201
#endif
202
      return pc;
203
    }
204
  else
205
    {
206
      unsigned long pc;
207
      collect_register_by_name (regcache, "pswa", &pc);
208
      return pc;
209
    }
210
}
211
 
212
static void
213
s390_set_pc (struct regcache *regcache, CORE_ADDR newpc)
214
{
215
  if (register_size (0) == 4)
216
    {
217
      unsigned int pc = newpc;
218
#ifndef __s390x__
219
      pc |= 0x80000000;
220
#endif
221
      supply_register_by_name (regcache, "pswa", &pc);
222
    }
223
  else
224
    {
225
      unsigned long pc = newpc;
226
      supply_register_by_name (regcache, "pswa", &pc);
227
    }
228
}
229
 
230
#ifdef __s390x__
231
static unsigned long
232
s390_get_hwcap (void)
233
{
234
  int wordsize = register_size (0);
235
  unsigned char *data = alloca (2 * wordsize);
236
  int offset = 0;
237
 
238
  while ((*the_target->read_auxv) (offset, data, 2 * wordsize) == 2 * wordsize)
239
    {
240
      if (wordsize == 4)
241
        {
242
          unsigned int *data_p = (unsigned int *)data;
243
          if (data_p[0] == AT_HWCAP)
244
            return data_p[1];
245
        }
246
      else
247
        {
248
          unsigned long *data_p = (unsigned long *)data;
249
          if (data_p[0] == AT_HWCAP)
250
            return data_p[1];
251
        }
252
 
253
      offset += 2 * wordsize;
254
    }
255
 
256
  return 0;
257
}
258
#endif
259
 
260
static void
261
s390_arch_setup (void)
262
{
263
  /* Assume 31-bit inferior process.  */
264
  init_registers_s390_linux32 ();
265
  the_low_target.num_regs = s390_num_regs;
266
  the_low_target.regmap = s390_regmap;
267
 
268
  /* On a 64-bit host, check the low bit of the (31-bit) PSWM
269
     -- if this is one, we actually have a 64-bit inferior.  */
270
#ifdef __s390x__
271
  {
272
    unsigned int pswm;
273
    struct regcache *regcache = get_thread_regcache (current_inferior, 1);
274
    collect_register_by_name (regcache, "pswm", &pswm);
275
    if (pswm & 1)
276
      init_registers_s390x_linux64 ();
277
 
278
    /* For a 31-bit inferior, check whether the kernel supports
279
       using the full 64-bit GPRs.  */
280
    else if (s390_get_hwcap () & HWCAP_S390_HIGH_GPRS)
281
      {
282
        init_registers_s390_linux64 ();
283
        the_low_target.num_regs = s390_num_regs_3264;
284
        the_low_target.regmap = s390_regmap_3264;
285
      }
286
  }
287
#endif
288
}
289
 
290
 
291
static int
292
s390_breakpoint_at (CORE_ADDR pc)
293
{
294
  unsigned char c[s390_breakpoint_len];
295
  read_inferior_memory (pc, c, s390_breakpoint_len);
296
  return memcmp (c, s390_breakpoint, s390_breakpoint_len) == 0;
297
}
298
 
299
 
300
struct linux_target_ops the_low_target = {
301
  s390_arch_setup,
302
  s390_num_regs,
303
  s390_regmap,
304
  s390_cannot_fetch_register,
305
  s390_cannot_store_register,
306
  s390_get_pc,
307
  s390_set_pc,
308
  s390_breakpoint,
309
  s390_breakpoint_len,
310
  NULL,
311
  s390_breakpoint_len,
312
  s390_breakpoint_at,
313
  NULL,
314
  NULL,
315
  NULL,
316
  NULL,
317
  s390_collect_ptrace_register,
318
  s390_supply_ptrace_register,
319
};

powered by: WebSVN 2.1.0

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