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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [gdb/] [i386gnu-nat.c] - Blame information for rev 1774

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

Line No. Rev Author Line
1 578 markom
/* Low level interface to i386 running the GNU Hurd.
2
   Copyright 1992, 1995, 1996, 1998, 2000, 2001
3
   Free Software Foundation, Inc.
4
 
5
   This file is part of GDB.
6
 
7
   This program is free software; you can redistribute it and/or modify
8
   it under the terms of the GNU General Public License as published by
9
   the Free Software Foundation; either version 2 of the License, or
10
   (at your option) any later version.
11
 
12
   This program is distributed in the hope that it will be useful,
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
   GNU General Public License for more details.
16
 
17
   You should have received a copy of the GNU General Public License
18
   along with this program; if not, write to the Free Software
19
   Foundation, Inc., 59 Temple Place - Suite 330,
20
   Boston, MA 02111-1307, USA.  */
21
 
22
#include "defs.h"
23
#include "inferior.h"
24
#include "floatformat.h"
25
#include "regcache.h"
26
 
27
#include "gdb_assert.h"
28
#include <stdio.h>
29
#include <errno.h>
30
 
31
#include <mach.h>
32
#include <mach_error.h>
33
#include <mach/message.h>
34
#include <mach/exception.h>
35
 
36
#include "gnu-nat.h"
37
 
38
/* The FPU hardware state.  */
39
struct env387
40
{
41
  unsigned short control;
42
  unsigned short r0;
43
  unsigned short status;
44
  unsigned short r1;
45
  unsigned short tag;
46
  unsigned short r2;
47
  unsigned long eip;
48
  unsigned short code_seg;
49
  unsigned short opcode;
50
  unsigned long operand;
51
  unsigned short operand_seg;
52
  unsigned short r3;
53
  unsigned char regs[8][10];
54
};
55
 
56
 
57
/* Offset to the thread_state_t location where REG is stored.  */
58
#define REG_OFFSET(reg) offsetof (struct i386_thread_state, reg)
59
 
60
/* At reg_offset[i] is the offset to the thread_state_t location where
61
   the gdb registers[i] is stored.  */
62
static int reg_offset[] =
63
{
64
  REG_OFFSET (eax), REG_OFFSET (ecx), REG_OFFSET (edx), REG_OFFSET (ebx),
65
  REG_OFFSET (uesp), REG_OFFSET (ebp), REG_OFFSET (esi), REG_OFFSET (edi),
66
  REG_OFFSET (eip), REG_OFFSET (efl), REG_OFFSET (cs), REG_OFFSET (ss),
67
  REG_OFFSET (ds), REG_OFFSET (es), REG_OFFSET (fs), REG_OFFSET (gs)
68
};
69
 
70
#define REG_ADDR(state, regnum) ((char *)(state) + reg_offset[regnum])
71
 
72
 
73
/* Get the whole floating-point state of THREAD and record the
74
   values of the corresponding (pseudo) registers.  */
75
static void
76
fetch_fpregs (struct proc *thread)
77
{
78
  mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT;
79
  struct i386_float_state state;
80
  struct env387 *ep = (struct env387 *) state.hw_state;
81
  error_t err;
82
  int i;
83
 
84
  err = thread_get_state (thread->port, i386_FLOAT_STATE,
85
                          (thread_state_t) &state, &count);
86
  if (err)
87
    {
88
      warning ("Couldn't fetch floating-point state from %s",
89
               proc_string (thread));
90
      return;
91
    }
92
 
93
  if (! state.initialized)
94
    /* The floating-point state isn't initialized.  */
95
    {
96
      for (i = FP0_REGNUM; i <= FP7_REGNUM; i++)
97
        supply_register (i, NULL);
98
      for (i = FIRST_FPU_CTRL_REGNUM; i <= LAST_FPU_CTRL_REGNUM; i++)
99
        supply_register (i, NULL);
100
 
101
      return;
102
    }
103
 
104
  /* Supply the floating-point registers.  */
105
  for (i = 0; i < 8; i++)
106
    supply_register (FP0_REGNUM + i, ep->regs[i]);
107
 
108
  supply_register (FCTRL_REGNUM, (char *) &ep->control);
109
  supply_register (FSTAT_REGNUM, (char *) &ep->status);
110
  supply_register (FTAG_REGNUM,  (char *) &ep->tag);
111
  supply_register (FCOFF_REGNUM, (char *) &ep->eip);
112
  supply_register (FDS_REGNUM,   (char *) &ep->operand_seg);
113
  supply_register (FDOFF_REGNUM, (char *) &ep->operand);
114
 
115
  /* Store the code segment and opcode pseudo registers.  */
116
  {
117
    long l;
118
 
119
    l = ep->code_seg;
120
    supply_register (FCS_REGNUM, (char *) &l);
121
    l = ep->opcode & ((1 << 11) - 1);
122
    supply_register (FOP_REGNUM, (char *) &l);
123
  }
124
}
125
 
