fca14e47114dbc94bac655a0d576f7ea4cd6ae1b
[deliverable/binutils-gdb.git] / gdb / i386gnu-nat.c
1 /* 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 "gdb_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 \f
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 \f
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 \f
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 gdb_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 }
This page took 0.03629 seconds and 3 git commands to generate.