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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-7.1/] [gdb/] [i386-nto-tdep.c] - Blame information for rev 318

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

Line No. Rev Author Line
1 227 jeremybenn
/* Target-dependent code for QNX Neutrino x86.
2
 
3
   Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010
4
   Free Software Foundation, Inc.
5
 
6
   Contributed by QNX Software Systems Ltd.
7
 
8
   This file is part of GDB.
9
 
10
   This program is free software; you can redistribute it and/or modify
11
   it under the terms of the GNU General Public License as published by
12
   the Free Software Foundation; either version 3 of the License, or
13
   (at your option) any later version.
14
 
15
   This program is distributed in the hope that it will be useful,
16
   but WITHOUT ANY WARRANTY; without even the implied warranty of
17
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
   GNU General Public License for more details.
19
 
20
   You should have received a copy of the GNU General Public License
21
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
22
 
23
#include "defs.h"
24
#include "frame.h"
25
#include "osabi.h"
26
#include "regcache.h"
27
#include "target.h"
28
 
29
#include "gdb_assert.h"
30
#include "gdb_string.h"
31
 
32
#include "i386-tdep.h"
33
#include "i387-tdep.h"
34
#include "nto-tdep.h"
35
#include "solib.h"
36
#include "solib-svr4.h"
37
 
38
#ifndef X86_CPU_FXSR
39
#define X86_CPU_FXSR (1L << 12)
40
#endif
41
 
42
/* Why 13?  Look in our /usr/include/x86/context.h header at the
43
   x86_cpu_registers structure and you'll see an 'exx' junk register
44
   that is just filler.  Don't ask me, ask the kernel guys.  */
45
#define NUM_GPREGS 13
46
 
47
/* Mapping between the general-purpose registers in `struct xxx'
48
   format and GDB's register cache layout.  */
49
 
50
/* From <x86/context.h>.  */
51
static int i386nto_gregset_reg_offset[] =
52
{
53
  7 * 4,                        /* %eax */
54
  6 * 4,                        /* %ecx */
55
  5 * 4,                        /* %edx */
56
  4 * 4,                        /* %ebx */
57
  11 * 4,                       /* %esp */
58
  2 * 4,                        /* %epb */
59
  1 * 4,                        /* %esi */
60
 
61
  8 * 4,                        /* %eip */
62
  10 * 4,                       /* %eflags */
63
  9 * 4,                        /* %cs */
64
  12 * 4,                       /* %ss */
65
  -1                            /* filler */
66
};
67
 
68
/* Given a GDB register number REGNUM, return the offset into
69
   Neutrino's register structure or -1 if the register is unknown.  */
70
 
71
static int
72
nto_reg_offset (int regnum)
73
{
74
  if (regnum >= 0 && regnum < ARRAY_SIZE (i386nto_gregset_reg_offset))
75
    return i386nto_gregset_reg_offset[regnum];
76
 
77
  return -1;
78
}
79
 
80
static void
81
i386nto_supply_gregset (struct regcache *regcache, char *gpregs)
82
{
83
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
84
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
85
 
86
  if(tdep->gregset == NULL)
87
    tdep->gregset = regset_alloc (gdbarch, i386_supply_gregset,
88
                                  i386_collect_gregset);
89
 
90
  gdb_assert (tdep->gregset_reg_offset == i386nto_gregset_reg_offset);
91
  tdep->gregset->supply_regset (tdep->gregset, regcache, -1,
92
                                gpregs, NUM_GPREGS * 4);
93
}
94
 
95
static void
96
i386nto_supply_fpregset (struct regcache *regcache, char *fpregs)
97
{
98
  if (nto_cpuinfo_valid && nto_cpuinfo_flags | X86_CPU_FXSR)
99
    i387_supply_fxsave (regcache, -1, fpregs);
100
  else
101
    i387_supply_fsave (regcache, -1, fpregs);
102
}
103
 
104
static void
105
i386nto_supply_regset (struct regcache *regcache, int regset, char *data)
106
{
107
  switch (regset)
108
    {
109
    case NTO_REG_GENERAL:
110
      i386nto_supply_gregset (regcache, data);
111
      break;
112
    case NTO_REG_FLOAT:
113
      i386nto_supply_fpregset (regcache, data);
114
      break;
115
    }
116
}
117
 
118
static int
119
i386nto_regset_id (int regno)
120
{
121
  if (regno == -1)
122
    return NTO_REG_END;
123
  else if (regno < I386_NUM_GREGS)
124
    return NTO_REG_GENERAL;
125
  else if (regno < I386_NUM_GREGS + I386_NUM_FREGS)
126
    return NTO_REG_FLOAT;
127
  else if (regno < I386_SSE_NUM_REGS)
128
    return NTO_REG_FLOAT; /* We store xmm registers in fxsave_area.  */
129
 
130
  return -1;                    /* Error.  */
131
}
132
 
