2000-02-19 Philippe De Muyter <phdm@macqel.be>
[deliverable/binutils-gdb.git] / gdb / i386gnu-nat.c
CommitLineData
da59e081 1/* Low level interface to i386 running the GNU Hurd.
c906108c
SS
2 Copyright (C) 1992, 1995, 1996 Free Software Foundation, Inc.
3
c5aa993b 4 This file is part of GDB.
c906108c 5
c5aa993b
JM
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.
c906108c 10
c5aa993b
JM
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.
c906108c 15
c5aa993b
JM
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. */
c906108c
SS
20
21#include "defs.h"
22#include "inferior.h"
23#include "floatformat.h"
24
da59e081 25#include <assert.h>
c906108c
SS
26#include <stdio.h>
27#include <errno.h>
28
29#include <mach.h>
da59e081 30#include <mach_error.h>
c906108c
SS
31#include <mach/message.h>
32#include <mach/exception.h>
c906108c
SS
33
34#include "gnu-nat.h"
35
da59e081
JM
36/* The FPU hardware state. */
37struct 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};
c906108c 53
c906108c 54\f
da59e081
JM
55/* Offset to the thread_state_t location where REG is stored. */
56#define REG_OFFSET(reg) offsetof (struct i386_thread_state, reg)
c906108c 57
da59e081
JM
58/* At reg_offset[i] is the offset to the thread_state_t location where
59 the gdb registers[i] is stored. */
c5aa993b 60static int reg_offset[] =
c906108c 61{
c5aa993b
JM
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)
c906108c
SS
66};
67
da59e081
JM
68#define REG_ADDR(state, regnum) ((char *)(state) + reg_offset[regnum])
69
c906108c 70\f
da59e081
JM
71/* Get the whole floating-point state of THREAD and record the
72 values of the corresponding (pseudo) registers. */
73static void
74fetch_fpregs (struct proc *thread)
c906108c 75{
da59e081
JM
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;
c906108c 81
da59e081
JM
82 err = thread_get_state (thread->port, i386_FLOAT_STATE,
83 (thread_state_t) &state, &count);
84 if (err)
c906108c 85 {
da59e081
JM
86 warning ("Couldn't fetch floating-point state from %s",
87 proc_string (thread));
88 return;
c906108c 89 }
da59e081
JM
90
91 if (! state.initialized)
92 /* The floating-point state isn't initialized. */
c906108c 93 {
da59e081
JM
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;
c906108c 100 }
da59e081
JM
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 }
c906108c 122}
da59e081
JM
123
124/* Fetch register REGNO, or all regs if REGNO is -1. */
c906108c 125void
da59e081 126gnu_fetch_registers (int regno)
c906108c
SS
127{
128 struct proc *thread;
c5aa993b 129
da59e081
JM
130 /* Make sure we know about new threads. */
131 inf_update_procs (current_inferior);
c906108c
SS
132
133 thread = inf_tid_to_thread (current_inferior, inferior_pid);
c5aa993b 134 if (!thread)
da59e081
JM
135 error ("Can't fetch registers from thread %d: No such thread",
136 inferior_pid);
c906108c 137
da59e081 138 if (regno < NUM_GREGS || regno == -1)
c906108c 139 {
da59e081
JM
140 thread_state_t state;
141
142 /* This does the dirty work for us. */
143 state = proc_get_state (thread, 0);
144 if (!state)
c906108c 145 {
da59e081
JM
146 warning ("Couldn't fetch registers from %s",
147 proc_string (thread));
148 return;
c906108c
SS
149 }
150
da59e081 151 if (regno == -1)
c906108c 152 {
da59e081
JM
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;
c906108c
SS
160 }
161 else
162 {
da59e081
JM
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);
c906108c
SS
167 }
168 }
da59e081
JM
169
170 if (regno >= NUM_GREGS || regno == -1)
171 {
172 proc_debug (thread, "fetching floating-point registers");
173
174 fetch_fpregs (thread);
175 }
c906108c 176}
da59e081 177
c906108c 178\f
da59e081
JM
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. */
183static void
184convert_to_env387 (struct env387 *ep, char *regs, signed char *valid)
c906108c
SS
185{
186 int i;
c5aa993b 187
da59e081
JM
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. */
219static void
220store_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;
c5aa993b 225
da59e081
JM
226 err = thread_get_state (thread->port, i386_FLOAT_STATE,
227 (thread_state_t) &state, &count);
228 if (err)
c906108c 229 {
da59e081
JM
230 warning ("Couldn't fetch floating-point state from %s",
231 proc_string (thread));
232 return;
c906108c 233 }
c5aa993b 234
da59e081
JM
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)
c906108c 241 {
da59e081
JM
242 warning ("Couldn't store floating-point state into %s",
243 proc_string (thread));
244 return;
c906108c 245 }
c906108c 246}
c5aa993b 247
da59e081
JM
248/* Store at least register REGNO, or all regs if REGNO == -1. */
249void
250gnu_store_registers (int regno)
c5aa993b 251{
da59e081 252 struct proc *thread;
c906108c 253
da59e081
JM
254 /* Make sure we know about new threads. */
255 inf_update_procs (current_inferior);
c5aa993b 256
da59e081 257 thread = inf_tid_to_thread (current_inferior, inferior_pid);
c906108c 258 if (!thread)
da59e081
JM
259 error ("Couldn't store registers into thread %d: No such thread",
260 inferior_pid);
c906108c 261
da59e081 262 if (regno < NUM_GREGS || regno == -1)
c906108c 263 {
da59e081
JM
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;
c906108c 268
da59e081
JM
269 if (!was_aborted && was_valid)
270 memcpy (&old_state, &thread->state, sizeof (old_state));
c906108c 271
da59e081
JM
272 state = proc_get_state (thread, 1);
273 if (!state)
274 {
275 warning ("Couldn't store registers into %s", proc_string (thread));
276 return;
277 }
c906108c 278
da59e081
JM
279 if (!was_aborted && was_valid)
280 /* See which registers have changed after aborting the thread. */
281 {
282 int check_regno;
283
284 for (check_regno = 0; check_regno < NUM_GREGS; check_regno++)
285 if ((thread->fetched_regs & (1 << check_regno))
286 && memcpy (REG_ADDR (&old_state, check_regno),
287 REG_ADDR (state, check_regno),
288 REGISTER_RAW_SIZE (check_regno)))
289 /* Register CHECK_REGNO has changed! Ack! */
290 {
291 warning ("Register %s changed after the thread was aborted",
292 REGISTER_NAME (check_regno));
293 if (regno >= 0 && regno != check_regno)
294 /* Update gdb's copy of the register. */
295 supply_register (check_regno, REG_ADDR (state, check_regno));
296 else
297 warning ("... also writing this register! Suspicious...");
298 }
299 }
c906108c 300
da59e081
JM
301#define fill(state, regno) \
302 memcpy (REG_ADDR(state, regno), &registers[REGISTER_BYTE (regno)], \
303 REGISTER_RAW_SIZE (regno))
c906108c 304
da59e081
JM
305 if (regno == -1)
306 {
307 int i;
308
309 proc_debug (thread, "storing all registers");
c5aa993b 310
da59e081
JM
311 for (i = 0; i < NUM_GREGS; i++)
312 if (register_valid[i])
313 fill (state, i);
314 }
315 else
316 {
317 proc_debug (thread, "storing register %s", REGISTER_NAME (regno));
c906108c 318
da59e081
JM
319 assert (register_valid[regno]);
320 fill (state, regno);
321 }
c906108c 322 }
c5aa993b 323
da59e081 324#undef fill
c906108c 325
da59e081
JM
326 if (regno >= NUM_GREGS || regno == -1)
327 {
328 proc_debug (thread, "storing floating-point registers");
329
330 store_fpregs (thread);
331 }
c906108c 332}
This page took 0.05284 seconds and 4 git commands to generate.