xref: /netbsd-src/external/gpl3/gdb/dist/gdbserver/linux-mips-low.cc (revision 64f917f5a88990e32dd65fcd4348042fa7f852b9)
18dffb485Schristos /* GNU/Linux/MIPS specific low level interface, for the remote server for GDB.
2*64f917f5Schristos    Copyright (C) 1995-2024 Free Software Foundation, Inc.
38dffb485Schristos 
48dffb485Schristos    This file is part of GDB.
58dffb485Schristos 
68dffb485Schristos    This program is free software; you can redistribute it and/or modify
78dffb485Schristos    it under the terms of the GNU General Public License as published by
88dffb485Schristos    the Free Software Foundation; either version 3 of the License, or
98dffb485Schristos    (at your option) any later version.
108dffb485Schristos 
118dffb485Schristos    This program is distributed in the hope that it will be useful,
128dffb485Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
138dffb485Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
148dffb485Schristos    GNU General Public License for more details.
158dffb485Schristos 
168dffb485Schristos    You should have received a copy of the GNU General Public License
178dffb485Schristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
188dffb485Schristos 
198dffb485Schristos #include "linux-low.h"
208dffb485Schristos 
218dffb485Schristos #include "nat/gdb_ptrace.h"
228dffb485Schristos #include <endian.h>
238dffb485Schristos 
248dffb485Schristos #include "nat/mips-linux-watch.h"
258dffb485Schristos #include "gdb_proc_service.h"
268dffb485Schristos 
278dffb485Schristos /* Linux target op definitions for the MIPS architecture.  */
288dffb485Schristos 
298dffb485Schristos class mips_target : public linux_process_target
308dffb485Schristos {
318dffb485Schristos public:
328dffb485Schristos 
338dffb485Schristos   const regs_info *get_regs_info () override;
348dffb485Schristos 
358dffb485Schristos   const gdb_byte *sw_breakpoint_from_kind (int kind, int *size) override;
368dffb485Schristos 
378dffb485Schristos   bool supports_z_point_type (char z_type) override;
388dffb485Schristos 
398dffb485Schristos protected:
408dffb485Schristos 
418dffb485Schristos   void low_arch_setup () override;
428dffb485Schristos 
438dffb485Schristos   bool low_cannot_fetch_register (int regno) override;
448dffb485Schristos 
458dffb485Schristos   bool low_cannot_store_register (int regno) override;
468dffb485Schristos 
478dffb485Schristos   bool low_fetch_register (regcache *regcache, int regno) override;
488dffb485Schristos 
498dffb485Schristos   bool low_supports_breakpoints () override;
508dffb485Schristos 
518dffb485Schristos   CORE_ADDR low_get_pc (regcache *regcache) override;
528dffb485Schristos 
538dffb485Schristos   void low_set_pc (regcache *regcache, CORE_ADDR newpc) override;
548dffb485Schristos 
558dffb485Schristos   bool low_breakpoint_at (CORE_ADDR pc) override;
568dffb485Schristos 
578dffb485Schristos   int low_insert_point (raw_bkpt_type type, CORE_ADDR addr,
588dffb485Schristos 			int size, raw_breakpoint *bp) override;
598dffb485Schristos 
608dffb485Schristos   int low_remove_point (raw_bkpt_type type, CORE_ADDR addr,
618dffb485Schristos 			int size, raw_breakpoint *bp) override;
628dffb485Schristos 
638dffb485Schristos   bool low_stopped_by_watchpoint () override;
648dffb485Schristos 
658dffb485Schristos   CORE_ADDR low_stopped_data_address () override;
668dffb485Schristos 
678dffb485Schristos   void low_collect_ptrace_register (regcache *regcache, int regno,
688dffb485Schristos 				    char *buf) override;
698dffb485Schristos 
708dffb485Schristos   void low_supply_ptrace_register (regcache *regcache, int regno,
718dffb485Schristos 				   const char *buf) override;
728dffb485Schristos 
738dffb485Schristos   arch_process_info *low_new_process () override;
748dffb485Schristos 
758dffb485Schristos   void low_delete_process (arch_process_info *info) override;
768dffb485Schristos 
778dffb485Schristos   void low_new_thread (lwp_info *) override;
788dffb485Schristos 
798dffb485Schristos   void low_delete_thread (arch_lwp_info *) override;
808dffb485Schristos 
818dffb485Schristos   void low_new_fork (process_info *parent, process_info *child) override;
828dffb485Schristos 
838dffb485Schristos   void low_prepare_to_resume (lwp_info *lwp) override;
848dffb485Schristos };
858dffb485Schristos 
868dffb485Schristos /* The singleton target ops object.  */
878dffb485Schristos 
888dffb485Schristos static mips_target the_mips_target;
898dffb485Schristos 
908dffb485Schristos /* Defined in auto-generated file mips-linux.c.  */
918dffb485Schristos void init_registers_mips_linux (void);
928dffb485Schristos extern const struct target_desc *tdesc_mips_linux;
938dffb485Schristos 
948dffb485Schristos /* Defined in auto-generated file mips-dsp-linux.c.  */
958dffb485Schristos void init_registers_mips_dsp_linux (void);
968dffb485Schristos extern const struct target_desc *tdesc_mips_dsp_linux;
978dffb485Schristos 
988dffb485Schristos /* Defined in auto-generated file mips64-linux.c.  */
998dffb485Schristos void init_registers_mips64_linux (void);
1008dffb485Schristos extern const struct target_desc *tdesc_mips64_linux;
1018dffb485Schristos 
1028dffb485Schristos /* Defined in auto-generated file mips64-dsp-linux.c.  */
1038dffb485Schristos void init_registers_mips64_dsp_linux (void);
1048dffb485Schristos extern const struct target_desc *tdesc_mips64_dsp_linux;
1058dffb485Schristos 
1068dffb485Schristos #ifdef __mips64
1078dffb485Schristos #define tdesc_mips_linux tdesc_mips64_linux
1088dffb485Schristos #define tdesc_mips_dsp_linux tdesc_mips64_dsp_linux
1098dffb485Schristos #endif
1108dffb485Schristos 
1118dffb485Schristos #ifndef PTRACE_GET_THREAD_AREA
1128dffb485Schristos #define PTRACE_GET_THREAD_AREA 25
1138dffb485Schristos #endif
1148dffb485Schristos 
1158dffb485Schristos #ifdef HAVE_SYS_REG_H
1168dffb485Schristos #include <sys/reg.h>
1178dffb485Schristos #endif
1188dffb485Schristos 
1198dffb485Schristos #define mips_num_regs 73
1208dffb485Schristos #define mips_dsp_num_regs 80
1218dffb485Schristos 
1228dffb485Schristos #include <asm/ptrace.h>
1238dffb485Schristos 
1248dffb485Schristos #ifndef DSP_BASE
1258dffb485Schristos #define DSP_BASE 71
1268dffb485Schristos #define DSP_CONTROL 77
1278dffb485Schristos #endif
1288dffb485Schristos 
1298dffb485Schristos union mips_register
1308dffb485Schristos {
1318dffb485Schristos   unsigned char buf[8];
1328dffb485Schristos 
1338dffb485Schristos   /* Deliberately signed, for proper sign extension.  */
1348dffb485Schristos   int reg32;
1358dffb485Schristos   long long reg64;
1368dffb485Schristos };
1378dffb485Schristos 
1388dffb485Schristos /* Return the ptrace ``address'' of register REGNO. */
1398dffb485Schristos 
1408dffb485Schristos #define mips_base_regs							\
1418dffb485Schristos   -1,  1,  2,  3,  4,  5,  6,  7,					\
1428dffb485Schristos   8,  9,  10, 11, 12, 13, 14, 15,					\
1438dffb485Schristos   16, 17, 18, 19, 20, 21, 22, 23,					\
1448dffb485Schristos   24, 25, 26, 27, 28, 29, 30, 31,					\
1458dffb485Schristos 									\
1468dffb485Schristos   -1, MMLO, MMHI, BADVADDR, CAUSE, PC,					\
1478dffb485Schristos 									\
1488dffb485Schristos   FPR_BASE,      FPR_BASE + 1,  FPR_BASE + 2,  FPR_BASE + 3,		\
1498dffb485Schristos   FPR_BASE + 4,  FPR_BASE + 5,  FPR_BASE + 6,  FPR_BASE + 7,		\
1508dffb485Schristos   FPR_BASE + 8,  FPR_BASE + 9,  FPR_BASE + 10, FPR_BASE + 11,		\
1518dffb485Schristos   FPR_BASE + 12, FPR_BASE + 13, FPR_BASE + 14, FPR_BASE + 15,		\
1528dffb485Schristos   FPR_BASE + 16, FPR_BASE + 17, FPR_BASE + 18, FPR_BASE + 19,		\
1538dffb485Schristos   FPR_BASE + 20, FPR_BASE + 21, FPR_BASE + 22, FPR_BASE + 23,		\
1548dffb485Schristos   FPR_BASE + 24, FPR_BASE + 25, FPR_BASE + 26, FPR_BASE + 27,		\
1558dffb485Schristos   FPR_BASE + 28, FPR_BASE + 29, FPR_BASE + 30, FPR_BASE + 31,		\
1568dffb485Schristos   FPC_CSR, FPC_EIR
1578dffb485Schristos 
1588dffb485Schristos #define mips_dsp_regs							\
1598dffb485Schristos   DSP_BASE,      DSP_BASE + 1,  DSP_BASE + 2,  DSP_BASE + 3,		\
1608dffb485Schristos   DSP_BASE + 4,  DSP_BASE + 5,						\
1618dffb485Schristos   DSP_CONTROL
1628dffb485Schristos 
1638dffb485Schristos static int mips_regmap[mips_num_regs] = {
1648dffb485Schristos   mips_base_regs,
1658dffb485Schristos   0
1668dffb485Schristos };
1678dffb485Schristos 
1688dffb485Schristos static int mips_dsp_regmap[mips_dsp_num_regs] = {
1698dffb485Schristos   mips_base_regs,
1708dffb485Schristos   mips_dsp_regs,
1718dffb485Schristos   0
1728dffb485Schristos };
1738dffb485Schristos 
1748dffb485Schristos /* DSP registers are not in any regset and can only be accessed
1758dffb485Schristos    individually.  */
1768dffb485Schristos 
1778dffb485Schristos static unsigned char mips_dsp_regset_bitmap[(mips_dsp_num_regs + 7) / 8] = {
1788dffb485Schristos   0xfe, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x80
1798dffb485Schristos };
1808dffb485Schristos 
1818dffb485Schristos static int have_dsp = -1;
1828dffb485Schristos 
1838dffb485Schristos /* Try peeking at an arbitrarily chosen DSP register and pick the available
1848dffb485Schristos    user register set accordingly.  */
1858dffb485Schristos 
1868dffb485Schristos static const struct target_desc *
1878dffb485Schristos mips_read_description (void)
1888dffb485Schristos {
1898dffb485Schristos   if (have_dsp < 0)
1908dffb485Schristos     {
1918dffb485Schristos       int pid = lwpid_of (current_thread);
1928dffb485Schristos 
1938dffb485Schristos       errno = 0;
1948dffb485Schristos       ptrace (PTRACE_PEEKUSER, pid, DSP_CONTROL, 0);
1958dffb485Schristos       switch (errno)
1968dffb485Schristos 	{
1978dffb485Schristos 	case 0:
1988dffb485Schristos 	  have_dsp = 1;
1998dffb485Schristos 	  break;
2008dffb485Schristos 	case EIO:
2018dffb485Schristos 	  have_dsp = 0;
2028dffb485Schristos 	  break;
2038dffb485Schristos 	default:
2048dffb485Schristos 	  perror_with_name ("ptrace");
2058dffb485Schristos 	  break;
2068dffb485Schristos 	}
2078dffb485Schristos     }
2088dffb485Schristos 
2098dffb485Schristos   return have_dsp ? tdesc_mips_dsp_linux : tdesc_mips_linux;
2108dffb485Schristos }
2118dffb485Schristos 
2128dffb485Schristos void
2138dffb485Schristos mips_target::low_arch_setup ()
2148dffb485Schristos {
2158dffb485Schristos   current_process ()->tdesc = mips_read_description ();
2168dffb485Schristos }
2178dffb485Schristos 
2188dffb485Schristos /* Per-process arch-specific data we want to keep.  */
2198dffb485Schristos 
2208dffb485Schristos struct arch_process_info
2218dffb485Schristos {
2228dffb485Schristos   /* -1 if the kernel and/or CPU do not support watch registers.
2238dffb485Schristos       1 if watch_readback is valid and we can read style, num_valid
2248dffb485Schristos 	and the masks.
2258dffb485Schristos       0 if we need to read the watch_readback.  */
2268dffb485Schristos 
2278dffb485Schristos   int watch_readback_valid;
2288dffb485Schristos 
2298dffb485Schristos   /* Cached watch register read values.  */
2308dffb485Schristos 
2318dffb485Schristos   struct pt_watch_regs watch_readback;
2328dffb485Schristos 
2338dffb485Schristos   /* Current watchpoint requests for this process.  */
2348dffb485Schristos 
2358dffb485Schristos   struct mips_watchpoint *current_watches;
2368dffb485Schristos 
2378dffb485Schristos   /* The current set of watch register values for writing the
2388dffb485Schristos      registers.  */
2398dffb485Schristos 
2408dffb485Schristos   struct pt_watch_regs watch_mirror;
2418dffb485Schristos };
2428dffb485Schristos 
2438dffb485Schristos /* Per-thread arch-specific data we want to keep.  */
2448dffb485Schristos 
2458dffb485Schristos struct arch_lwp_info
2468dffb485Schristos {
2478dffb485Schristos   /* Non-zero if our copy differs from what's recorded in the thread.  */
2488dffb485Schristos   int watch_registers_changed;
2498dffb485Schristos };
2508dffb485Schristos 
2518dffb485Schristos /* From mips-linux-nat.c.  */
2528dffb485Schristos 
2538dffb485Schristos /* Pseudo registers can not be read.  ptrace does not provide a way to
2548dffb485Schristos    read (or set) PS_REGNUM, and there's no point in reading or setting
2558dffb485Schristos    ZERO_REGNUM, it's always 0.  We also can not set BADVADDR, CAUSE,
2568dffb485Schristos    or FCRIR via ptrace().  */
2578dffb485Schristos 
2588dffb485Schristos bool
2598dffb485Schristos mips_target::low_cannot_fetch_register (int regno)
2608dffb485Schristos {
2618dffb485Schristos   const struct target_desc *tdesc;
2628dffb485Schristos 
2638dffb485Schristos   if (get_regs_info ()->usrregs->regmap[regno] == -1)
2648dffb485Schristos     return true;
2658dffb485Schristos 
2668dffb485Schristos   tdesc = current_process ()->tdesc;
2678dffb485Schristos 
2688dffb485Schristos   /* On n32 we can't access 64-bit registers via PTRACE_PEEKUSR.  */
2698dffb485Schristos   if (register_size (tdesc, regno) > sizeof (PTRACE_XFER_TYPE))
2708dffb485Schristos     return true;
2718dffb485Schristos 
2728dffb485Schristos   if (find_regno (tdesc, "r0") == regno)
2738dffb485Schristos     return true;
2748dffb485Schristos 
2758dffb485Schristos   return false;
2768dffb485Schristos }
2778dffb485Schristos 
2788dffb485Schristos bool
2798dffb485Schristos mips_target::low_cannot_store_register (int regno)
2808dffb485Schristos {
2818dffb485Schristos   const struct target_desc *tdesc;
2828dffb485Schristos 
2838dffb485Schristos   if (get_regs_info ()->usrregs->regmap[regno] == -1)
2848dffb485Schristos     return true;
2858dffb485Schristos 
2868dffb485Schristos   tdesc = current_process ()->tdesc;
2878dffb485Schristos 
2888dffb485Schristos   /* On n32 we can't access 64-bit registers via PTRACE_POKEUSR.  */
2898dffb485Schristos   if (register_size (tdesc, regno) > sizeof (PTRACE_XFER_TYPE))
2908dffb485Schristos     return true;
2918dffb485Schristos 
2928dffb485Schristos   if (find_regno (tdesc, "r0") == regno)
2938dffb485Schristos     return true;
2948dffb485Schristos 
2958dffb485Schristos   if (find_regno (tdesc, "cause") == regno)
2968dffb485Schristos     return true;
2978dffb485Schristos 
2988dffb485Schristos   if (find_regno (tdesc, "badvaddr") == regno)
2998dffb485Schristos     return true;
3008dffb485Schristos 
3018dffb485Schristos   if (find_regno (tdesc, "fir") == regno)
3028dffb485Schristos     return true;
3038dffb485Schristos 
3048dffb485Schristos   return false;
3058dffb485Schristos }
3068dffb485Schristos 
3078dffb485Schristos bool
3088dffb485Schristos mips_target::low_fetch_register (regcache *regcache, int regno)
3098dffb485Schristos {
3108dffb485Schristos   const struct target_desc *tdesc = current_process ()->tdesc;
3118dffb485Schristos 
3128dffb485Schristos   if (find_regno (tdesc, "r0") == regno)
3138dffb485Schristos     {
3148dffb485Schristos       supply_register_zeroed (regcache, regno);
3158dffb485Schristos       return true;
3168dffb485Schristos     }
3178dffb485Schristos 
3188dffb485Schristos   return false;
3198dffb485Schristos }
3208dffb485Schristos 
3218dffb485Schristos bool
3228dffb485Schristos mips_target::low_supports_breakpoints ()
3238dffb485Schristos {
3248dffb485Schristos   return true;
3258dffb485Schristos }
3268dffb485Schristos 
3278dffb485Schristos CORE_ADDR
3288dffb485Schristos mips_target::low_get_pc (regcache *regcache)
3298dffb485Schristos {
3308dffb485Schristos   union mips_register pc;
3318dffb485Schristos   collect_register_by_name (regcache, "pc", pc.buf);
3328dffb485Schristos   return register_size (regcache->tdesc, 0) == 4 ? pc.reg32 : pc.reg64;
3338dffb485Schristos }
3348dffb485Schristos 
3358dffb485Schristos void
3368dffb485Schristos mips_target::low_set_pc (regcache *regcache, CORE_ADDR pc)
3378dffb485Schristos {
3388dffb485Schristos   union mips_register newpc;
3398dffb485Schristos   if (register_size (regcache->tdesc, 0) == 4)
3408dffb485Schristos     newpc.reg32 = pc;
3418dffb485Schristos   else
3428dffb485Schristos     newpc.reg64 = pc;
3438dffb485Schristos 
3448dffb485Schristos   supply_register_by_name (regcache, "pc", newpc.buf);
3458dffb485Schristos }
3468dffb485Schristos 
3478dffb485Schristos /* Correct in either endianness.  */
3488dffb485Schristos static const unsigned int mips_breakpoint = 0x0005000d;
3498dffb485Schristos #define mips_breakpoint_len 4
3508dffb485Schristos 
3518dffb485Schristos /* Implementation of target ops method "sw_breakpoint_from_kind".  */
3528dffb485Schristos 
3538dffb485Schristos const gdb_byte *
3548dffb485Schristos mips_target::sw_breakpoint_from_kind (int kind, int *size)
3558dffb485Schristos {
3568dffb485Schristos   *size = mips_breakpoint_len;
3578dffb485Schristos   return (const gdb_byte *) &mips_breakpoint;
3588dffb485Schristos }
3598dffb485Schristos 
3608dffb485Schristos bool
3618dffb485Schristos mips_target::low_breakpoint_at (CORE_ADDR where)
3628dffb485Schristos {
3638dffb485Schristos   unsigned int insn;
3648dffb485Schristos 
3658dffb485Schristos   read_memory (where, (unsigned char *) &insn, 4);
3668dffb485Schristos   if (insn == mips_breakpoint)
3678dffb485Schristos     return true;
3688dffb485Schristos 
3698dffb485Schristos   /* If necessary, recognize more trap instructions here.  GDB only uses the
3708dffb485Schristos      one.  */
3718dffb485Schristos   return false;
3728dffb485Schristos }
3738dffb485Schristos 
3748dffb485Schristos /* Mark the watch registers of lwp, represented by ENTRY, as changed.  */
3758dffb485Schristos 
3768dffb485Schristos static void
3778dffb485Schristos update_watch_registers_callback (thread_info *thread)
3788dffb485Schristos {
3798dffb485Schristos   struct lwp_info *lwp = get_thread_lwp (thread);
3808dffb485Schristos 
3818dffb485Schristos   /* The actual update is done later just before resuming the lwp,
3828dffb485Schristos      we just mark that the registers need updating.  */
3838dffb485Schristos   lwp->arch_private->watch_registers_changed = 1;
3848dffb485Schristos 
3858dffb485Schristos   /* If the lwp isn't stopped, force it to momentarily pause, so
3868dffb485Schristos      we can update its watch registers.  */
3878dffb485Schristos   if (!lwp->stopped)
3888dffb485Schristos     linux_stop_lwp (lwp);
3898dffb485Schristos }
3908dffb485Schristos 
3918dffb485Schristos /* This is the implementation of linux target ops method
3928dffb485Schristos    low_new_process.  */
3938dffb485Schristos 
3948dffb485Schristos arch_process_info *
3958dffb485Schristos mips_target::low_new_process ()
3968dffb485Schristos {
3978dffb485Schristos   struct arch_process_info *info = XCNEW (struct arch_process_info);
3988dffb485Schristos 
3998dffb485Schristos   return info;
4008dffb485Schristos }
4018dffb485Schristos 
4028dffb485Schristos /* This is the implementation of linux target ops method
4038dffb485Schristos    low_delete_process.  */
4048dffb485Schristos 
4058dffb485Schristos void
4068dffb485Schristos mips_target::low_delete_process (arch_process_info *info)
4078dffb485Schristos {
4088dffb485Schristos   xfree (info);
4098dffb485Schristos }
4108dffb485Schristos 
4118dffb485Schristos /* This is the implementation of linux target ops method low_new_thread.
4128dffb485Schristos    Mark the watch registers as changed, so the threads' copies will
4138dffb485Schristos    be updated.  */
4148dffb485Schristos 
4158dffb485Schristos void
4168dffb485Schristos mips_target::low_new_thread (lwp_info *lwp)
4178dffb485Schristos {
4188dffb485Schristos   struct arch_lwp_info *info = XCNEW (struct arch_lwp_info);
4198dffb485Schristos 
4208dffb485Schristos   info->watch_registers_changed = 1;
4218dffb485Schristos 
4228dffb485Schristos   lwp->arch_private = info;
4238dffb485Schristos }
4248dffb485Schristos 
4258dffb485Schristos /* Function to call when a thread is being deleted.  */
4268dffb485Schristos 
4278dffb485Schristos void
4288dffb485Schristos mips_target::low_delete_thread (arch_lwp_info *arch_lwp)
4298dffb485Schristos {
4308dffb485Schristos   xfree (arch_lwp);
4318dffb485Schristos }
4328dffb485Schristos 
4338dffb485Schristos /* Create a new mips_watchpoint and add it to the list.  */
4348dffb485Schristos 
4358dffb485Schristos static void
4368dffb485Schristos mips_add_watchpoint (struct arch_process_info *priv, CORE_ADDR addr, int len,
4378dffb485Schristos 		     enum target_hw_bp_type watch_type)
4388dffb485Schristos {
4398dffb485Schristos   struct mips_watchpoint *new_watch;
4408dffb485Schristos   struct mips_watchpoint **pw;
4418dffb485Schristos 
4428dffb485Schristos   new_watch = XNEW (struct mips_watchpoint);
4438dffb485Schristos   new_watch->addr = addr;
4448dffb485Schristos   new_watch->len = len;
4458dffb485Schristos   new_watch->type = watch_type;
4468dffb485Schristos   new_watch->next = NULL;
4478dffb485Schristos 
4488dffb485Schristos   pw = &priv->current_watches;
4498dffb485Schristos   while (*pw != NULL)
4508dffb485Schristos     pw = &(*pw)->next;
4518dffb485Schristos   *pw = new_watch;
4528dffb485Schristos }
4538dffb485Schristos 
4548dffb485Schristos /* Hook to call when a new fork is attached.  */
4558dffb485Schristos 
4568dffb485Schristos void
4578dffb485Schristos mips_target::low_new_fork (process_info *parent,
4588dffb485Schristos 			   process_info *child)
4598dffb485Schristos {
4608dffb485Schristos   struct arch_process_info *parent_private;
4618dffb485Schristos   struct arch_process_info *child_private;
4628dffb485Schristos   struct mips_watchpoint *wp;
4638dffb485Schristos 
4648dffb485Schristos   /* These are allocated by linux_add_process.  */
4658dffb485Schristos   gdb_assert (parent->priv != NULL
4668dffb485Schristos 	      && parent->priv->arch_private != NULL);
4678dffb485Schristos   gdb_assert (child->priv != NULL
4688dffb485Schristos 	      && child->priv->arch_private != NULL);
4698dffb485Schristos 
4708dffb485Schristos   /* Linux kernel before 2.6.33 commit
4718dffb485Schristos      72f674d203cd230426437cdcf7dd6f681dad8b0d
4728dffb485Schristos      will inherit hardware debug registers from parent
4738dffb485Schristos      on fork/vfork/clone.  Newer Linux kernels create such tasks with
4748dffb485Schristos      zeroed debug registers.
4758dffb485Schristos 
4768dffb485Schristos      GDB core assumes the child inherits the watchpoints/hw
4778dffb485Schristos      breakpoints of the parent, and will remove them all from the
4788dffb485Schristos      forked off process.  Copy the debug registers mirrors into the
4798dffb485Schristos      new process so that all breakpoints and watchpoints can be
4808dffb485Schristos      removed together.  The debug registers mirror will become zeroed
4818dffb485Schristos      in the end before detaching the forked off process, thus making
4828dffb485Schristos      this compatible with older Linux kernels too.  */
4838dffb485Schristos 
4848dffb485Schristos   parent_private = parent->priv->arch_private;
4858dffb485Schristos   child_private = child->priv->arch_private;
4868dffb485Schristos 
4878dffb485Schristos   child_private->watch_readback_valid = parent_private->watch_readback_valid;
4888dffb485Schristos   child_private->watch_readback = parent_private->watch_readback;
4898dffb485Schristos 
4908dffb485Schristos   for (wp = parent_private->current_watches; wp != NULL; wp = wp->next)
4918dffb485Schristos     mips_add_watchpoint (child_private, wp->addr, wp->len, wp->type);
4928dffb485Schristos 
4938dffb485Schristos   child_private->watch_mirror = parent_private->watch_mirror;
4948dffb485Schristos }
4958dffb485Schristos /* This is the implementation of linux target ops method
4968dffb485Schristos    low_prepare_to_resume.  If the watch regs have changed, update the
4978dffb485Schristos    thread's copies.  */
4988dffb485Schristos 
4998dffb485Schristos void
5008dffb485Schristos mips_target::low_prepare_to_resume (lwp_info *lwp)
5018dffb485Schristos {
5028dffb485Schristos   ptid_t ptid = ptid_of (get_lwp_thread (lwp));
5038dffb485Schristos   struct process_info *proc = find_process_pid (ptid.pid ());
5048dffb485Schristos   struct arch_process_info *priv = proc->priv->arch_private;
5058dffb485Schristos 
5068dffb485Schristos   if (lwp->arch_private->watch_registers_changed)
5078dffb485Schristos     {
5088dffb485Schristos       /* Only update the watch registers if we have set or unset a
5098dffb485Schristos 	 watchpoint already.  */
5108dffb485Schristos       if (mips_linux_watch_get_num_valid (&priv->watch_mirror) > 0)
5118dffb485Schristos 	{
5128dffb485Schristos 	  /* Write the mirrored watch register values.  */
5138dffb485Schristos 	  int tid = ptid.lwp ();
5148dffb485Schristos 
5158dffb485Schristos 	  if (-1 == ptrace (PTRACE_SET_WATCH_REGS, tid,
5168dffb485Schristos 			    &priv->watch_mirror, NULL))
5178dffb485Schristos 	    perror_with_name ("Couldn't write watch register");
5188dffb485Schristos 	}
5198dffb485Schristos 
5208dffb485Schristos       lwp->arch_private->watch_registers_changed = 0;
5218dffb485Schristos     }
5228dffb485Schristos }
5238dffb485Schristos 
5248dffb485Schristos bool
5258dffb485Schristos mips_target::supports_z_point_type (char z_type)
5268dffb485Schristos {
5278dffb485Schristos   switch (z_type)
5288dffb485Schristos     {
5298dffb485Schristos     case Z_PACKET_WRITE_WP:
5308dffb485Schristos     case Z_PACKET_READ_WP:
5318dffb485Schristos     case Z_PACKET_ACCESS_WP:
5328dffb485Schristos       return true;
5338dffb485Schristos     default:
5348dffb485Schristos       return false;
5358dffb485Schristos     }
5368dffb485Schristos }
5378dffb485Schristos 
5388dffb485Schristos /* This is the implementation of linux target ops method
5398dffb485Schristos    low_insert_point.  */
5408dffb485Schristos 
5418dffb485Schristos int
5428dffb485Schristos mips_target::low_insert_point (raw_bkpt_type type, CORE_ADDR addr,
5438dffb485Schristos 			       int len, raw_breakpoint *bp)
5448dffb485Schristos {
5458dffb485Schristos   struct process_info *proc = current_process ();
5468dffb485Schristos   struct arch_process_info *priv = proc->priv->arch_private;
5478dffb485Schristos   struct pt_watch_regs regs;
5488dffb485Schristos   long lwpid;
5498dffb485Schristos   enum target_hw_bp_type watch_type;
5508dffb485Schristos   uint32_t irw;
5518dffb485Schristos 
5528dffb485Schristos   lwpid = lwpid_of (current_thread);
5538dffb485Schristos   if (!mips_linux_read_watch_registers (lwpid,
5548dffb485Schristos 					&priv->watch_readback,
5558dffb485Schristos 					&priv->watch_readback_valid,
5568dffb485Schristos 					0))
5578dffb485Schristos     return -1;
5588dffb485Schristos 
5598dffb485Schristos   if (len <= 0)
5608dffb485Schristos     return -1;
5618dffb485Schristos 
5628dffb485Schristos   regs = priv->watch_readback;
5638dffb485Schristos   /* Add the current watches.  */
5648dffb485Schristos   mips_linux_watch_populate_regs (priv->current_watches, &regs);
5658dffb485Schristos 
5668dffb485Schristos   /* Now try to add the new watch.  */
5678dffb485Schristos   watch_type = raw_bkpt_type_to_target_hw_bp_type (type);
5688dffb485Schristos   irw = mips_linux_watch_type_to_irw (watch_type);
5698dffb485Schristos   if (!mips_linux_watch_try_one_watch (&regs, addr, len, irw))
5708dffb485Schristos     return -1;
5718dffb485Schristos 
5728dffb485Schristos   /* It fit.  Stick it on the end of the list.  */
5738dffb485Schristos   mips_add_watchpoint (priv, addr, len, watch_type);
5748dffb485Schristos 
5758dffb485Schristos   priv->watch_mirror = regs;
5768dffb485Schristos 
5778dffb485Schristos   /* Only update the threads of this process.  */
5788dffb485Schristos   for_each_thread (proc->pid, update_watch_registers_callback);
5798dffb485Schristos 
5808dffb485Schristos   return 0;
5818dffb485Schristos }
5828dffb485Schristos 
5838dffb485Schristos /* This is the implementation of linux target ops method
5848dffb485Schristos    low_remove_point.  */
5858dffb485Schristos 
5868dffb485Schristos int
5878dffb485Schristos mips_target::low_remove_point (raw_bkpt_type type, CORE_ADDR addr,
5888dffb485Schristos 			       int len, raw_breakpoint *bp)
5898dffb485Schristos {
5908dffb485Schristos   struct process_info *proc = current_process ();
5918dffb485Schristos   struct arch_process_info *priv = proc->priv->arch_private;
5928dffb485Schristos 
5938dffb485Schristos   int deleted_one;
5948dffb485Schristos   enum target_hw_bp_type watch_type;
5958dffb485Schristos 
5968dffb485Schristos   struct mips_watchpoint **pw;
5978dffb485Schristos   struct mips_watchpoint *w;
5988dffb485Schristos 
5998dffb485Schristos   /* Search for a known watch that matches.  Then unlink and free it.  */
6008dffb485Schristos   watch_type = raw_bkpt_type_to_target_hw_bp_type (type);
6018dffb485Schristos   deleted_one = 0;
6028dffb485Schristos   pw = &priv->current_watches;
6038dffb485Schristos   while ((w = *pw))
6048dffb485Schristos     {
6058dffb485Schristos       if (w->addr == addr && w->len == len && w->type == watch_type)
6068dffb485Schristos 	{
6078dffb485Schristos 	  *pw = w->next;
6088dffb485Schristos 	  free (w);
6098dffb485Schristos 	  deleted_one = 1;
6108dffb485Schristos 	  break;
6118dffb485Schristos 	}
6128dffb485Schristos       pw = &(w->next);
6138dffb485Schristos     }
6148dffb485Schristos 
6158dffb485Schristos   if (!deleted_one)
6168dffb485Schristos     return -1;  /* We don't know about it, fail doing nothing.  */
6178dffb485Schristos 
6188dffb485Schristos   /* At this point watch_readback is known to be valid because we
6198dffb485Schristos      could not have added the watch without reading it.  */
6208dffb485Schristos   gdb_assert (priv->watch_readback_valid == 1);
6218dffb485Schristos 
6228dffb485Schristos   priv->watch_mirror = priv->watch_readback;
6238dffb485Schristos   mips_linux_watch_populate_regs (priv->current_watches,
6248dffb485Schristos 				  &priv->watch_mirror);
6258dffb485Schristos 
6268dffb485Schristos   /* Only update the threads of this process.  */
6278dffb485Schristos   for_each_thread (proc->pid, update_watch_registers_callback);
6288dffb485Schristos 
6298dffb485Schristos   return 0;
6308dffb485Schristos }
6318dffb485Schristos 
6328dffb485Schristos /* This is the implementation of linux target ops method
6338dffb485Schristos    low_stopped_by_watchpoint.  The watchhi R and W bits indicate
6348dffb485Schristos    the watch register triggered. */
6358dffb485Schristos 
6368dffb485Schristos bool
6378dffb485Schristos mips_target::low_stopped_by_watchpoint ()
6388dffb485Schristos {
6398dffb485Schristos   struct process_info *proc = current_process ();
6408dffb485Schristos   struct arch_process_info *priv = proc->priv->arch_private;
6418dffb485Schristos   int n;
6428dffb485Schristos   int num_valid;
6438dffb485Schristos   long lwpid = lwpid_of (current_thread);
6448dffb485Schristos 
6458dffb485Schristos   if (!mips_linux_read_watch_registers (lwpid,
6468dffb485Schristos 					&priv->watch_readback,
6478dffb485Schristos 					&priv->watch_readback_valid,
6488dffb485Schristos 					1))
6498dffb485Schristos     return 0;
6508dffb485Schristos 
6518dffb485Schristos   num_valid = mips_linux_watch_get_num_valid (&priv->watch_readback);
6528dffb485Schristos 
6538dffb485Schristos   for (n = 0; n < MAX_DEBUG_REGISTER && n < num_valid; n++)
6548dffb485Schristos     if (mips_linux_watch_get_watchhi (&priv->watch_readback, n)
6558dffb485Schristos 	& (R_MASK | W_MASK))
6568dffb485Schristos       return true;
6578dffb485Schristos 
6588dffb485Schristos   return false;
6598dffb485Schristos }
6608dffb485Schristos 
6618dffb485Schristos /* This is the implementation of linux target ops method
6628dffb485Schristos    low_stopped_data_address.  */
6638dffb485Schristos 
6648dffb485Schristos CORE_ADDR
6658dffb485Schristos mips_target::low_stopped_data_address ()
6668dffb485Schristos {
6678dffb485Schristos   struct process_info *proc = current_process ();
6688dffb485Schristos   struct arch_process_info *priv = proc->priv->arch_private;
6698dffb485Schristos   int n;
6708dffb485Schristos   int num_valid;
6718dffb485Schristos   long lwpid = lwpid_of (current_thread);
6728dffb485Schristos 
6738dffb485Schristos   /* On MIPS we don't know the low order 3 bits of the data address.
6748dffb485Schristos      GDB does not support remote targets that can't report the
6758dffb485Schristos      watchpoint address.  So, make our best guess; return the starting
6768dffb485Schristos      address of a watchpoint request which overlaps the one that
6778dffb485Schristos      triggered.  */
6788dffb485Schristos 
6798dffb485Schristos   if (!mips_linux_read_watch_registers (lwpid,
6808dffb485Schristos 					&priv->watch_readback,
6818dffb485Schristos 					&priv->watch_readback_valid,
6828dffb485Schristos 					0))
6838dffb485Schristos     return 0;
6848dffb485Schristos 
6858dffb485Schristos   num_valid = mips_linux_watch_get_num_valid (&priv->watch_readback);
6868dffb485Schristos 
6878dffb485Schristos   for (n = 0; n < MAX_DEBUG_REGISTER && n < num_valid; n++)
6888dffb485Schristos     if (mips_linux_watch_get_watchhi (&priv->watch_readback, n)
6898dffb485Schristos 	& (R_MASK | W_MASK))
6908dffb485Schristos       {
6918dffb485Schristos 	CORE_ADDR t_low, t_hi;
6928dffb485Schristos 	int t_irw;
6938dffb485Schristos 	struct mips_watchpoint *watch;
6948dffb485Schristos 
6958dffb485Schristos 	t_low = mips_linux_watch_get_watchlo (&priv->watch_readback, n);
6968dffb485Schristos 	t_irw = t_low & IRW_MASK;
6978dffb485Schristos 	t_hi = (mips_linux_watch_get_watchhi (&priv->watch_readback, n)
6988dffb485Schristos 		| IRW_MASK);
6998dffb485Schristos 	t_low &= ~(CORE_ADDR)t_hi;
7008dffb485Schristos 
7018dffb485Schristos 	for (watch = priv->current_watches;
7028dffb485Schristos 	     watch != NULL;
7038dffb485Schristos 	     watch = watch->next)
7048dffb485Schristos 	  {
7058dffb485Schristos 	    CORE_ADDR addr = watch->addr;
7068dffb485Schristos 	    CORE_ADDR last_byte = addr + watch->len - 1;
7078dffb485Schristos 
7088dffb485Schristos 	    if ((t_irw & mips_linux_watch_type_to_irw (watch->type)) == 0)
7098dffb485Schristos 	      {
7108dffb485Schristos 		/* Different type.  */
7118dffb485Schristos 		continue;
7128dffb485Schristos 	      }
7138dffb485Schristos 	    /* Check for overlap of even a single byte.  */
7148dffb485Schristos 	    if (last_byte >= t_low && addr <= t_low + t_hi)
7158dffb485Schristos 	      return addr;
7168dffb485Schristos 	  }
7178dffb485Schristos       }
7188dffb485Schristos 
7198dffb485Schristos   /* Shouldn't happen.  */
7208dffb485Schristos   return 0;
7218dffb485Schristos }
7228dffb485Schristos 
7238dffb485Schristos /* Fetch the thread-local storage pointer for libthread_db.  */
7248dffb485Schristos 
7258dffb485Schristos ps_err_e
7268dffb485Schristos ps_get_thread_area (struct ps_prochandle *ph,
7278dffb485Schristos 		    lwpid_t lwpid, int idx, void **base)
7288dffb485Schristos {
7298dffb485Schristos   if (ptrace (PTRACE_GET_THREAD_AREA, lwpid, NULL, base) != 0)
7308dffb485Schristos     return PS_ERR;
7318dffb485Schristos 
7328dffb485Schristos   /* IDX is the bias from the thread pointer to the beginning of the
7338dffb485Schristos      thread descriptor.  It has to be subtracted due to implementation
7348dffb485Schristos      quirks in libthread_db.  */
7358dffb485Schristos   *base = (void *) ((char *)*base - idx);
7368dffb485Schristos 
7378dffb485Schristos   return PS_OK;
7388dffb485Schristos }
7398dffb485Schristos 
7408dffb485Schristos static void
7418dffb485Schristos mips_collect_register (struct regcache *regcache,
7428dffb485Schristos 		       int use_64bit, int regno, union mips_register *reg)
7438dffb485Schristos {
7448dffb485Schristos   union mips_register tmp_reg;
7458dffb485Schristos 
7468dffb485Schristos   if (use_64bit)
7478dffb485Schristos     {
7488dffb485Schristos       collect_register (regcache, regno, &tmp_reg.reg64);
7498dffb485Schristos       *reg = tmp_reg;
7508dffb485Schristos     }
7518dffb485Schristos   else
7528dffb485Schristos     {
7538dffb485Schristos       collect_register (regcache, regno, &tmp_reg.reg32);
7548dffb485Schristos       reg->reg64 = tmp_reg.reg32;
7558dffb485Schristos     }
7568dffb485Schristos }
7578dffb485Schristos 
7588dffb485Schristos static void
7598dffb485Schristos mips_supply_register (struct regcache *regcache,
7608dffb485Schristos 		      int use_64bit, int regno, const union mips_register *reg)
7618dffb485Schristos {
7628dffb485Schristos   int offset = 0;
7638dffb485Schristos 
7648dffb485Schristos   /* For big-endian 32-bit targets, ignore the high four bytes of each
7658dffb485Schristos      eight-byte slot.  */
7668dffb485Schristos   if (__BYTE_ORDER == __BIG_ENDIAN && !use_64bit)
7678dffb485Schristos     offset = 4;
7688dffb485Schristos 
7698dffb485Schristos   supply_register (regcache, regno, reg->buf + offset);
7708dffb485Schristos }
7718dffb485Schristos 
7728dffb485Schristos #ifdef HAVE_PTRACE_GETREGS
7738dffb485Schristos 
7748dffb485Schristos static void
7758dffb485Schristos mips_collect_register_32bit (struct regcache *regcache,
7768dffb485Schristos 			     int use_64bit, int regno, unsigned char *buf)
7778dffb485Schristos {
7788dffb485Schristos   union mips_register tmp_reg;
7798dffb485Schristos   int reg32;
7808dffb485Schristos 
7818dffb485Schristos   mips_collect_register (regcache, use_64bit, regno, &tmp_reg);
7828dffb485Schristos   reg32 = tmp_reg.reg64;
7838dffb485Schristos   memcpy (buf, &reg32, 4);
7848dffb485Schristos }
7858dffb485Schristos 
7868dffb485Schristos static void
7878dffb485Schristos mips_supply_register_32bit (struct regcache *regcache,
7888dffb485Schristos 			    int use_64bit, int regno, const unsigned char *buf)
7898dffb485Schristos {
7908dffb485Schristos   union mips_register tmp_reg;
7918dffb485Schristos   int reg32;
7928dffb485Schristos 
7938dffb485Schristos   memcpy (&reg32, buf, 4);
7948dffb485Schristos   tmp_reg.reg64 = reg32;
7958dffb485Schristos   mips_supply_register (regcache, use_64bit, regno, &tmp_reg);
7968dffb485Schristos }
7978dffb485Schristos 
7988dffb485Schristos static void
7998dffb485Schristos mips_fill_gregset (struct regcache *regcache, void *buf)
8008dffb485Schristos {
8018dffb485Schristos   union mips_register *regset = (union mips_register *) buf;
8028dffb485Schristos   int i, use_64bit;
8038dffb485Schristos   const struct target_desc *tdesc = regcache->tdesc;
8048dffb485Schristos 
8058dffb485Schristos   use_64bit = (register_size (tdesc, 0) == 8);
8068dffb485Schristos 
8078dffb485Schristos   for (i = 1; i < 32; i++)
8088dffb485Schristos     mips_collect_register (regcache, use_64bit, i, regset + i);
8098dffb485Schristos 
8108dffb485Schristos   mips_collect_register (regcache, use_64bit,
8118dffb485Schristos 			 find_regno (tdesc, "lo"), regset + 32);
8128dffb485Schristos   mips_collect_register (regcache, use_64bit,
8138dffb485Schristos 			 find_regno (tdesc, "hi"), regset + 33);
8148dffb485Schristos   mips_collect_register (regcache, use_64bit,
8158dffb485Schristos 			 find_regno (tdesc, "pc"), regset + 34);
8168dffb485Schristos   mips_collect_register (regcache, use_64bit,
8178dffb485Schristos 			 find_regno (tdesc, "badvaddr"), regset + 35);
8188dffb485Schristos   mips_collect_register (regcache, use_64bit,
8198dffb485Schristos 			 find_regno (tdesc, "status"), regset + 36);
8208dffb485Schristos   mips_collect_register (regcache, use_64bit,
8218dffb485Schristos 			 find_regno (tdesc, "cause"), regset + 37);
8228dffb485Schristos 
8238dffb485Schristos   mips_collect_register (regcache, use_64bit,
8248dffb485Schristos 			 find_regno (tdesc, "restart"), regset + 0);
8258dffb485Schristos }
8268dffb485Schristos 
8278dffb485Schristos static void
8288dffb485Schristos mips_store_gregset (struct regcache *regcache, const void *buf)
8298dffb485Schristos {
8308dffb485Schristos   const union mips_register *regset = (const union mips_register *) buf;
8318dffb485Schristos   int i, use_64bit;
8328dffb485Schristos 
8338dffb485Schristos   use_64bit = (register_size (regcache->tdesc, 0) == 8);
8348dffb485Schristos 
8358dffb485Schristos   supply_register_by_name_zeroed (regcache, "r0");
8368dffb485Schristos 
8378dffb485Schristos   for (i = 1; i < 32; i++)
8388dffb485Schristos     mips_supply_register (regcache, use_64bit, i, regset + i);
8398dffb485Schristos 
8408dffb485Schristos   mips_supply_register (regcache, use_64bit,
8418dffb485Schristos 			find_regno (regcache->tdesc, "lo"), regset + 32);
8428dffb485Schristos   mips_supply_register (regcache, use_64bit,
8438dffb485Schristos 			find_regno (regcache->tdesc, "hi"), regset + 33);
8448dffb485Schristos   mips_supply_register (regcache, use_64bit,
8458dffb485Schristos 			find_regno (regcache->tdesc, "pc"), regset + 34);
8468dffb485Schristos   mips_supply_register (regcache, use_64bit,
8478dffb485Schristos 			find_regno (regcache->tdesc, "badvaddr"), regset + 35);
8488dffb485Schristos   mips_supply_register (regcache, use_64bit,
8498dffb485Schristos 			find_regno (regcache->tdesc, "status"), regset + 36);
8508dffb485Schristos   mips_supply_register (regcache, use_64bit,
8518dffb485Schristos 			find_regno (regcache->tdesc, "cause"), regset + 37);
8528dffb485Schristos 
8538dffb485Schristos   mips_supply_register (regcache, use_64bit,
8548dffb485Schristos 			find_regno (regcache->tdesc, "restart"), regset + 0);
8558dffb485Schristos }
8568dffb485Schristos 
8578dffb485Schristos static void
8588dffb485Schristos mips_fill_fpregset (struct regcache *regcache, void *buf)
8598dffb485Schristos {
8608dffb485Schristos   union mips_register *regset = (union mips_register *) buf;
8618dffb485Schristos   int i, use_64bit, first_fp, big_endian;
8628dffb485Schristos 
8638dffb485Schristos   use_64bit = (register_size (regcache->tdesc, 0) == 8);
8648dffb485Schristos   first_fp = find_regno (regcache->tdesc, "f0");
8658dffb485Schristos   big_endian = (__BYTE_ORDER == __BIG_ENDIAN);
8668dffb485Schristos 
8678dffb485Schristos   /* See GDB for a discussion of this peculiar layout.  */
8688dffb485Schristos   for (i = 0; i < 32; i++)
8698dffb485Schristos     if (use_64bit)
8708dffb485Schristos       collect_register (regcache, first_fp + i, regset[i].buf);
8718dffb485Schristos     else
8728dffb485Schristos       collect_register (regcache, first_fp + i,
8738dffb485Schristos 			regset[i & ~1].buf + 4 * (big_endian != (i & 1)));
8748dffb485Schristos 
8758dffb485Schristos   mips_collect_register_32bit (regcache, use_64bit,
8768dffb485Schristos 			       find_regno (regcache->tdesc, "fcsr"), regset[32].buf);
8778dffb485Schristos   mips_collect_register_32bit (regcache, use_64bit,
8788dffb485Schristos 			       find_regno (regcache->tdesc, "fir"),
8798dffb485Schristos 			       regset[32].buf + 4);
8808dffb485Schristos }
8818dffb485Schristos 
8828dffb485Schristos static void
8838dffb485Schristos mips_store_fpregset (struct regcache *regcache, const void *buf)
8848dffb485Schristos {
8858dffb485Schristos   const union mips_register *regset = (const union mips_register *) buf;
8868dffb485Schristos   int i, use_64bit, first_fp, big_endian;
8878dffb485Schristos 
8888dffb485Schristos   use_64bit = (register_size (regcache->tdesc, 0) == 8);
8898dffb485Schristos   first_fp = find_regno (regcache->tdesc, "f0");
8908dffb485Schristos   big_endian = (__BYTE_ORDER == __BIG_ENDIAN);
8918dffb485Schristos 
8928dffb485Schristos   /* See GDB for a discussion of this peculiar layout.  */
8938dffb485Schristos   for (i = 0; i < 32; i++)
8948dffb485Schristos     if (use_64bit)
8958dffb485Schristos       supply_register (regcache, first_fp + i, regset[i].buf);
8968dffb485Schristos     else
8978dffb485Schristos       supply_register (regcache, first_fp + i,
8988dffb485Schristos 		       regset[i & ~1].buf + 4 * (big_endian != (i & 1)));
8998dffb485Schristos 
9008dffb485Schristos   mips_supply_register_32bit (regcache, use_64bit,
9018dffb485Schristos 			      find_regno (regcache->tdesc, "fcsr"),
9028dffb485Schristos 			      regset[32].buf);
9038dffb485Schristos   mips_supply_register_32bit (regcache, use_64bit,
9048dffb485Schristos 			      find_regno (regcache->tdesc, "fir"),
9058dffb485Schristos 			      regset[32].buf + 4);
9068dffb485Schristos }
9078dffb485Schristos #endif /* HAVE_PTRACE_GETREGS */
9088dffb485Schristos 
9098dffb485Schristos /* Take care of 32-bit registers with 64-bit ptrace, POKEUSER side.  */
9108dffb485Schristos 
9118dffb485Schristos void
9128dffb485Schristos mips_target::low_collect_ptrace_register (regcache *regcache, int regno,
9138dffb485Schristos 					  char *buf)
9148dffb485Schristos {
9158dffb485Schristos   int use_64bit = sizeof (PTRACE_XFER_TYPE) == 8;
9168dffb485Schristos 
9178dffb485Schristos   if (use_64bit && register_size (regcache->tdesc, regno) == 4)
9188dffb485Schristos     {
9198dffb485Schristos       union mips_register reg;
9208dffb485Schristos 
9218dffb485Schristos       mips_collect_register (regcache, 0, regno, &reg);
9228dffb485Schristos       memcpy (buf, &reg, sizeof (reg));
9238dffb485Schristos     }
9248dffb485Schristos   else
9258dffb485Schristos     collect_register (regcache, regno, buf);
9268dffb485Schristos }
9278dffb485Schristos 
9288dffb485Schristos /* Take care of 32-bit registers with 64-bit ptrace, PEEKUSER side.  */
9298dffb485Schristos 
9308dffb485Schristos void
9318dffb485Schristos mips_target::low_supply_ptrace_register (regcache *regcache, int regno,
9328dffb485Schristos 					 const char *buf)
9338dffb485Schristos {
9348dffb485Schristos   int use_64bit = sizeof (PTRACE_XFER_TYPE) == 8;
9358dffb485Schristos 
9368dffb485Schristos   if (use_64bit && register_size (regcache->tdesc, regno) == 4)
9378dffb485Schristos     {
9388dffb485Schristos       union mips_register reg;
9398dffb485Schristos 
9408dffb485Schristos       memcpy (&reg, buf, sizeof (reg));
9418dffb485Schristos       mips_supply_register (regcache, 0, regno, &reg);
9428dffb485Schristos     }
9438dffb485Schristos   else
9448dffb485Schristos     supply_register (regcache, regno, buf);
9458dffb485Schristos }
9468dffb485Schristos 
9478dffb485Schristos static struct regset_info mips_regsets[] = {
9488dffb485Schristos #ifdef HAVE_PTRACE_GETREGS
9498dffb485Schristos   { PTRACE_GETREGS, PTRACE_SETREGS, 0, 38 * 8, GENERAL_REGS,
9508dffb485Schristos     mips_fill_gregset, mips_store_gregset },
9518dffb485Schristos   { PTRACE_GETFPREGS, PTRACE_SETFPREGS, 0, 33 * 8, FP_REGS,
9528dffb485Schristos     mips_fill_fpregset, mips_store_fpregset },
9538dffb485Schristos #endif /* HAVE_PTRACE_GETREGS */
9548dffb485Schristos   NULL_REGSET
9558dffb485Schristos };
9568dffb485Schristos 
9578dffb485Schristos static struct regsets_info mips_regsets_info =
9588dffb485Schristos   {
9598dffb485Schristos     mips_regsets, /* regsets */
9608dffb485Schristos     0, /* num_regsets */
9618dffb485Schristos     NULL, /* disabled_regsets */
9628dffb485Schristos   };
9638dffb485Schristos 
9648dffb485Schristos static struct usrregs_info mips_dsp_usrregs_info =
9658dffb485Schristos   {
9668dffb485Schristos     mips_dsp_num_regs,
9678dffb485Schristos     mips_dsp_regmap,
9688dffb485Schristos   };
9698dffb485Schristos 
9708dffb485Schristos static struct usrregs_info mips_usrregs_info =
9718dffb485Schristos   {
9728dffb485Schristos     mips_num_regs,
9738dffb485Schristos     mips_regmap,
9748dffb485Schristos   };
9758dffb485Schristos 
9768dffb485Schristos static struct regs_info dsp_regs_info =
9778dffb485Schristos   {
9788dffb485Schristos     mips_dsp_regset_bitmap,
9798dffb485Schristos     &mips_dsp_usrregs_info,
9808dffb485Schristos     &mips_regsets_info
9818dffb485Schristos   };
9828dffb485Schristos 
9838dffb485Schristos static struct regs_info myregs_info =
9848dffb485Schristos   {
9858dffb485Schristos     NULL, /* regset_bitmap */
9868dffb485Schristos     &mips_usrregs_info,
9878dffb485Schristos     &mips_regsets_info
9888dffb485Schristos   };
9898dffb485Schristos 
9908dffb485Schristos const regs_info *
9918dffb485Schristos mips_target::get_regs_info ()
9928dffb485Schristos {
9938dffb485Schristos   if (have_dsp)
9948dffb485Schristos     return &dsp_regs_info;
9958dffb485Schristos   else
9968dffb485Schristos     return &myregs_info;
9978dffb485Schristos }
9988dffb485Schristos 
9998dffb485Schristos /* The linux target ops object.  */
10008dffb485Schristos 
10018dffb485Schristos linux_process_target *the_linux_target = &the_mips_target;
10028dffb485Schristos 
10038dffb485Schristos void
10048dffb485Schristos initialize_low_arch (void)
10058dffb485Schristos {
10068dffb485Schristos   /* Initialize the Linux target descriptions.  */
10078dffb485Schristos   init_registers_mips_linux ();
10088dffb485Schristos   init_registers_mips_dsp_linux ();
10098dffb485Schristos   init_registers_mips64_linux ();
10108dffb485Schristos   init_registers_mips64_dsp_linux ();
10118dffb485Schristos 
10128dffb485Schristos   initialize_regsets_info (&mips_regsets_info);
10138dffb485Schristos }
1014