126
/* Fetch register REGNO, or all regs if REGNO is -1.  */
127
void
128
gnu_fetch_registers (int regno)
129
{
130
  struct proc *thread;
131
 
132
  /* Make sure we know about new threads.  */
133
  inf_update_procs (current_inferior);
134
 
135
  thread = inf_tid_to_thread (current_inferior, PIDGET (inferior_ptid));
136
  if (!thread)
137
    error ("Can't fetch registers from thread %d: No such thread",
138
           PIDGET (inferior_ptid));
139
 
140
  if (regno < NUM_GREGS || regno == -1)
141
    {
142
      thread_state_t state;
143
 
144
      /* This does the dirty work for us.  */
145
      state = proc_get_state (thread, 0);
146
      if (!state)
147
        {
148
          warning ("Couldn't fetch registers from %s",
149
                   proc_string (thread));
150
          return;
151
        }
152
 
153
      if (regno == -1)
154
        {
155
          int i;
156
 
157
          proc_debug (thread, "fetching all register");
158
 
159
          for (i = 0; i < NUM_GREGS; i++)
160
            supply_register (i, REG_ADDR (state, i));
161
          thread->fetched_regs = ~0;
162
        }
163
      else
164
        {
165
          proc_debug (thread, "fetching register %s", REGISTER_NAME (regno));
166
 
167
          supply_register (regno, REG_ADDR (state, regno));
168
          thread->fetched_regs |= (1 << regno);
169
        }
170
    }
171
 
172
  if (regno >= NUM_GREGS || regno == -1)
173
    {
174
      proc_debug (thread, "fetching floating-point registers");
175
 
176
      fetch_fpregs (thread);
177
    }
178
}
179
 
180
 
181
/* Fill the i387 hardware state EP with selected data from the set of
182
   (pseudo) registers specified by REGS and VALID.  VALID is an array
183
   indicating which registers in REGS are valid.  If VALID is zero,
184
   all registers are assumed to be valid.  */
185
static void
186
convert_to_env387 (struct env387 *ep, char *regs, signed char *valid)
187
{
188
  int i;
189
 
190
  /* Fill in the floating-point registers.  */
191
  for (i = 0; i < 8; i++)
192
    if (!valid || valid[i])
193
      memcpy (ep->regs[i], &regs[REGISTER_BYTE (FP0_REGNUM + i)],
194
              REGISTER_RAW_SIZE (FP0_REGNUM + i));
195
 
196
#define fill(member, regno)                                              \
197
  if (!valid || valid[(regno)])                                          \
198
    memcpy (&ep->member, &regs[REGISTER_BYTE (regno)],                   \
199
            sizeof (ep->member));
200
 
201
  fill (control, FCTRL_REGNUM);
202
  fill (status, FSTAT_REGNUM);
203
  fill (tag, FTAG_REGNUM);
204
  fill (eip, FCOFF_REGNUM);
205
  fill (operand, FDOFF_REGNUM);
206
  fill (operand_seg, FDS_REGNUM);
207
 
208
#undef fill
209
 
210
  if (!valid || valid[FCS_REGNUM])
211
    ep->code_seg =
212
      (* (int *) &registers[REGISTER_BYTE (FCS_REGNUM)] & 0xffff);
213
 
214
  if (!valid || valid[FOP_REGNUM])
215
    ep->opcode =
216
      ((* (int *) &registers[REGISTER_BYTE (FOP_REGNUM)] & ((1 << 11) - 1)));
217
}
218
 
219
/* Store the whole floating-point state into THREAD using information
220
   from the corresponding (pseudo) registers.  */
