xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/m68k-linux-nat.c (revision 6881a4007f077b54e5f51159c52b9b25f57deb0d)
1699b0f92Schristos /* Motorola m68k native support for GNU/Linux.
2699b0f92Schristos 
3*6881a400Schristos    Copyright (C) 1996-2023 Free Software Foundation, Inc.
4699b0f92Schristos 
5699b0f92Schristos    This file is part of GDB.
6699b0f92Schristos 
7699b0f92Schristos    This program is free software; you can redistribute it and/or modify
8699b0f92Schristos    it under the terms of the GNU General Public License as published by
9699b0f92Schristos    the Free Software Foundation; either version 3 of the License, or
10699b0f92Schristos    (at your option) any later version.
11699b0f92Schristos 
12699b0f92Schristos    This program is distributed in the hope that it will be useful,
13699b0f92Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
14699b0f92Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15699b0f92Schristos    GNU General Public License for more details.
16699b0f92Schristos 
17699b0f92Schristos    You should have received a copy of the GNU General Public License
18699b0f92Schristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19699b0f92Schristos 
20699b0f92Schristos #include "defs.h"
21699b0f92Schristos #include "frame.h"
22699b0f92Schristos #include "inferior.h"
23699b0f92Schristos #include "language.h"
24699b0f92Schristos #include "gdbcore.h"
25699b0f92Schristos #include "regcache.h"
26699b0f92Schristos #include "target.h"
27699b0f92Schristos #include "linux-nat.h"
287d62b00eSchristos #include "gdbarch.h"
29699b0f92Schristos 
30699b0f92Schristos #include "m68k-tdep.h"
31699b0f92Schristos 
32699b0f92Schristos #include <sys/dir.h>
33699b0f92Schristos #include <signal.h>
34699b0f92Schristos #include "nat/gdb_ptrace.h"
35699b0f92Schristos #include <sys/user.h>
36699b0f92Schristos #include <sys/ioctl.h>
37699b0f92Schristos #include <fcntl.h>
38699b0f92Schristos #include <sys/procfs.h>
39699b0f92Schristos 
40699b0f92Schristos #ifdef HAVE_SYS_REG_H
41699b0f92Schristos #include <sys/reg.h>
42699b0f92Schristos #endif
43699b0f92Schristos 
44699b0f92Schristos #include <sys/file.h>
45699b0f92Schristos #include <sys/stat.h>
46699b0f92Schristos 
47699b0f92Schristos #include "floatformat.h"
48699b0f92Schristos 
49699b0f92Schristos /* Prototypes for supply_gregset etc.  */
50699b0f92Schristos #include "gregset.h"
51699b0f92Schristos 
52699b0f92Schristos /* Defines ps_err_e, struct ps_prochandle.  */
53699b0f92Schristos #include "gdb_proc_service.h"
54699b0f92Schristos 
55699b0f92Schristos #include "inf-ptrace.h"
56699b0f92Schristos 
57699b0f92Schristos #ifndef PTRACE_GET_THREAD_AREA
58699b0f92Schristos #define PTRACE_GET_THREAD_AREA 25
59699b0f92Schristos #endif
60699b0f92Schristos 
617f2ac410Schristos 
627f2ac410Schristos class m68k_linux_nat_target final : public linux_nat_target
637f2ac410Schristos {
647f2ac410Schristos public:
657f2ac410Schristos   /* Add our register access methods.  */
667f2ac410Schristos   void fetch_registers (struct regcache *, int) override;
677f2ac410Schristos   void store_registers (struct regcache *, int) override;
687f2ac410Schristos };
697f2ac410Schristos 
707f2ac410Schristos static m68k_linux_nat_target the_m68k_linux_nat_target;
717f2ac410Schristos 
72699b0f92Schristos /* This table must line up with gdbarch_register_name in "m68k-tdep.c".  */
73699b0f92Schristos static const int regmap[] =
74699b0f92Schristos {
75699b0f92Schristos   PT_D0, PT_D1, PT_D2, PT_D3, PT_D4, PT_D5, PT_D6, PT_D7,
76699b0f92Schristos   PT_A0, PT_A1, PT_A2, PT_A3, PT_A4, PT_A5, PT_A6, PT_USP,
77699b0f92Schristos   PT_SR, PT_PC,
78699b0f92Schristos   /* PT_FP0, ..., PT_FP7 */
79699b0f92Schristos   21, 24, 27, 30, 33, 36, 39, 42,
80699b0f92Schristos   /* PT_FPCR, PT_FPSR, PT_FPIAR */
81699b0f92Schristos   45, 46, 47
82699b0f92Schristos };
83699b0f92Schristos 
84699b0f92Schristos /* Which ptrace request retrieves which registers?
85699b0f92Schristos    These apply to the corresponding SET requests as well.  */
86699b0f92Schristos #define NUM_GREGS (18)
87699b0f92Schristos #define MAX_NUM_REGS (NUM_GREGS + 11)
88699b0f92Schristos 
89699b0f92Schristos static int
90699b0f92Schristos getregs_supplies (int regno)
91699b0f92Schristos {
92699b0f92Schristos   return 0 <= regno && regno < NUM_GREGS;
93699b0f92Schristos }
94699b0f92Schristos 
95699b0f92Schristos static int
96699b0f92Schristos getfpregs_supplies (int regno)
97699b0f92Schristos {
98699b0f92Schristos   return M68K_FP0_REGNUM <= regno && regno <= M68K_FPI_REGNUM;
99699b0f92Schristos }
100699b0f92Schristos 
101699b0f92Schristos /* Does the current host support the GETREGS request?  */
102699b0f92Schristos static int have_ptrace_getregs =
103699b0f92Schristos #ifdef HAVE_PTRACE_GETREGS
104699b0f92Schristos   1
105699b0f92Schristos #else
106699b0f92Schristos   0
107699b0f92Schristos #endif
108699b0f92Schristos ;
109699b0f92Schristos 
110699b0f92Schristos 
111699b0f92Schristos 
112699b0f92Schristos /* Fetching registers directly from the U area, one at a time.  */
113699b0f92Schristos 
114699b0f92Schristos /* Fetch one register.  */
115699b0f92Schristos 
116699b0f92Schristos static void
117699b0f92Schristos fetch_register (struct regcache *regcache, int regno)
118699b0f92Schristos {
1197f2ac410Schristos   struct gdbarch *gdbarch = regcache->arch ();
120699b0f92Schristos   long regaddr, val;
121699b0f92Schristos   int i;
122699b0f92Schristos   gdb_byte buf[M68K_MAX_REGISTER_SIZE];
1237f2ac410Schristos   pid_t tid = get_ptrace_pid (regcache->ptid ());
124699b0f92Schristos 
125699b0f92Schristos   regaddr = 4 * regmap[regno];
126699b0f92Schristos   for (i = 0; i < register_size (gdbarch, regno); i += sizeof (long))
127699b0f92Schristos     {
128699b0f92Schristos       errno = 0;
129699b0f92Schristos       val = ptrace (PTRACE_PEEKUSER, tid, regaddr, 0);
130699b0f92Schristos       memcpy (&buf[i], &val, sizeof (long));
131699b0f92Schristos       regaddr += sizeof (long);
132699b0f92Schristos       if (errno != 0)
133699b0f92Schristos 	error (_("Couldn't read register %s (#%d): %s."),
134699b0f92Schristos 	       gdbarch_register_name (gdbarch, regno),
135699b0f92Schristos 	       regno, safe_strerror (errno));
136699b0f92Schristos     }
1377f2ac410Schristos   regcache->raw_supply (regno, buf);
138699b0f92Schristos }
139699b0f92Schristos 
140699b0f92Schristos /* Fetch register values from the inferior.
141699b0f92Schristos    If REGNO is negative, do this for all registers.
142699b0f92Schristos    Otherwise, REGNO specifies which register (so we can save time).  */
143699b0f92Schristos 
144699b0f92Schristos static void
145699b0f92Schristos old_fetch_inferior_registers (struct regcache *regcache, int regno)
146699b0f92Schristos {
147699b0f92Schristos   if (regno >= 0)
148699b0f92Schristos     {
149699b0f92Schristos       fetch_register (regcache, regno);
150699b0f92Schristos     }
151699b0f92Schristos   else
152699b0f92Schristos     {
153699b0f92Schristos       for (regno = 0;
1547f2ac410Schristos 	   regno < gdbarch_num_regs (regcache->arch ());
155699b0f92Schristos 	   regno++)
156699b0f92Schristos 	{
157699b0f92Schristos 	  fetch_register (regcache, regno);
158699b0f92Schristos 	}
159699b0f92Schristos     }
160699b0f92Schristos }
161699b0f92Schristos 
162699b0f92Schristos /* Store one register.  */
163699b0f92Schristos 
164699b0f92Schristos static void
165699b0f92Schristos store_register (const struct regcache *regcache, int regno)
166699b0f92Schristos {
1677f2ac410Schristos   struct gdbarch *gdbarch = regcache->arch ();
168699b0f92Schristos   long regaddr, val;
169699b0f92Schristos   int i;
170699b0f92Schristos   gdb_byte buf[M68K_MAX_REGISTER_SIZE];
1717f2ac410Schristos   pid_t tid = get_ptrace_pid (regcache->ptid ());
172699b0f92Schristos 
173699b0f92Schristos   regaddr = 4 * regmap[regno];
174699b0f92Schristos 
175699b0f92Schristos   /* Put the contents of regno into a local buffer.  */
1767f2ac410Schristos   regcache->raw_collect (regno, buf);
177699b0f92Schristos 
178699b0f92Schristos   /* Store the local buffer into the inferior a chunk at the time.  */
179699b0f92Schristos   for (i = 0; i < register_size (gdbarch, regno); i += sizeof (long))
180699b0f92Schristos     {
181699b0f92Schristos       errno = 0;
182699b0f92Schristos       memcpy (&val, &buf[i], sizeof (long));
183699b0f92Schristos       ptrace (PTRACE_POKEUSER, tid, regaddr, val);
184699b0f92Schristos       regaddr += sizeof (long);
185699b0f92Schristos       if (errno != 0)
186699b0f92Schristos 	error (_("Couldn't write register %s (#%d): %s."),
187699b0f92Schristos 	       gdbarch_register_name (gdbarch, regno),
188699b0f92Schristos 	       regno, safe_strerror (errno));
189699b0f92Schristos     }
190699b0f92Schristos }
191699b0f92Schristos 
192699b0f92Schristos /* Store our register values back into the inferior.
193699b0f92Schristos    If REGNO is negative, do this for all registers.
194699b0f92Schristos    Otherwise, REGNO specifies which register (so we can save time).  */
195699b0f92Schristos 
196699b0f92Schristos static void
197699b0f92Schristos old_store_inferior_registers (const struct regcache *regcache, int regno)
198699b0f92Schristos {
199699b0f92Schristos   if (regno >= 0)
200699b0f92Schristos     {
201699b0f92Schristos       store_register (regcache, regno);
202699b0f92Schristos     }
203699b0f92Schristos   else
204699b0f92Schristos     {
205699b0f92Schristos       for (regno = 0;
2067f2ac410Schristos 	   regno < gdbarch_num_regs (regcache->arch ());
207699b0f92Schristos 	   regno++)
208699b0f92Schristos 	{
209699b0f92Schristos 	  store_register (regcache, regno);
210699b0f92Schristos 	}
211699b0f92Schristos     }
212699b0f92Schristos }
213699b0f92Schristos 
214699b0f92Schristos /*  Given a pointer to a general register set in /proc format
215699b0f92Schristos    (elf_gregset_t *), unpack the register contents and supply
216699b0f92Schristos    them as gdb's idea of the current register values.  */
217699b0f92Schristos 
218699b0f92Schristos void
219699b0f92Schristos supply_gregset (struct regcache *regcache, const elf_gregset_t *gregsetp)
220699b0f92Schristos {
2217f2ac410Schristos   struct gdbarch *gdbarch = regcache->arch ();
222699b0f92Schristos   const elf_greg_t *regp = (const elf_greg_t *) gregsetp;
223699b0f92Schristos   int regi;
224699b0f92Schristos 
225699b0f92Schristos   for (regi = M68K_D0_REGNUM;
226699b0f92Schristos        regi <= gdbarch_sp_regnum (gdbarch);
227699b0f92Schristos        regi++)
2287f2ac410Schristos     regcache->raw_supply (regi, &regp[regmap[regi]]);
2297f2ac410Schristos   regcache->raw_supply (gdbarch_ps_regnum (gdbarch), &regp[PT_SR]);
2307f2ac410Schristos   regcache->raw_supply (gdbarch_pc_regnum (gdbarch), &regp[PT_PC]);
231699b0f92Schristos }
232699b0f92Schristos 
233699b0f92Schristos /* Fill register REGNO (if it is a general-purpose register) in
234699b0f92Schristos    *GREGSETPS with the value in GDB's register array.  If REGNO is -1,
235699b0f92Schristos    do this for all registers.  */
236699b0f92Schristos void
237699b0f92Schristos fill_gregset (const struct regcache *regcache,
238699b0f92Schristos 	      elf_gregset_t *gregsetp, int regno)
239699b0f92Schristos {
240699b0f92Schristos   elf_greg_t *regp = (elf_greg_t *) gregsetp;
241699b0f92Schristos   int i;
242699b0f92Schristos 
243699b0f92Schristos   for (i = 0; i < NUM_GREGS; i++)
244699b0f92Schristos     if (regno == -1 || regno == i)
2457f2ac410Schristos       regcache->raw_collect (i, regp + regmap[i]);
246699b0f92Schristos }
247699b0f92Schristos 
248699b0f92Schristos #ifdef HAVE_PTRACE_GETREGS
249699b0f92Schristos 
250699b0f92Schristos /* Fetch all general-purpose registers from process/thread TID and
251699b0f92Schristos    store their values in GDB's register array.  */
252699b0f92Schristos 
253699b0f92Schristos static void
254699b0f92Schristos fetch_regs (struct regcache *regcache, int tid)
255699b0f92Schristos {
256699b0f92Schristos   elf_gregset_t regs;
257699b0f92Schristos 
258699b0f92Schristos   if (ptrace (PTRACE_GETREGS, tid, 0, (int) &regs) < 0)
259699b0f92Schristos     {
260699b0f92Schristos       if (errno == EIO)
261699b0f92Schristos 	{
262699b0f92Schristos 	  /* The kernel we're running on doesn't support the GETREGS
263699b0f92Schristos 	     request.  Reset `have_ptrace_getregs'.  */
264699b0f92Schristos 	  have_ptrace_getregs = 0;
265699b0f92Schristos 	  return;
266699b0f92Schristos 	}
267699b0f92Schristos 
268699b0f92Schristos       perror_with_name (_("Couldn't get registers"));
269699b0f92Schristos     }
270699b0f92Schristos 
271699b0f92Schristos   supply_gregset (regcache, (const elf_gregset_t *) &regs);
272699b0f92Schristos }
273699b0f92Schristos 
274699b0f92Schristos /* Store all valid general-purpose registers in GDB's register array
275699b0f92Schristos    into the process/thread specified by TID.  */
276699b0f92Schristos 
277699b0f92Schristos static void
278699b0f92Schristos store_regs (const struct regcache *regcache, int tid, int regno)
279699b0f92Schristos {
280699b0f92Schristos   elf_gregset_t regs;
281699b0f92Schristos 
282699b0f92Schristos   if (ptrace (PTRACE_GETREGS, tid, 0, (int) &regs) < 0)
283699b0f92Schristos     perror_with_name (_("Couldn't get registers"));
284699b0f92Schristos 
285699b0f92Schristos   fill_gregset (regcache, &regs, regno);
286699b0f92Schristos 
287699b0f92Schristos   if (ptrace (PTRACE_SETREGS, tid, 0, (int) &regs) < 0)
288699b0f92Schristos     perror_with_name (_("Couldn't write registers"));
289699b0f92Schristos }
290699b0f92Schristos 
291699b0f92Schristos #else
292699b0f92Schristos 
293699b0f92Schristos static void fetch_regs (struct regcache *regcache, int tid)
294699b0f92Schristos {
295699b0f92Schristos }
296699b0f92Schristos 
297699b0f92Schristos static void store_regs (const struct regcache *regcache, int tid, int regno)
298699b0f92Schristos {
299699b0f92Schristos }
300699b0f92Schristos 
301699b0f92Schristos #endif
302699b0f92Schristos 
303699b0f92Schristos 
304699b0f92Schristos /* Transfering floating-point registers between GDB, inferiors and cores.  */
305699b0f92Schristos 
306699b0f92Schristos /* What is the address of fpN within the floating-point register set F?  */
307699b0f92Schristos #define FPREG_ADDR(f, n) (&(f)->fpregs[(n) * 3])
308699b0f92Schristos 
309699b0f92Schristos /* Fill GDB's register array with the floating-point register values in
310699b0f92Schristos    *FPREGSETP.  */
311699b0f92Schristos 
312699b0f92Schristos void
313699b0f92Schristos supply_fpregset (struct regcache *regcache, const elf_fpregset_t *fpregsetp)
314699b0f92Schristos {
3157f2ac410Schristos   struct gdbarch *gdbarch = regcache->arch ();
316699b0f92Schristos   int regi;
317699b0f92Schristos 
318699b0f92Schristos   for (regi = gdbarch_fp0_regnum (gdbarch);
319699b0f92Schristos        regi < gdbarch_fp0_regnum (gdbarch) + 8; regi++)
3207f2ac410Schristos     regcache->raw_supply
3217f2ac410Schristos       (regi, FPREG_ADDR (fpregsetp, regi - gdbarch_fp0_regnum (gdbarch)));
3227f2ac410Schristos   regcache->raw_supply (M68K_FPC_REGNUM, &fpregsetp->fpcntl[0]);
3237f2ac410Schristos   regcache->raw_supply (M68K_FPS_REGNUM, &fpregsetp->fpcntl[1]);
3247f2ac410Schristos   regcache->raw_supply (M68K_FPI_REGNUM, &fpregsetp->fpcntl[2]);
325699b0f92Schristos }
326699b0f92Schristos 
327699b0f92Schristos /* Fill register REGNO (if it is a floating-point register) in
328699b0f92Schristos    *FPREGSETP with the value in GDB's register array.  If REGNO is -1,
329699b0f92Schristos    do this for all registers.  */
330699b0f92Schristos 
331699b0f92Schristos void
332699b0f92Schristos fill_fpregset (const struct regcache *regcache,
333699b0f92Schristos 	       elf_fpregset_t *fpregsetp, int regno)
334699b0f92Schristos {
3357f2ac410Schristos   struct gdbarch *gdbarch = regcache->arch ();
336699b0f92Schristos   int i;
337699b0f92Schristos 
338699b0f92Schristos   /* Fill in the floating-point registers.  */
339699b0f92Schristos   for (i = gdbarch_fp0_regnum (gdbarch);
340699b0f92Schristos        i < gdbarch_fp0_regnum (gdbarch) + 8; i++)
341699b0f92Schristos     if (regno == -1 || regno == i)
3427f2ac410Schristos       regcache->raw_collect
3437f2ac410Schristos 	(i, FPREG_ADDR (fpregsetp, i - gdbarch_fp0_regnum (gdbarch)));
344699b0f92Schristos 
345699b0f92Schristos   /* Fill in the floating-point control registers.  */
346699b0f92Schristos   for (i = M68K_FPC_REGNUM; i <= M68K_FPI_REGNUM; i++)
347699b0f92Schristos     if (regno == -1 || regno == i)
3487f2ac410Schristos       regcache->raw_collect (i, &fpregsetp->fpcntl[i - M68K_FPC_REGNUM]);
349699b0f92Schristos }
350699b0f92Schristos 
351699b0f92Schristos #ifdef HAVE_PTRACE_GETREGS
352699b0f92Schristos 
353699b0f92Schristos /* Fetch all floating-point registers from process/thread TID and store
354699b0f92Schristos    thier values in GDB's register array.  */
355699b0f92Schristos 
356699b0f92Schristos static void
357699b0f92Schristos fetch_fpregs (struct regcache *regcache, int tid)
358699b0f92Schristos {
359699b0f92Schristos   elf_fpregset_t fpregs;
360699b0f92Schristos 
361699b0f92Schristos   if (ptrace (PTRACE_GETFPREGS, tid, 0, (int) &fpregs) < 0)
362699b0f92Schristos     perror_with_name (_("Couldn't get floating point status"));
363699b0f92Schristos 
364699b0f92Schristos   supply_fpregset (regcache, (const elf_fpregset_t *) &fpregs);
365699b0f92Schristos }
366699b0f92Schristos 
367699b0f92Schristos /* Store all valid floating-point registers in GDB's register array
368699b0f92Schristos    into the process/thread specified by TID.  */
369699b0f92Schristos 
370699b0f92Schristos static void
371699b0f92Schristos store_fpregs (const struct regcache *regcache, int tid, int regno)
372699b0f92Schristos {
373699b0f92Schristos   elf_fpregset_t fpregs;
374699b0f92Schristos 
375699b0f92Schristos   if (ptrace (PTRACE_GETFPREGS, tid, 0, (int) &fpregs) < 0)
376699b0f92Schristos     perror_with_name (_("Couldn't get floating point status"));
377699b0f92Schristos 
378699b0f92Schristos   fill_fpregset (regcache, &fpregs, regno);
379699b0f92Schristos 
380699b0f92Schristos   if (ptrace (PTRACE_SETFPREGS, tid, 0, (int) &fpregs) < 0)
381699b0f92Schristos     perror_with_name (_("Couldn't write floating point status"));
382699b0f92Schristos }
383699b0f92Schristos 
384699b0f92Schristos #else
385699b0f92Schristos 
386699b0f92Schristos static void fetch_fpregs (struct regcache *regcache, int tid)
387699b0f92Schristos {
388699b0f92Schristos }
389699b0f92Schristos 
390699b0f92Schristos static void store_fpregs (const struct regcache *regcache, int tid, int regno)
391699b0f92Schristos {
392699b0f92Schristos }
393699b0f92Schristos 
394699b0f92Schristos #endif
395699b0f92Schristos 
396699b0f92Schristos /* Transferring arbitrary registers between GDB and inferior.  */
397699b0f92Schristos 
398699b0f92Schristos /* Fetch register REGNO from the child process.  If REGNO is -1, do
399699b0f92Schristos    this for all registers (including the floating point and SSE
400699b0f92Schristos    registers).  */
401699b0f92Schristos 
4027f2ac410Schristos void
4037f2ac410Schristos m68k_linux_nat_target::fetch_registers (struct regcache *regcache, int regno)
404699b0f92Schristos {
405699b0f92Schristos   pid_t tid;
406699b0f92Schristos 
407699b0f92Schristos   /* Use the old method of peeking around in `struct user' if the
408699b0f92Schristos      GETREGS request isn't available.  */
409699b0f92Schristos   if (! have_ptrace_getregs)
410699b0f92Schristos     {
411699b0f92Schristos       old_fetch_inferior_registers (regcache, regno);
412699b0f92Schristos       return;
413699b0f92Schristos     }
414699b0f92Schristos 
4157f2ac410Schristos   tid = get_ptrace_pid (regcache->ptid ());
416699b0f92Schristos 
417699b0f92Schristos   /* Use the PTRACE_GETFPXREGS request whenever possible, since it
418699b0f92Schristos      transfers more registers in one system call, and we'll cache the
419699b0f92Schristos      results.  But remember that fetch_fpxregs can fail, and return
420699b0f92Schristos      zero.  */
421699b0f92Schristos   if (regno == -1)
422699b0f92Schristos     {
423699b0f92Schristos       fetch_regs (regcache, tid);
424699b0f92Schristos 
425699b0f92Schristos       /* The call above might reset `have_ptrace_getregs'.  */
426699b0f92Schristos       if (! have_ptrace_getregs)
427699b0f92Schristos 	{
428699b0f92Schristos 	  old_fetch_inferior_registers (regcache, -1);
429699b0f92Schristos 	  return;
430699b0f92Schristos 	}
431699b0f92Schristos 
432699b0f92Schristos       fetch_fpregs (regcache, tid);
433699b0f92Schristos       return;
434699b0f92Schristos     }
435699b0f92Schristos 
436699b0f92Schristos   if (getregs_supplies (regno))
437699b0f92Schristos     {
438699b0f92Schristos       fetch_regs (regcache, tid);
439699b0f92Schristos       return;
440699b0f92Schristos     }
441699b0f92Schristos 
442699b0f92Schristos   if (getfpregs_supplies (regno))
443699b0f92Schristos     {
444699b0f92Schristos       fetch_fpregs (regcache, tid);
445699b0f92Schristos       return;
446699b0f92Schristos     }
447699b0f92Schristos 
448*6881a400Schristos   internal_error (_("Got request for bad register number %d."), regno);
449699b0f92Schristos }
450699b0f92Schristos 
451699b0f92Schristos /* Store register REGNO back into the child process.  If REGNO is -1,
452699b0f92Schristos    do this for all registers (including the floating point and SSE
453699b0f92Schristos    registers).  */
4547f2ac410Schristos void
4557f2ac410Schristos m68k_linux_nat_target::store_registers (struct regcache *regcache, int regno)
456699b0f92Schristos {
457699b0f92Schristos   pid_t tid;
458699b0f92Schristos 
459699b0f92Schristos   /* Use the old method of poking around in `struct user' if the
460699b0f92Schristos      SETREGS request isn't available.  */
461699b0f92Schristos   if (! have_ptrace_getregs)
462699b0f92Schristos     {
463699b0f92Schristos       old_store_inferior_registers (regcache, regno);
464699b0f92Schristos       return;
465699b0f92Schristos     }
466699b0f92Schristos 
4677f2ac410Schristos   tid = get_ptrace_pid (regcache->ptid ());
468699b0f92Schristos 
469699b0f92Schristos   /* Use the PTRACE_SETFPREGS requests whenever possible, since it
470699b0f92Schristos      transfers more registers in one system call.  But remember that
471699b0f92Schristos      store_fpregs can fail, and return zero.  */
472699b0f92Schristos   if (regno == -1)
473699b0f92Schristos     {
474699b0f92Schristos       store_regs (regcache, tid, regno);
475699b0f92Schristos       store_fpregs (regcache, tid, regno);
476699b0f92Schristos       return;
477699b0f92Schristos     }
478699b0f92Schristos 
479699b0f92Schristos   if (getregs_supplies (regno))
480699b0f92Schristos     {
481699b0f92Schristos       store_regs (regcache, tid, regno);
482699b0f92Schristos       return;
483699b0f92Schristos     }
484699b0f92Schristos 
485699b0f92Schristos   if (getfpregs_supplies (regno))
486699b0f92Schristos     {
487699b0f92Schristos       store_fpregs (regcache, tid, regno);
488699b0f92Schristos       return;
489699b0f92Schristos     }
490699b0f92Schristos 
491*6881a400Schristos   internal_error (_("Got request to store bad register number %d."), regno);
492699b0f92Schristos }
493699b0f92Schristos 
494699b0f92Schristos 
495699b0f92Schristos /* Fetch the thread-local storage pointer for libthread_db.  */
496699b0f92Schristos 
497699b0f92Schristos ps_err_e
498699b0f92Schristos ps_get_thread_area (struct ps_prochandle *ph,
499699b0f92Schristos 		    lwpid_t lwpid, int idx, void **base)
500699b0f92Schristos {
501699b0f92Schristos   if (ptrace (PTRACE_GET_THREAD_AREA, lwpid, NULL, base) < 0)
502699b0f92Schristos     return PS_ERR;
503699b0f92Schristos 
504699b0f92Schristos   /* IDX is the bias from the thread pointer to the beginning of the
505699b0f92Schristos      thread descriptor.  It has to be subtracted due to implementation
506699b0f92Schristos      quirks in libthread_db.  */
507699b0f92Schristos   *base = (char *) *base - idx;
508699b0f92Schristos 
509699b0f92Schristos   return PS_OK;
510699b0f92Schristos }
511699b0f92Schristos 
5127d62b00eSchristos void _initialize_m68k_linux_nat ();
513699b0f92Schristos void
5147d62b00eSchristos _initialize_m68k_linux_nat ()
515699b0f92Schristos {
516699b0f92Schristos   /* Register the target.  */
5177f2ac410Schristos   linux_target = &the_m68k_linux_nat_target;
5187f2ac410Schristos   add_inf_child_target (&the_m68k_linux_nat_target);
519699b0f92Schristos }
520