* d10v-dis.c: Fix formatting.
[deliverable/binutils-gdb.git] / gdb / i386m3-nat.c
CommitLineData
c906108c 1/* Low level interface to I386 running mach 3.0.
b6ba6518
KB
2 Copyright 1992, 1993, 1994, 1996, 2000, 2001
3 Free Software Foundation, Inc.
c906108c 4
c5aa993b 5 This file is part of GDB.
c906108c 6
c5aa993b
JM
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.
c906108c 11
c5aa993b
JM
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.
c906108c 16
c5aa993b
JM
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. */
c906108c
SS
21
22#include "defs.h"
23#include "inferior.h"
24#include "floatformat.h"
4e052eda 25#include "regcache.h"
c906108c
SS
26
27#include <stdio.h>
28
29#include <mach.h>
30#include <mach/message.h>
31#include <mach/exception.h>
32#include <mach_error.h>
33
34/* Hmmm... Should this not be here?
35 * Now for i386_float_info() target_has_execution
36 */
37#include <target.h>
38
39/* This mess is duplicated in bfd/i386mach3.h
c5aa993b 40
c906108c
SS
41 * This is an ugly way to hack around the incorrect
42 * definition of UPAGES in i386/machparam.h.
43 *
44 * The definition should specify the size reserved
45 * for "struct user" in core files in PAGES,
46 * but instead it gives it in 512-byte core-clicks
47 * for i386 and i860.
48 */
49#include <sys/param.h>
50#if UPAGES == 16
51#define UAREA_SIZE ctob(UPAGES)
52#elif UPAGES == 2
53#define UAREA_SIZE (NBPG*UPAGES)
54#else
c5aa993b 55FIXME ! !UPAGES is neither 2 nor 16
c906108c
SS
56#endif
57
58/* @@@ Should move print_387_status() to i387-tdep.c */
59extern void print_387_control_word (); /* i387-tdep.h */
60extern void print_387_status_word ();
61
62#define private static
c906108c 63\f
c5aa993b 64
c906108c
SS
65/* Find offsets to thread states at compile time.
66 * If your compiler does not grok this, calculate offsets
67 * offsets yourself and use them (or get a compatible compiler :-)
68 */
69
70#define REG_OFFSET(reg) (int)(&((struct i386_thread_state *)0)->reg)
71
72/* at reg_offset[i] is the offset to the i386_thread_state
73 * location where the gdb registers[i] is stored.
74 */
75
c5aa993b 76static int reg_offset[] =
c906108c 77{
c5aa993b
JM
78 REG_OFFSET (eax), REG_OFFSET (ecx), REG_OFFSET (edx), REG_OFFSET (ebx),
79 REG_OFFSET (uesp), REG_OFFSET (ebp), REG_OFFSET (esi), REG_OFFSET (edi),
80 REG_OFFSET (eip), REG_OFFSET (efl), REG_OFFSET (cs), REG_OFFSET (ss),
81 REG_OFFSET (ds), REG_OFFSET (es), REG_OFFSET (fs), REG_OFFSET (gs)
c906108c
SS
82};
83
84#define REG_ADDRESS(state,regnum) ((char *)(state)+reg_offset[regnum])
85
86/* Fetch COUNT contiguous registers from thread STATE starting from REGNUM
87 * Caller knows that the regs handled in one transaction are of same size.
88 */
89#define FETCH_REGS(state, regnum, count) \
90 memcpy (&registers[REGISTER_BYTE (regnum)], \
91 REG_ADDRESS (state, regnum), \
92 count*REGISTER_SIZE)
93
94/* Store COUNT contiguous registers to thread STATE starting from REGNUM */
95#define STORE_REGS(state, regnum, count) \
96 memcpy (REG_ADDRESS (state, regnum), \
97 &registers[REGISTER_BYTE (regnum)], \
98 count*REGISTER_SIZE)
99\f
100/*
101 * Fetch inferiors registers for gdb.
102 * REGNO specifies which (as gdb views it) register, -1 for all.
103 */
104
105void
fba45db2 106fetch_inferior_registers (int regno)
c906108c
SS
107{
108 kern_return_t ret;
109 thread_state_data_t state;
110 unsigned int stateCnt = i386_THREAD_STATE_COUNT;
111 int index;
c5aa993b
JM
112
113 if (!MACH_PORT_VALID (current_thread))
c906108c
SS
114 error ("fetch inferior registers: Invalid thread");
115
116 if (must_suspend_thread)
117 setup_thread (current_thread, 1);
118
119 ret = thread_get_state (current_thread,
120 i386_THREAD_STATE,
121 state,
122 &stateCnt);
123
124 if (ret != KERN_SUCCESS)
125 warning ("fetch_inferior_registers: %s ",
126 mach_error_string (ret));
127#if 0
128 /* It may be more effective to store validate all of them,
129 * since we fetched them all anyway
130 */
131 else if (regno != -1)
c5aa993b 132 supply_register (regno, (char *) state + reg_offset[regno]);
c906108c
SS
133#endif
134 else
135 {
c5aa993b
JM
136 for (index = 0; index < NUM_REGS; index++)
137 supply_register (index, (char *) state + reg_offset[index]);
c906108c
SS
138 }
139
140 if (must_suspend_thread)
141 setup_thread (current_thread, 0);
142}
143\f
144/* Store our register values back into the inferior.
145 * If REGNO is -1, do this for all registers.
146 * Otherwise, REGNO specifies which register
147 *
148 * On mach3 all registers are always saved in one call.
149 */
150void
fba45db2 151store_inferior_registers (int regno)
c906108c
SS
152{
153 kern_return_t ret;
154 thread_state_data_t state;
155 unsigned int stateCnt = i386_THREAD_STATE_COUNT;
156 register int index;
157
c5aa993b 158 if (!MACH_PORT_VALID (current_thread))
c906108c
SS
159 error ("store inferior registers: Invalid thread");
160
161 if (must_suspend_thread)
162 setup_thread (current_thread, 1);
163
164 /* Fetch the state of the current thread */
165 ret = thread_get_state (current_thread,
166 i386_THREAD_STATE,
167 state,
168 &stateCnt);
169
c5aa993b 170 if (ret != KERN_SUCCESS)
c906108c
SS
171 {
172 warning ("store_inferior_registers (get): %s",
173 mach_error_string (ret));
174 if (must_suspend_thread)
175 setup_thread (current_thread, 0);
176 return;
177 }
178
179 /* move gdb's registers to thread's state
c5aa993b 180
c906108c
SS
181 * Since we save all registers anyway, save the ones
182 * that gdb thinks are valid (e.g. ignore the regno
183 * parameter)
184 */
185#if 0
186 if (regno != -1)
187 STORE_REGS (state, regno, 1);
188 else
189#endif
190 {
c5aa993b 191 for (index = 0; index < NUM_REGS; index++)
c906108c
SS
192 STORE_REGS (state, index, 1);
193 }
c5aa993b 194
c906108c
SS
195 /* Write gdb's current view of register to the thread
196 */
197 ret = thread_set_state (current_thread,
198 i386_THREAD_STATE,
199 state,
200 i386_THREAD_STATE_COUNT);
c5aa993b 201
c906108c
SS
202 if (ret != KERN_SUCCESS)
203 warning ("store_inferior_registers (set): %s",
204 mach_error_string (ret));
205
206 if (must_suspend_thread)
207 setup_thread (current_thread, 0);
208}
c906108c
SS
209\f
210
c5aa993b 211
c906108c
SS
212/* Return the address in the core dump or inferior of register REGNO.
213 * BLOCKEND should be the address of the end of the UPAGES area read
214 * in memory, but it's not?
215 *
216 * Currently our UX server dumps the whole thread state to the
217 * core file. If your UX does something else, adapt the routine
218 * below to return the offset to the given register.
219 *
220 * Called by core-aout.c(fetch_core_registers)
221 */
222
223CORE_ADDR
fba45db2 224register_addr (int regno, CORE_ADDR blockend)
c906108c
SS
225{
226 CORE_ADDR addr;
227
228 if (regno < 0 || regno >= NUM_REGS)
229 error ("Invalid register number %d.", regno);
230
231 /* UAREA_SIZE == 8 kB in i386 */
c5aa993b 232 addr = (unsigned int) REG_ADDRESS (UAREA_SIZE - sizeof (struct i386_thread_state), regno);
c906108c
SS
233
234 return addr;
235}
236
237/* jtv@hut.fi: I copied and modified this 387 code from
238 * gdb/i386-xdep.c. Modifications for Mach 3.0.
239 *
240 * i387 status dumper. See also i387-tdep.c
241 */
c5aa993b 242struct env387
c906108c
SS
243{
244 unsigned short control;
245 unsigned short r0;
246 unsigned short status;
247 unsigned short r1;
248 unsigned short tag;
249 unsigned short r2;
250 unsigned long eip;
251 unsigned short code_seg;
252 unsigned short opcode;
253 unsigned long operand;
254 unsigned short operand_seg;
255 unsigned short r3;
256 unsigned char regs[8][10];
257};
258/* This routine is machine independent?
259 * Should move it to i387-tdep.c but you need to export struct env387
260 */
261private
fba45db2 262print_387_status (unsigned short status, struct env387 *ep)
c906108c
SS
263{
264 int i;
265 int bothstatus;
266 int top;
267 int fpreg;
268 unsigned char *p;
c5aa993b 269
c906108c 270 bothstatus = ((status != 0) && (ep->status != 0));
c5aa993b 271 if (status != 0)
c906108c
SS
272 {
273 if (bothstatus)
274 printf_unfiltered ("u: ");
275 print_387_status_word (status);
276 }
c5aa993b
JM
277
278 if (ep->status != 0)
c906108c
SS
279 {
280 if (bothstatus)
281 printf_unfiltered ("e: ");
282 print_387_status_word (ep->status);
283 }
c5aa993b 284
c906108c
SS
285 print_387_control_word (ep->control);
286 printf_unfiltered ("last exception: ");
c5aa993b
JM
287 printf_unfiltered ("opcode %s; ", local_hex_string (ep->opcode));
288 printf_unfiltered ("pc %s:", local_hex_string (ep->code_seg));
289 printf_unfiltered ("%s; ", local_hex_string (ep->eip));
290 printf_unfiltered ("operand %s", local_hex_string (ep->operand_seg));
291 printf_unfiltered (":%s\n", local_hex_string (ep->operand));
292
c906108c 293 top = (ep->status >> 11) & 7;
c5aa993b 294
c906108c 295 printf_unfiltered ("regno tag msb lsb value\n");
c5aa993b 296 for (fpreg = 7; fpreg >= 0; fpreg--)
c906108c
SS
297 {
298 double val;
c5aa993b 299
c906108c 300 printf_unfiltered ("%s %d: ", fpreg == top ? "=>" : " ", fpreg);
c5aa993b
JM
301
302 switch ((ep->tag >> (fpreg * 2)) & 3)
c906108c 303 {
c5aa993b
JM
304 case 0:
305 printf_unfiltered ("valid ");
306 break;
307 case 1:
308 printf_unfiltered ("zero ");
309 break;
310 case 2:
311 printf_unfiltered ("trap ");
312 break;
313 case 3:
314 printf_unfiltered ("empty ");
315 break;
c906108c
SS
316 }
317 for (i = 9; i >= 0; i--)
318 printf_unfiltered ("%02x", ep->regs[fpreg][i]);
c5aa993b
JM
319
320 floatformat_to_double (&floatformat_i387_ext, (char *) ep->regs[fpreg],
321 &val);
c906108c
SS
322 printf_unfiltered (" %g\n", val);
323 }
324 if (ep->r0)
c5aa993b 325 printf_unfiltered ("warning: reserved0 is %s\n", local_hex_string (ep->r0));
c906108c 326 if (ep->r1)
c5aa993b 327 printf_unfiltered ("warning: reserved1 is %s\n", local_hex_string (ep->r1));
c906108c 328 if (ep->r2)
c5aa993b 329 printf_unfiltered ("warning: reserved2 is %s\n", local_hex_string (ep->r2));
c906108c 330 if (ep->r3)
c5aa993b 331 printf_unfiltered ("warning: reserved3 is %s\n", local_hex_string (ep->r3));
c906108c 332}
c5aa993b 333
c906108c
SS
334/*
335 * values that go into fp_kind (from <i386/fpreg.h>)
336 */
c5aa993b
JM
337#define FP_NO 0 /* no fp chip, no emulator (no fp support) */
338#define FP_SW 1 /* no fp chip, using software emulator */
339#define FP_HW 2 /* chip present bit */
340#define FP_287 2 /* 80287 chip present */
341#define FP_387 3 /* 80387 chip present */
c906108c 342
c5aa993b
JM
343typedef struct fpstate
344{
c906108c 345#if 1
c5aa993b 346 unsigned char state[FP_STATE_BYTES]; /* "hardware" state */
c906108c 347#else
c5aa993b 348 struct env387 state; /* Actually this */
c906108c 349#endif
c5aa993b
JM
350 int status; /* Duplicate status */
351}
352 *fpstate_t;
c906108c
SS
353
354/* Mach 3 specific routines.
355 */
356private boolean_t
fba45db2 357get_i387_state (struct fpstate *fstate)
c906108c
SS
358{
359 kern_return_t ret;
360 thread_state_data_t state;
361 unsigned int fsCnt = i386_FLOAT_STATE_COUNT;
362 struct i386_float_state *fsp;
c5aa993b 363
c906108c
SS
364 ret = thread_get_state (current_thread,
365 i386_FLOAT_STATE,
366 state,
367 &fsCnt);
368
369 if (ret != KERN_SUCCESS)
370 {
371 warning ("Can not get live floating point state: %s",
372 mach_error_string (ret));
373 return FALSE;
374 }
375
c5aa993b 376 fsp = (struct i386_float_state *) state;
c906108c
SS
377 /* The 387 chip (also 486 counts) or a software emulator? */
378 if (!fsp->initialized || (fsp->fpkind != FP_387 && fsp->fpkind != FP_SW))
379 return FALSE;
380
381 /* Clear the target then copy thread's float state there.
382 Make a copy of the status word, for some reason?
383 */
384 memset (fstate, 0, sizeof (struct fpstate));
385
386 fstate->status = fsp->exc_status;
387
c5aa993b 388 memcpy (fstate->state, (char *) &fsp->hw_state, FP_STATE_BYTES);
c906108c
SS
389
390 return TRUE;
391}
392
393private boolean_t
fba45db2 394get_i387_core_state (struct fpstate *fstate)
c906108c
SS
395{
396 /* Not implemented yet. Core files do not contain float state. */
397 return FALSE;
398}
399
400/*
401 * This is called by "info float" command
402 */
403void
fba45db2 404i386_mach3_float_info (void)
c906108c 405{
c5aa993b 406 char buf[sizeof (struct fpstate) + 2 * sizeof (int)];
c906108c
SS
407 boolean_t valid = FALSE;
408 fpstate_t fps;
c5aa993b 409
c906108c
SS
410 if (target_has_execution)
411 valid = get_i387_state (buf);
c5aa993b
JM
412#if 0
413 else if (WE HAVE CORE FILE) /* @@@@ Core files not supported */
c906108c 414 valid = get_i387_core_state (buf);
c5aa993b 415#endif
c906108c 416
c5aa993b 417 if (!valid)
c906108c
SS
418 {
419 warning ("no floating point status saved");
420 return;
421 }
c5aa993b 422
c906108c
SS
423 fps = (fpstate_t) buf;
424
c5aa993b 425 print_387_status (fps->status, (struct env387 *) fps->state);
c906108c 426}
This page took 0.131684 seconds and 4 git commands to generate.