221
static void
222
store_fpregs (struct proc *thread)
223
{
224
  mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT;
225
  struct i386_float_state state;
226
  error_t err;
227
 
228
  err = thread_get_state (thread->port, i386_FLOAT_STATE,
229
                          (thread_state_t) &state, &count);
230
  if (err)
231
    {
232
      warning ("Couldn't fetch floating-point state from %s",
233
               proc_string (thread));
234
      return;
235
    }
236
 
237
  convert_to_env387 ((struct env387 *) state.hw_state,
238
                     registers, register_valid);
239
 
240
  err = thread_set_state (thread->port, i386_FLOAT_STATE,
241
                          (thread_state_t) &state, i386_FLOAT_STATE_COUNT);
242
  if (err)
243
    {
244
      warning ("Couldn't store floating-point state into %s",
245
               proc_string (thread));
246
      return;
247
    }
248
}
249
 
250
/* Store at least register REGNO, or all regs if REGNO == -1.  */
251
void
252
gnu_store_registers (int regno)
253
{
254
  struct proc *thread;
255
 
256
  /* Make sure we know about new threads.  */
257
  inf_update_procs (current_inferior);
258
 
259
  thread = inf_tid_to_thread (current_inferior, PIDGET (inferior_ptid));
260
  if (!thread)
261
    error ("Couldn't store registers into thread %d: No such thread",
262
           PIDGET (inferior_ptid));
263
 
264
  if (regno < NUM_GREGS || regno == -1)
265
    {
266
      thread_state_t state;
267
      thread_state_data_t old_state;
268
      int was_aborted = thread->aborted;
269
      int was_valid = thread->state_valid;
270
      int trace;
271
 
272
      if (!was_aborted && was_valid)
273
        memcpy (&old_state, &thread->state, sizeof (old_state));
274
 
275
      state = proc_get_state (thread, 1);
276
      if (!state)
277
        {
278
          warning ("Couldn't store registers into %s", proc_string (thread));
279
          return;
280
        }
281
 
282
      /* Save the T bit.  We might try to restore the %eflags register
283
         below, but changing the T bit would seriously confuse GDB.  */
284
      trace = ((struct i386_thread_state *)state)->efl & 0x100;
285
 
286
      if (!was_aborted && was_valid)
287
        /* See which registers have changed after aborting the thread.  */
288
        {
289
          int check_regno;
290
 
291
          for (check_regno = 0; check_regno < NUM_GREGS; check_regno++)
292
            if ((thread->fetched_regs & (1 << check_regno))
293
                && memcpy (REG_ADDR (&old_state, check_regno),
294
                           REG_ADDR (state, check_regno),
295
                           REGISTER_RAW_SIZE (check_regno)))
296
              /* Register CHECK_REGNO has changed!  Ack!  */
297
              {
298
                warning ("Register %s changed after the thread was aborted",
299
                         REGISTER_NAME (check_regno));
300
                if (regno >= 0 && regno != check_regno)
301
                  /* Update gdb's copy of the register.  */
302
                  supply_register (check_regno, REG_ADDR (state, check_regno));
303
                else
304
                  warning ("... also writing this register!  Suspicious...");
305
              }
306
        }
307
 
308
#define fill(state, regno)                                               \
309
  memcpy (REG_ADDR(state, regno), &registers[REGISTER_BYTE (regno)],     \
310
          REGISTER_RAW_SIZE (regno))
311
 
312
      if (regno == -1)
313
        {
314
          int i;
315
 
316
          proc_debug (thread, "storing all registers");
317
 
318
          for (i = 0; i < NUM_GREGS; i++)
319
            if (register_valid[i])
320
              fill (state, i);
321
        }
322
      else
323
        {
324
          proc_debug (thread, "storing register %s", REGISTER_NAME (regno));
325
 
326
          gdb_assert (register_valid[regno]);
327
          fill (state, regno);
328
        }
329
 
330
      /* Restore the T bit.  */
331
      ((struct i386_thread_state *)state)->efl &= ~0x100;
332
      ((struct i386_thread_state *)state)->efl |= trace;
333
    }
334
 
335
#undef fill
336
 
337
  if (regno >= NUM_GREGS || regno == -1)
338
    {
339
      proc_debug (thread, "storing floating-point registers");
340
 
341
      store_fpregs (thread);
342
    }
343
}

powered by: WebSVN 2.1.0

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