1 /* Low level interface to i386 running the GNU Hurd.
2 Copyright (C) 1992, 1995, 1996, 2000 Free Software Foundation, Inc.
4 This file is part of GDB.
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.
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.
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. */
23 #include "floatformat.h"
30 #include <mach_error.h>
31 #include <mach/message.h>
32 #include <mach/exception.h>
36 /* The FPU hardware state. */
39 unsigned short control;
41 unsigned short status;
46 unsigned short code_seg;
47 unsigned short opcode;
48 unsigned long operand;
49 unsigned short operand_seg;
51 unsigned char regs[8][10];
55 /* Offset to the thread_state_t location where REG is stored. */
56 #define REG_OFFSET(reg) offsetof (struct i386_thread_state, reg)
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[] =
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)
68 #define REG_ADDR(state, regnum) ((char *)(state) + reg_offset[regnum])
71 /* Get the whole floating-point state of THREAD and record the
72 values of the corresponding (pseudo) registers. */
74 fetch_fpregs (struct proc *thread)
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;
82 err = thread_get_state (thread->port, i386_FLOAT_STATE,
83 (thread_state_t) &state, &count);
86 warning ("Couldn't fetch floating-point state from %s",
87 proc_string (thread));
91 if (! state.initialized)
92 /* The floating-point state isn't initialized. */
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);
102 /* Supply the floating-point registers. */
103 for (i = 0; i < 8; i++)
104 supply_register (FP0_REGNUM + i, ep->regs[i]);
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);
113 /* Store the code segment and opcode pseudo registers. */
118 supply_register (FCS_REGNUM, (char *) &l);
119 l = ep->opcode & ((1 << 11) - 1);
120 supply_register (FOP_REGNUM, (char *) &l);
124 /* Fetch register REGNO, or all regs if REGNO is -1. */
126 gnu_fetch_registers (int regno)
130 /* Make sure we know about new threads. */
131 inf_update_procs (current_inferior);
133 thread = inf_tid_to_thread (current_inferior, inferior_pid);
135 error ("Can't fetch registers from thread %d: No such thread",
138 if (regno < NUM_GREGS || regno == -1)
140 thread_state_t state;
142 /* This does the dirty work for us. */
143 state = proc_get_state (thread, 0);
146 warning ("Couldn't fetch registers from %s",
147 proc_string (thread));
155 proc_debug (thread, "fetching all register");
157 for (i = 0; i < NUM_GREGS; i++)
158 supply_register (i, REG_ADDR (state, i));
159 thread->fetched_regs = ~0;
163 proc_debug (thread, "fetching register %s", REGISTER_NAME (regno));
165 supply_register (regno, REG_ADDR (state, regno));
166 thread->fetched_regs |= (1 << regno);
170 if (regno >= NUM_GREGS || regno == -1)
172 proc_debug (thread, "fetching floating-point registers");
174 fetch_fpregs (thread);
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. */
184 convert_to_env387 (struct env387 *ep, char *regs, signed char *valid)
188 /* Fill in the floating-point registers. */
189 for (i = 0; i < 8; i++)
190 if (!valid || valid[i])
191 memcpy (ep->regs[i], ®s[REGISTER_BYTE (FP0_REGNUM + i)],
192 REGISTER_RAW_SIZE (FP0_REGNUM + i));
194 #define fill(member, regno) \
195 if (!valid || valid[(regno)]) \
196 memcpy (&ep->member, ®s[REGISTER_BYTE (regno)], \
197 sizeof (ep->member));
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);
208 if (!valid || valid[FCS_REGNUM])
210 (* (int *) ®isters[REGISTER_BYTE (FCS_REGNUM)] & 0xffff);
212 if (!valid || valid[FOP_REGNUM])
214 ((* (int *) ®isters[REGISTER_BYTE (FOP_REGNUM)] & ((1 << 11) - 1)));
217 /* Store the whole floating-point state into THREAD using information
218 from the corresponding (pseudo) registers. */
220 store_fpregs (struct proc *thread)
222 mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT;
223 struct i386_float_state state;
226 err = thread_get_state (thread->port, i386_FLOAT_STATE,
227 (thread_state_t) &state, &count);
230 warning ("Couldn't fetch floating-point state from %s",
231 proc_string (thread));
235 convert_to_env387 ((struct env387 *) state.hw_state,
236 registers, register_valid);
238 err = thread_set_state (thread->port, i386_FLOAT_STATE,
239 (thread_state_t) &state, i386_FLOAT_STATE_COUNT);
242 warning ("Couldn't store floating-point state into %s",
243 proc_string (thread));
248 /* Store at least register REGNO, or all regs if REGNO == -1. */
250 gnu_store_registers (int regno)
254 /* Make sure we know about new threads. */
255 inf_update_procs (current_inferior);
257 thread = inf_tid_to_thread (current_inferior, inferior_pid);
259 error ("Couldn't store registers into thread %d: No such thread",
262 if (regno < NUM_GREGS || regno == -1)
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;
270 if (!was_aborted && was_valid)
271 memcpy (&old_state, &thread->state, sizeof (old_state));
273 state = proc_get_state (thread, 1);
276 warning ("Couldn't store registers into %s", proc_string (thread));
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;
284 if (!was_aborted && was_valid)
285 /* See which registers have changed after aborting the thread. */
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! */
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));
302 warning ("... also writing this register! Suspicious...");
306 #define fill(state, regno) \
307 memcpy (REG_ADDR(state, regno), ®isters[REGISTER_BYTE (regno)], \
308 REGISTER_RAW_SIZE (regno))
314 proc_debug (thread, "storing all registers");
316 for (i = 0; i < NUM_GREGS; i++)
317 if (register_valid[i])
322 proc_debug (thread, "storing register %s", REGISTER_NAME (regno));
324 assert (register_valid[regno]);
328 /* Restore the T bit. */
329 ((struct i386_thread_state *)state)->efl &= ~0x100;
330 ((struct i386_thread_state *)state)->efl |= trace;
335 if (regno >= NUM_GREGS || regno == -1)
337 proc_debug (thread, "storing floating-point registers");
339 store_fpregs (thread);