63c3bd0d7d8afbf44f76c5d49483c73107f09064
[deliverable/binutils-gdb.git] / gdb / i386gnu-nat.c
1 /* Low level interface to I386 running the GNU Hurd
2 Copyright (C) 1992 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, Boston, MA 02111-1307, USA. */
19
20 #include "defs.h"
21 #include "inferior.h"
22 #include "floatformat.h"
23
24 #include <stdio.h>
25
26 #include <mach.h>
27 #include <mach/message.h>
28 #include <mach/exception.h>
29 #include <mach_error.h>
30
31 #include "gnu-nat.h"
32
33 /* Hmmm... Should this not be here?
34 * Now for i386_float_info() target_has_execution
35 */
36 #include <target.h>
37
38 /* @@@ Should move print_387_status() to i387-tdep.c */
39 extern void print_387_control_word (); /* i387-tdep.h */
40 extern void print_387_status_word ();
41 \f
42 /* Find offsets to thread states at compile time.
43 * If your compiler does not grok this, calculate offsets
44 * offsets yourself and use them (or get a compatible compiler :-)
45 */
46
47 #define REG_OFFSET(reg) (int)(&((struct i386_thread_state *)0)->reg)
48
49 /* at reg_offset[i] is the offset to the i386_thread_state
50 * location where the gdb registers[i] is stored.
51 */
52
53 static int reg_offset[] =
54 {
55 REG_OFFSET(eax), REG_OFFSET(ecx), REG_OFFSET(edx), REG_OFFSET(ebx),
56 REG_OFFSET(uesp), REG_OFFSET(ebp), REG_OFFSET(esi), REG_OFFSET(edi),
57 REG_OFFSET(eip), REG_OFFSET(efl), REG_OFFSET(cs), REG_OFFSET(ss),
58 REG_OFFSET(ds), REG_OFFSET(es), REG_OFFSET(fs), REG_OFFSET(gs)
59 };
60
61 #define REG_ADDR(state,regnum) ((char *)(state)+reg_offset[regnum])
62
63 /* Fetch COUNT contiguous registers from thread STATE starting from REGNUM
64 * Caller knows that the regs handled in one transaction are of same size.
65 */
66 #define FETCH_REGS(state, regnum, count) \
67 memcpy (&registers[REGISTER_BYTE (regnum)], \
68 REG_ADDR (state, regnum), \
69 count * REGISTER_RAW_SIZE (regnum))
70
71 /* Store COUNT contiguous registers to thread STATE starting from REGNUM */
72 #define STORE_REGS(state, regnum, count) \
73 memcpy (REG_ADDR (state, regnum), \
74 &registers[REGISTER_BYTE (regnum)], \
75 count * REGISTER_RAW_SIZE (regnum))
76 \f
77 /*
78 * Fetch inferiors registers for gdb.
79 * REG specifies which (as gdb views it) register, -1 for all.
80 */
81 void
82 gnu_fetch_registers (int reg)
83 {
84 thread_state_t state;
85 struct proc *thread = inf_tid_to_thread (current_inferior, inferior_pid);
86
87 if (!thread)
88 error ("fetch inferior registers: %d: Invalid thread", inferior_pid);
89
90 state = proc_get_state (thread, 0);
91
92 if (! state)
93 warning ("Couldn't fetch register %s.", reg_names[reg]);
94 else if (reg >= 0)
95 {
96 proc_debug (thread, "fetching register: %s", reg_names[reg]);
97 supply_register (reg, REG_ADDR(state, reg));
98 thread->fetched_regs |= (1 << reg);
99 }
100 else
101 {
102 proc_debug (thread, "fetching all registers");
103 for (reg = 0; reg < NUM_REGS; reg++)
104 supply_register (reg, REG_ADDR(state, reg));
105 thread->fetched_regs = ~0;
106 }
107 }
108 \f
109 /* Store our register values back into the inferior.
110 * If REG is -1, do this for all registers.
111 * Otherwise, REG specifies which register
112 *
113 * On mach3 all registers are always saved in one call.
114 */
115 void
116 gnu_store_registers (reg)
117 int reg;
118 {
119 int was_aborted, was_valid;
120 thread_state_t state;
121 thread_state_data_t old_state;
122 struct proc *thread = inf_tid_to_thread (current_inferior, inferior_pid);
123
124 if (! thread)
125 error ("store inferior registers: %d: Invalid thread", inferior_pid);
126
127 proc_debug (thread, "storing register %s.", reg_names[reg]);
128
129 was_aborted = thread->aborted;
130 was_valid = thread->state_valid;
131 if (! was_aborted && was_valid)
132 bcopy (&thread->state, &old_state, sizeof (old_state));
133
134 state = proc_get_state (thread, 1);
135
136 if (! state)
137 warning ("Couldn't store register %s.", reg_names[reg]);
138 else
139 {
140 if (! was_aborted && was_valid)
141 /* See which registers have changed after aborting the thread. */
142 {
143 int check_reg;
144 for (check_reg = 0; check_reg < NUM_REGS; check_reg++)
145 if ((thread->fetched_regs & (1 << check_reg))
146 && bcmp (REG_ADDR (&old_state, check_reg),
147 REG_ADDR (state, check_reg),
148 REGISTER_RAW_SIZE (check_reg)))
149 /* Register CHECK_REG has changed! Ack! */
150 {
151 warning ("Register %s changed after thread was aborted.",
152 reg_names [check_reg]);
153 if (reg >= 0 && reg != check_reg)
154 /* Update gdb's copy of the register. */
155 supply_register (check_reg, REG_ADDR (state, check_reg));
156 else
157 warning ("... also writing this register! Suspicious...");
158 }
159 }
160
161 if (reg >= 0)
162 {
163 proc_debug (thread, "storing register: %s", reg_names[reg]);
164 STORE_REGS (state, reg, 1);
165 }
166 else
167 {
168 proc_debug (thread, "storing all registers");
169 for (reg = 0; reg < NUM_REGS; reg++)
170 STORE_REGS (state, reg, 1);
171 }
172 }
173 }
174 \f
175 /* jtv@hut.fi: I copied and modified this 387 code from
176 * gdb/i386-xdep.c. Modifications for Mach 3.0.
177 *
178 * i387 status dumper. See also i387-tdep.c
179 */
180 struct env387
181 {
182 unsigned short control;
183 unsigned short r0;
184 unsigned short status;
185 unsigned short r1;
186 unsigned short tag;
187 unsigned short r2;
188 unsigned long eip;
189 unsigned short code_seg;
190 unsigned short opcode;
191 unsigned long operand;
192 unsigned short operand_seg;
193 unsigned short r3;
194 unsigned char regs[8][10];
195 };
196 /* This routine is machine independent?
197 * Should move it to i387-tdep.c but you need to export struct env387
198 */
199 static
200 print_387_status (status, ep)
201 unsigned short status;
202 struct env387 *ep;
203 {
204 int i;
205 int bothstatus;
206 int top;
207 int fpreg;
208 unsigned char *p;
209
210 bothstatus = ((status != 0) && (ep->status != 0));
211 if (status != 0)
212 {
213 if (bothstatus)
214 printf_unfiltered ("u: ");
215 print_387_status_word (status);
216 }
217
218 if (ep->status != 0)
219 {
220 if (bothstatus)
221 printf_unfiltered ("e: ");
222 print_387_status_word (ep->status);
223 }
224
225 print_387_control_word (ep->control);
226 printf_unfiltered ("last exception: ");
227 printf_unfiltered ("opcode %s; ", local_hex_string(ep->opcode));
228 printf_unfiltered ("pc %s:", local_hex_string(ep->code_seg));
229 printf_unfiltered ("%s; ", local_hex_string(ep->eip));
230 printf_unfiltered ("operand %s", local_hex_string(ep->operand_seg));
231 printf_unfiltered (":%s\n", local_hex_string(ep->operand));
232
233 top = (ep->status >> 11) & 7;
234
235 printf_unfiltered ("regno tag msb lsb value\n");
236 for (fpreg = 7; fpreg >= 0; fpreg--)
237 {
238 double val;
239
240 printf_unfiltered ("%s %d: ", fpreg == top ? "=>" : " ", fpreg);
241
242 switch ((ep->tag >> (fpreg * 2)) & 3)
243 {
244 case 0: printf_unfiltered ("valid "); break;
245 case 1: printf_unfiltered ("zero "); break;
246 case 2: printf_unfiltered ("trap "); break;
247 case 3: printf_unfiltered ("empty "); break;
248 }
249 for (i = 9; i >= 0; i--)
250 printf_unfiltered ("%02x", ep->regs[fpreg][i]);
251
252 floatformat_to_double (&floatformat_i387_ext, (char *)ep->regs[fpreg],
253 &val);
254 printf_unfiltered (" %g\n", val);
255 }
256 if (ep->r0)
257 printf_unfiltered ("warning: reserved0 is %s\n", local_hex_string(ep->r0));
258 if (ep->r1)
259 printf_unfiltered ("warning: reserved1 is %s\n", local_hex_string(ep->r1));
260 if (ep->r2)
261 printf_unfiltered ("warning: reserved2 is %s\n", local_hex_string(ep->r2));
262 if (ep->r3)
263 printf_unfiltered ("warning: reserved3 is %s\n", local_hex_string(ep->r3));
264 }
265
266 /*
267 * values that go into fp_kind (from <i386/fpreg.h>)
268 */
269 #define FP_NO 0 /* no fp chip, no emulator (no fp support) */
270 #define FP_SW 1 /* no fp chip, using software emulator */
271 #define FP_HW 2 /* chip present bit */
272 #define FP_287 2 /* 80287 chip present */
273 #define FP_387 3 /* 80387 chip present */
274
275 typedef struct fpstate {
276 #if 1
277 unsigned char state[FP_STATE_BYTES]; /* "hardware" state */
278 #else
279 struct env387 state; /* Actually this */
280 #endif
281 int status; /* Duplicate status */
282 } *fpstate_t;
283
284 /* Mach 3 specific routines.
285 */
286 static int
287 get_i387_state (fstate)
288 struct fpstate *fstate;
289 {
290 error_t err;
291 thread_state_data_t state;
292 unsigned int fsCnt = i386_FLOAT_STATE_COUNT;
293 struct i386_float_state *fsp;
294 struct proc *thread = inf_tid_to_thread (current_inferior, inferior_pid);
295
296 if (!thread)
297 error ("get_i387_state: Invalid thread");
298
299 proc_abort (thread, 0); /* Make sure THREAD's in a reasonable state. */
300
301 err = thread_get_state (thread->port, i386_FLOAT_STATE, state, &fsCnt);
302 if (err)
303 {
304 warning ("Can not get live floating point state: %s",
305 mach_error_string (err));
306 return 0;
307 }
308
309 fsp = (struct i386_float_state *)state;
310 /* The 387 chip (also 486 counts) or a software emulator? */
311 if (!fsp->initialized || (fsp->fpkind != FP_387 && fsp->fpkind != FP_SW))
312 return 0;
313
314 /* Clear the target then copy thread's float state there.
315 Make a copy of the status word, for some reason?
316 */
317 memset (fstate, 0, sizeof (struct fpstate));
318
319 fstate->status = fsp->exc_status;
320
321 memcpy (fstate->state, (char *)&fsp->hw_state, FP_STATE_BYTES);
322
323 return 1;
324 }
325
326 /*
327 * This is called by "info float" command
328 */
329 void
330 i386_mach3_float_info()
331 {
332 char buf [sizeof (struct fpstate) + 2 * sizeof (int)];
333 int valid = 0;
334 fpstate_t fps;
335
336 if (target_has_execution)
337 valid = get_i387_state (buf);
338
339 if (!valid)
340 {
341 warning ("no floating point status saved");
342 return;
343 }
344
345 fps = (fpstate_t) buf;
346
347 print_387_status (fps->status, (struct env387 *)fps->state);
348 }
This page took 0.03926 seconds and 4 git commands to generate.