1130812Smarcel/* Low level interface to i386 running the GNU Hurd.
2130812Smarcel   Copyright 1992, 1995, 1996, 1998, 2000, 2001
3130812Smarcel   Free Software Foundation, Inc.
4130812Smarcel
5130812Smarcel   This file is part of GDB.
6130812Smarcel
7130812Smarcel   This program is free software; you can redistribute it and/or modify
8130812Smarcel   it under the terms of the GNU General Public License as published by
9130812Smarcel   the Free Software Foundation; either version 2 of the License, or
10130812Smarcel   (at your option) any later version.
11130812Smarcel
12130812Smarcel   This program is distributed in the hope that it will be useful,
13130812Smarcel   but WITHOUT ANY WARRANTY; without even the implied warranty of
14130812Smarcel   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15130812Smarcel   GNU General Public License for more details.
16130812Smarcel
17130812Smarcel   You should have received a copy of the GNU General Public License
18130812Smarcel   along with this program; if not, write to the Free Software
19130812Smarcel   Foundation, Inc., 59 Temple Place - Suite 330,
20130812Smarcel   Boston, MA 02111-1307, USA.  */
21130812Smarcel
22130812Smarcel#include "defs.h"
23130812Smarcel#include "inferior.h"
24130812Smarcel#include "floatformat.h"
25130812Smarcel#include "regcache.h"
26130812Smarcel
27130812Smarcel#include "gdb_assert.h"
28130812Smarcel#include <errno.h>
29130812Smarcel#include <stdio.h>
30130812Smarcel
31130812Smarcel#include <mach.h>
32130812Smarcel#include <mach_error.h>
33130812Smarcel#include <mach/message.h>
34130812Smarcel#include <mach/exception.h>
35130812Smarcel
36130812Smarcel#include "i386-tdep.h"
37130812Smarcel
38130812Smarcel#include "gnu-nat.h"
39130812Smarcel#include "i387-tdep.h"
40130812Smarcel
41130812Smarcel#ifdef HAVE_SYS_PROCFS_H
42130812Smarcel# include <sys/procfs.h>
43130812Smarcel# include "gregset.h"
44130812Smarcel#endif
45130812Smarcel
46130812Smarcel/* Offset to the thread_state_t location where REG is stored.  */
47130812Smarcel#define REG_OFFSET(reg) offsetof (struct i386_thread_state, reg)
48130812Smarcel
49130812Smarcel/* At REG_OFFSET[N] is the offset to the thread_state_t location where
50130812Smarcel   the GDB register N is stored.  */
51130812Smarcelstatic int reg_offset[] =
52130812Smarcel{
53130812Smarcel  REG_OFFSET (eax), REG_OFFSET (ecx), REG_OFFSET (edx), REG_OFFSET (ebx),
54130812Smarcel  REG_OFFSET (uesp), REG_OFFSET (ebp), REG_OFFSET (esi), REG_OFFSET (edi),
55130812Smarcel  REG_OFFSET (eip), REG_OFFSET (efl), REG_OFFSET (cs), REG_OFFSET (ss),
56130812Smarcel  REG_OFFSET (ds), REG_OFFSET (es), REG_OFFSET (fs), REG_OFFSET (gs)
57130812Smarcel};
58130812Smarcel
59130812Smarcel#define REG_ADDR(state, regnum) ((char *)(state) + reg_offset[regnum])
60130812Smarcel
61130812Smarcel
62130812Smarcel/* Get the whole floating-point state of THREAD and record the
63130812Smarcel   values of the corresponding (pseudo) registers.  */
64130812Smarcelstatic void
65130812Smarcelfetch_fpregs (struct proc *thread)
66130812Smarcel{
67130812Smarcel  mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT;
68130812Smarcel  struct i386_float_state state;
69130812Smarcel  error_t err;
70130812Smarcel
71130812Smarcel  err = thread_get_state (thread->port, i386_FLOAT_STATE,
72130812Smarcel			  (thread_state_t) &state, &count);
73130812Smarcel  if (err)
74130812Smarcel    {
75130812Smarcel      warning ("Couldn't fetch floating-point state from %s",
76130812Smarcel	       proc_string (thread));
77130812Smarcel      return;
78130812Smarcel    }
79130812Smarcel
80130812Smarcel  if (!state.initialized)
81130812Smarcel    /* The floating-point state isn't initialized.  */
82130812Smarcel    {
83130812Smarcel      int i;
84130812Smarcel
85130812Smarcel      for (i = FP0_REGNUM; i <= FOP_REGNUM; i++)
86130812Smarcel	supply_register (i, NULL);
87130812Smarcel
88130812Smarcel      return;
89130812Smarcel    }
90130812Smarcel
91130812Smarcel  /* Supply the floating-point registers.  */
92130812Smarcel  i387_supply_fsave (current_regcache, -1, state.hw_state);
93130812Smarcel}
94130812Smarcel
95130812Smarcel#ifdef HAVE_SYS_PROCFS_H
96130812Smarcel/* These two calls are used by the core-regset.c code for
97130812Smarcel   reading ELF core files.  */
98130812Smarcelvoid
99130812Smarcelsupply_gregset (gdb_gregset_t *gregs)
100130812Smarcel{
101130812Smarcel  int i;
102130812Smarcel  for (i = 0; i < I386_NUM_GREGS; i++)
103130812Smarcel    supply_register (i, REG_ADDR (gregs, i));
104130812Smarcel}
105130812Smarcel
106130812Smarcelvoid
107130812Smarcelsupply_fpregset (gdb_fpregset_t *fpregs)
108130812Smarcel{
109130812Smarcel  i387_supply_fsave (current_regcache, -1, fpregs);
110130812Smarcel}
111130812Smarcel#endif
112130812Smarcel
113130812Smarcel/* Fetch register REGNO, or all regs if REGNO is -1.  */
114130812Smarcelvoid
115130812Smarcelgnu_fetch_registers (int regno)
116130812Smarcel{
117130812Smarcel  struct proc *thread;
118130812Smarcel
119130812Smarcel  /* Make sure we know about new threads.  */
120130812Smarcel  inf_update_procs (current_inferior);
121130812Smarcel
122130812Smarcel  thread = inf_tid_to_thread (current_inferior, PIDGET (inferior_ptid));
123130812Smarcel  if (!thread)
124130812Smarcel    error ("Can't fetch registers from thread %d: No such thread",
125130812Smarcel	   PIDGET (inferior_ptid));
126130812Smarcel
127130812Smarcel  if (regno < I386_NUM_GREGS || regno == -1)
128130812Smarcel    {
129130812Smarcel      thread_state_t state;
130130812Smarcel
131130812Smarcel      /* This does the dirty work for us.  */
132130812Smarcel      state = proc_get_state (thread, 0);
133130812Smarcel      if (!state)
134130812Smarcel	{
135130812Smarcel	  warning ("Couldn't fetch registers from %s",
136130812Smarcel		   proc_string (thread));
137130812Smarcel	  return;
138130812Smarcel	}
139130812Smarcel
140130812Smarcel      if (regno == -1)
141130812Smarcel	{
142130812Smarcel	  int i;
143130812Smarcel
144130812Smarcel	  proc_debug (thread, "fetching all register");
145130812Smarcel
146130812Smarcel	  for (i = 0; i < I386_NUM_GREGS; i++)
147130812Smarcel	    supply_register (i, REG_ADDR (state, i));
148130812Smarcel	  thread->fetched_regs = ~0;
149130812Smarcel	}
150130812Smarcel      else
151130812Smarcel	{
152130812Smarcel	  proc_debug (thread, "fetching register %s", REGISTER_NAME (regno));
153130812Smarcel
154130812Smarcel	  supply_register (regno, REG_ADDR (state, regno));
155130812Smarcel	  thread->fetched_regs |= (1 << regno);
156130812Smarcel	}
157130812Smarcel    }
158130812Smarcel
159130812Smarcel  if (regno >= I386_NUM_GREGS || regno == -1)
160130812Smarcel    {
161130812Smarcel      proc_debug (thread, "fetching floating-point registers");
162130812Smarcel
163130812Smarcel      fetch_fpregs (thread);
164130812Smarcel    }
165130812Smarcel}
166130812Smarcel
167130812Smarcel
168130812Smarcel/* Store the whole floating-point state into THREAD using information
169130812Smarcel   from the corresponding (pseudo) registers.  */
170130812Smarcelstatic void
171130812Smarcelstore_fpregs (struct proc *thread, int regno)
172130812Smarcel{
173130812Smarcel  mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT;
174130812Smarcel  struct i386_float_state state;
175130812Smarcel  error_t err;
176130812Smarcel
177130812Smarcel  err = thread_get_state (thread->port, i386_FLOAT_STATE,
178130812Smarcel			  (thread_state_t) &state, &count);
179130812Smarcel  if (err)
180130812Smarcel    {
181130812Smarcel      warning ("Couldn't fetch floating-point state from %s",
182130812Smarcel	       proc_string (thread));
183130812Smarcel      return;
184130812Smarcel    }
185130812Smarcel
186130812Smarcel  /* FIXME: kettenis/2001-07-15: Is this right?  Should we somehow
187130812Smarcel     take into account DEPRECATED_REGISTER_VALID like the old code did?  */
188130812Smarcel  i387_fill_fsave (state.hw_state, regno);
189130812Smarcel
190130812Smarcel  err = thread_set_state (thread->port, i386_FLOAT_STATE,
191130812Smarcel			  (thread_state_t) &state, i386_FLOAT_STATE_COUNT);
192130812Smarcel  if (err)
193130812Smarcel    {
194130812Smarcel      warning ("Couldn't store floating-point state into %s",
195130812Smarcel	       proc_string (thread));
196130812Smarcel      return;
197130812Smarcel    }
198130812Smarcel}
199130812Smarcel
200130812Smarcel/* Store at least register REGNO, or all regs if REGNO == -1.  */
201130812Smarcelvoid
202130812Smarcelgnu_store_registers (int regno)
203130812Smarcel{
204130812Smarcel  struct proc *thread;
205130812Smarcel
206130812Smarcel  /* Make sure we know about new threads.  */
207130812Smarcel  inf_update_procs (current_inferior);
208130812Smarcel
209130812Smarcel  thread = inf_tid_to_thread (current_inferior, PIDGET (inferior_ptid));
210130812Smarcel  if (!thread)
211130812Smarcel    error ("Couldn't store registers into thread %d: No such thread",
212130812Smarcel	   PIDGET (inferior_ptid));
213130812Smarcel
214130812Smarcel  if (regno < I386_NUM_GREGS || regno == -1)
215130812Smarcel    {
216130812Smarcel      thread_state_t state;
217130812Smarcel      thread_state_data_t old_state;
218130812Smarcel      int was_aborted = thread->aborted;
219130812Smarcel      int was_valid = thread->state_valid;
220130812Smarcel      int trace;
221130812Smarcel
222130812Smarcel      if (!was_aborted && was_valid)
223130812Smarcel	memcpy (&old_state, &thread->state, sizeof (old_state));
224130812Smarcel
225130812Smarcel      state = proc_get_state (thread, 1);
226130812Smarcel      if (!state)
227130812Smarcel	{
228130812Smarcel	  warning ("Couldn't store registers into %s", proc_string (thread));
229130812Smarcel	  return;
230130812Smarcel	}
231130812Smarcel
232130812Smarcel      /* Save the T bit.  We might try to restore the %eflags register
233130812Smarcel         below, but changing the T bit would seriously confuse GDB.  */
234130812Smarcel      trace = ((struct i386_thread_state *)state)->efl & 0x100;
235130812Smarcel
236130812Smarcel      if (!was_aborted && was_valid)
237130812Smarcel	/* See which registers have changed after aborting the thread.  */
238130812Smarcel	{
239130812Smarcel	  int check_regno;
240130812Smarcel
241130812Smarcel	  for (check_regno = 0; check_regno < I386_NUM_GREGS; check_regno++)
242130812Smarcel	    if ((thread->fetched_regs & (1 << check_regno))
243130812Smarcel		&& memcpy (REG_ADDR (&old_state, check_regno),
244130812Smarcel			   REG_ADDR (state, check_regno),
245130812Smarcel			   DEPRECATED_REGISTER_RAW_SIZE (check_regno)))
246130812Smarcel	      /* Register CHECK_REGNO has changed!  Ack!  */
247130812Smarcel	      {
248130812Smarcel		warning ("Register %s changed after the thread was aborted",
249130812Smarcel			 REGISTER_NAME (check_regno));
250130812Smarcel		if (regno >= 0 && regno != check_regno)
251130812Smarcel		  /* Update GDB's copy of the register.  */
252130812Smarcel		  supply_register (check_regno, REG_ADDR (state, check_regno));
253130812Smarcel		else
254130812Smarcel		  warning ("... also writing this register!  Suspicious...");
255130812Smarcel	      }
256130812Smarcel	}
257130812Smarcel
258130812Smarcel#define fill(state, regno)                                               \
259130812Smarcel  memcpy (REG_ADDR(state, regno), &deprecated_registers[DEPRECATED_REGISTER_BYTE (regno)],     \
260130812Smarcel          DEPRECATED_REGISTER_RAW_SIZE (regno))
261130812Smarcel
262130812Smarcel      if (regno == -1)
263130812Smarcel	{
264130812Smarcel	  int i;
265130812Smarcel
266130812Smarcel	  proc_debug (thread, "storing all registers");
267130812Smarcel
268130812Smarcel	  for (i = 0; i < I386_NUM_GREGS; i++)
269130812Smarcel	    if (deprecated_register_valid[i])
270130812Smarcel	      fill (state, i);
271130812Smarcel	}
272130812Smarcel      else
273130812Smarcel	{
274130812Smarcel	  proc_debug (thread, "storing register %s", REGISTER_NAME (regno));
275130812Smarcel
276130812Smarcel	  gdb_assert (deprecated_register_valid[regno]);
277130812Smarcel	  fill (state, regno);
278130812Smarcel	}
279130812Smarcel
280130812Smarcel      /* Restore the T bit.  */
281130812Smarcel      ((struct i386_thread_state *)state)->efl &= ~0x100;
282130812Smarcel      ((struct i386_thread_state *)state)->efl |= trace;
283130812Smarcel    }
284130812Smarcel
285130812Smarcel#undef fill
286130812Smarcel
287130812Smarcel  if (regno >= I386_NUM_GREGS || regno == -1)
288130812Smarcel    {
289130812Smarcel      proc_debug (thread, "storing floating-point registers");
290130812Smarcel
291130812Smarcel      store_fpregs (thread, regno);
292130812Smarcel    }
293130812Smarcel}
294