133
static int
134
i386nto_register_area (struct gdbarch *gdbarch,
135
                       int regno, int regset, unsigned *off)
136
{
137
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
138
  int len;
139
 
140
  *off = 0;
141
  if (regset == NTO_REG_GENERAL)
142
    {
143
      if (regno == -1)
144
        return NUM_GPREGS * 4;
145
 
146
      *off = nto_reg_offset (regno);
147
      if (*off == -1)
148
        return 0;
149
      return 4;
150
    }
151
  else if (regset == NTO_REG_FLOAT)
152
    {
153
      unsigned off_adjust, regsize, regset_size, regno_base;
154
      /* The following are flags indicating number in our fxsave_area.  */
155
      int first_four = (regno >= I387_FCTRL_REGNUM (tdep)
156
                        && regno <= I387_FISEG_REGNUM (tdep));
157
      int second_four = (regno > I387_FISEG_REGNUM (tdep)
158
                         && regno <= I387_FOP_REGNUM (tdep));
159
      int st_reg = (regno >= I387_ST0_REGNUM (tdep)
160
                    && regno < I387_ST0_REGNUM (tdep) + 8);
161
      int xmm_reg = (regno >= I387_XMM0_REGNUM (tdep)
162
                     && regno < I387_MXCSR_REGNUM (tdep));
163
 
164
      if (nto_cpuinfo_valid && nto_cpuinfo_flags | X86_CPU_FXSR)
165
        {
166
          off_adjust = 32;
167
          regsize = 16;
168
          regset_size = 512;
169
          /* fxsave_area structure.  */
170
          if (first_four)
171
            {
172
              /* fpu_control_word, fpu_status_word, fpu_tag_word, fpu_operand
173
                 registers.  */
174
              regsize = 2; /* Two bytes each.  */
175
              off_adjust = 0;
176
              regno_base = I387_FCTRL_REGNUM (tdep);
177
            }
178
          else if (second_four)
179
            {
180
              /* fpu_ip, fpu_cs, fpu_op, fpu_ds registers.  */
181
              regsize = 4;
182
              off_adjust = 8;
183
              regno_base = I387_FISEG_REGNUM (tdep) + 1;
184
            }
185
          else if (st_reg)
186
            {
187
              /* ST registers.  */
188
              regsize = 16;
189
              off_adjust = 32;
190
              regno_base = I387_ST0_REGNUM (tdep);
191
            }
192
          else if (xmm_reg)
193
            {
194
              /* XMM registers.  */
195
              regsize = 16;
196
              off_adjust = 160;
197
              regno_base = I387_XMM0_REGNUM (tdep);
198
            }
199
          else if (regno == I387_MXCSR_REGNUM (tdep))
200
            {
201
              regsize = 4;
202
              off_adjust = 24;
203
              regno_base = I387_MXCSR_REGNUM (tdep);
204
            }
205
          else
206
            {
207
              /* Whole regset.  */
208
              gdb_assert (regno == -1);
209
              off_adjust = 0;
210
              regno_base = 0;
211
              regsize = regset_size;
212
            }
213
        }
214
      else
215
        {
216
          regset_size = 108;
217
          /* fsave_area structure.  */
218
          if (first_four || second_four)
219
            {
220
              /* fpu_control_word, ... , fpu_ds registers.  */
221
              regsize = 4;
222
              off_adjust = 0;
223
              regno_base = I387_FCTRL_REGNUM (tdep);
224
            }
225
          else if (st_reg)
226
            {
227
              /* One of ST registers.  */
228
              regsize = 10;
229
              off_adjust = 7 * 4;
230
              regno_base = I387_ST0_REGNUM (tdep);
231
            }
232
          else
233
            {
234
              /* Whole regset.  */
235
              gdb_assert (regno == -1);
236
              off_adjust = 0;
237
              regno_base = 0;
238
              regsize = regset_size;
239
            }
240
        }
241
 
242
      if (regno != -1)
243
        *off = off_adjust + (regno - regno_base) * regsize;
244
      else
245
        *off = 0;
246
      return regsize;
247
    }
248
  return -1;
249
}
250
 
251
static int
252
i386nto_regset_fill (const struct regcache *regcache, int regset, char *data)
253
{
254
  if (regset == NTO_REG_GENERAL)
255
    {
256
      int regno;
257
 
258
      for (regno = 0; regno < NUM_GPREGS; regno++)
259
        {
260
          int offset = nto_reg_offset (regno);
261
          if (offset != -1)
262
            regcache_raw_collect (regcache, regno, data + offset);
263
        }
264
    }
265
  else if (regset == NTO_REG_FLOAT)
266
    {
267
      if (nto_cpuinfo_valid && nto_cpuinfo_flags | X86_CPU_FXSR)
268
        i387_collect_fxsave (regcache, -1, data);
269
      else
270
        i387_collect_fsave (regcache, -1, data);
271
    }
272
  else
273
    return -1;
274
 
275
  return 0;
276
}
277
 
