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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [gdb/] [i386gnu-nat.c] - Blame information for rev 104

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

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

powered by: WebSVN 2.1.0

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