278
/* Return whether THIS_FRAME corresponds to a QNX Neutrino sigtramp
279
   routine.  */
280
 
281
static int
282
i386nto_sigtramp_p (struct frame_info *this_frame)
283
{
284
  CORE_ADDR pc = get_frame_pc (this_frame);
285
  char *name;
286
 
287
  find_pc_partial_function (pc, &name, NULL, NULL);
288
  return name && strcmp ("__signalstub", name) == 0;
289
}
290
 
291
/* Assuming THIS_FRAME is a QNX Neutrino sigtramp routine, return the
292
   address of the associated sigcontext structure.  */
293
 
294
static CORE_ADDR
295
i386nto_sigcontext_addr (struct frame_info *this_frame)
296
{
297
  struct gdbarch *gdbarch = get_frame_arch (this_frame);
298
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
299
  char buf[4];
300
  CORE_ADDR ptrctx;
301
 
302
  /* We store __ucontext_t addr in EDI register.  */
303
  get_frame_register (this_frame, I386_EDI_REGNUM, buf);
304
  ptrctx = extract_unsigned_integer (buf, 4, byte_order);
305
  ptrctx += 24 /* Context pointer is at this offset.  */;
306
 
307
  return ptrctx;
308
}
309
 
310
static void
311
init_i386nto_ops (void)
312
{
313
  nto_regset_id = i386nto_regset_id;
314
  nto_supply_gregset = i386nto_supply_gregset;
315
  nto_supply_fpregset = i386nto_supply_fpregset;
316
  nto_supply_altregset = nto_dummy_supply_regset;
317
  nto_supply_regset = i386nto_supply_regset;
318
  nto_register_area = i386nto_register_area;
319
  nto_regset_fill = i386nto_regset_fill;
320
  nto_fetch_link_map_offsets =
321
    svr4_ilp32_fetch_link_map_offsets;
322
}
323
 
324
static void
325
i386nto_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
326
{
327
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
328
  static struct target_so_ops nto_svr4_so_ops;
329
 
330
  /* Deal with our strange signals.  */
331
  nto_initialize_signals ();
332
 
333
  /* NTO uses ELF.  */
334
  i386_elf_init_abi (info, gdbarch);
335
 
336
  /* Neutrino rewinds to look more normal.  Need to override the i386
337
     default which is [unfortunately] to decrement the PC.  */
338
  set_gdbarch_decr_pc_after_break (gdbarch, 0);
339
 
340
  tdep->gregset_reg_offset = i386nto_gregset_reg_offset;
341
  tdep->gregset_num_regs = ARRAY_SIZE (i386nto_gregset_reg_offset);
342
  tdep->sizeof_gregset = NUM_GPREGS * 4;
343
 
344
  tdep->sigtramp_p = i386nto_sigtramp_p;
345
  tdep->sigcontext_addr = i386nto_sigcontext_addr;
346
  tdep->sc_reg_offset = i386nto_gregset_reg_offset;
347
  tdep->sc_num_regs = ARRAY_SIZE (i386nto_gregset_reg_offset);
348
 
349
  /* Setjmp()'s return PC saved in EDX (5).  */
350
  tdep->jb_pc_offset = 20;      /* 5x32 bit ints in.  */
351
 
352
  set_solib_svr4_fetch_link_map_offsets
353
    (gdbarch, svr4_ilp32_fetch_link_map_offsets);
354
 
355
  /* Initialize this lazily, to avoid an initialization order
356
     dependency on solib-svr4.c's _initialize routine.  */
357
  if (nto_svr4_so_ops.in_dynsym_resolve_code == NULL)
358
    {
359
      nto_svr4_so_ops = svr4_so_ops;
360
 
361
      /* Our loader handles solib relocations differently than svr4.  */
362
      nto_svr4_so_ops.relocate_section_addresses
363
        = nto_relocate_section_addresses;
364
 
365
      /* Supply a nice function to find our solibs.  */
366
      nto_svr4_so_ops.find_and_open_solib
367
        = nto_find_and_open_solib;
368
 
369
      /* Our linker code is in libc.  */
370
      nto_svr4_so_ops.in_dynsym_resolve_code
371
        = nto_in_dynsym_resolve_code;
372
    }
373
  set_solib_ops (gdbarch, &nto_svr4_so_ops);
374
}
375
 
376
/* Provide a prototype to silence -Wmissing-prototypes.  */
377
extern initialize_file_ftype _initialize_i386nto_tdep;
378
 
379
void
380
_initialize_i386nto_tdep (void)
381
{
382
  init_i386nto_ops ();
383
  gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_QNXNTO,
384
                          i386nto_init_abi);
385
  gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_elf_flavour,
386
                                  nto_elf_osabi_sniffer);
387
}

powered by: WebSVN 2.1.0

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