2012-05-24 Pedro Alves <palves@redhat.com>
[deliverable/binutils-gdb.git] / gdb / gdbserver / linux-crisv32-low.c
index d811b7c7369cf39e1d02a11eab343a7374483620..1cc4cd10c18d1ec90695a8b8912c361226bfec4f 100644 (file)
@@ -1,12 +1,12 @@
 /* GNU/Linux/CRIS specific low level interface, for the remote server for GDB.
-   Copyright (C) 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-   2007 Free Software Foundation, Inc.
+   Copyright (C) 1995-1996, 1998-2005, 2007-2012 Free Software
+   Foundation, Inc.
 
    This file is part of GDB.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "server.h"
 #include "linux-low.h"
 #include <sys/ptrace.h>
 
+/* Defined in auto-generated file reg-crisv32.c.  */
+void init_registers_crisv32 (void);
+
 /* CRISv32 */
 #define cris_num_regs 49
 
@@ -43,30 +44,30 @@ static int cris_regmap[] = {
 
   25*4,
 
-  26*4, -1,   -1,   29*4, 
+  26*4, -1,   -1,   29*4,
   30*4, 31*4, 32*4, 33*4,
   34*4, 35*4, 36*4, 37*4,
   38*4, 39*4, 40*4, -1
-  
+
 };
 
 extern int debug_threads;
 
 static CORE_ADDR
-cris_get_pc (void)
+cris_get_pc (struct regcache *regcache)
 {
   unsigned long pc;
-  collect_register_by_name ("pc", &pc);
+  collect_register_by_name (regcache, "pc", &pc);
   if (debug_threads)
     fprintf (stderr, "stop pc is %08lx\n", pc);
   return pc;
 }
 
 static void
-cris_set_pc (CORE_ADDR pc)
+cris_set_pc (struct regcache *regcache, CORE_ADDR pc)
 {
   unsigned long newpc = pc;
-  supply_register_by_name ("pc", &newpc);
+  supply_register_by_name (regcache, "pc", &newpc);
 }
 
 static const unsigned short cris_breakpoint = 0xe938;
@@ -98,51 +99,54 @@ cris_breakpoint_at (CORE_ADDR where)
 static CORE_ADDR
 cris_reinsert_addr (void)
 {
+  struct regcache *regcache = get_thread_regcache (current_inferior, 1);
   unsigned long pc;
-  collect_register_by_name ("srp", &pc);
+  collect_register_by_name (regcache, "srp", &pc);
   return pc;
 }
 
 static void
-cris_write_data_breakpoint (int bp, unsigned long start, unsigned long end)
+cris_write_data_breakpoint (struct regcache *regcache,
+                           int bp, unsigned long start, unsigned long end)
 {
   switch (bp)
     {
     case 0:
-      supply_register_by_name ("s3", &start);
-      supply_register_by_name ("s4", &end);
+      supply_register_by_name (regcache, "s3", &start);
+      supply_register_by_name (regcache, "s4", &end);
       break;
     case 1:
-      supply_register_by_name ("s5", &start);
-      supply_register_by_name ("s6", &end);
+      supply_register_by_name (regcache, "s5", &start);
+      supply_register_by_name (regcache, "s6", &end);
       break;
     case 2:
-      supply_register_by_name ("s7", &start);
-      supply_register_by_name ("s8", &end);
+      supply_register_by_name (regcache, "s7", &start);
+      supply_register_by_name (regcache, "s8", &end);
       break;
     case 3:
-      supply_register_by_name ("s9", &start);
-      supply_register_by_name ("s10", &end);
+      supply_register_by_name (regcache, "s9", &start);
+      supply_register_by_name (regcache, "s10", &end);
       break;
     case 4:
-      supply_register_by_name ("s11", &start);
-      supply_register_by_name ("s12", &end);
+      supply_register_by_name (regcache, "s11", &start);
+      supply_register_by_name (regcache, "s12", &end);
       break;
     case 5:
-      supply_register_by_name ("s13", &start);
-      supply_register_by_name ("s14", &end);
+      supply_register_by_name (regcache, "s13", &start);
+      supply_register_by_name (regcache, "s14", &end);
       break;
     }
 }
 
 static int
-cris_insert_watchpoint (char type, CORE_ADDR addr, int len)
+cris_insert_point (char type, CORE_ADDR addr, int len)
 {
   int bp;
   unsigned long bp_ctrl;
   unsigned long start, end;
   unsigned long ccs;
-  
+  struct regcache *regcache;
+
   /* Breakpoint/watchpoint types (GDB terminology):
      0 = memory breakpoint for instructions
      (not supported; done via memory write instead)
@@ -150,20 +154,22 @@ cris_insert_watchpoint (char type, CORE_ADDR addr, int len)
      2 = write watchpoint (supported)
      3 = read watchpoint (supported)
      4 = access watchpoint (supported).  */
-  
-  if (type < '2' || type > '4') 
+
+  if (type < '2' || type > '4')
     {
       /* Unsupported.  */
       return 1;
     }
 
+  regcache = get_thread_regcache (current_inferior, 1);
+
   /* Read watchpoints are set as access watchpoints, because of GDB's
      inability to deal with pure read watchpoints.  */
   if (type == '3')
     type = '4';
 
   /* Get the configuration register.  */
-  collect_register_by_name ("s0", &bp_ctrl);
+  collect_register_by_name (regcache, "s0", &bp_ctrl);
 
   /* The watchpoint allocation scheme is the simplest possible.
      For example, if a region is watched for read and
@@ -171,17 +177,17 @@ cris_insert_watchpoint (char type, CORE_ADDR addr, int len)
      be used.  Also, if a watch for a region that is already
      covered by one or more existing watchpoints, a new
      watchpoint will be used.  */
-    
+
   /* First, find a free data watchpoint.  */
   for (bp = 0; bp < 6; bp++)
     {
       /* Each data watchpoint's control registers occupy 2 bits
         (hence the 3), starting at bit 2 for D0 (hence the 2)
         with 4 bits between for each watchpoint (yes, the 4).  */
-      if (!(bp_ctrl & (0x3 << (2 + (bp * 4))))) 
+      if (!(bp_ctrl & (0x3 << (2 + (bp * 4)))))
        break;
     }
-    
+
   if (bp > 5)
     {
       /* We're out of watchpoints.  */
@@ -194,37 +200,38 @@ cris_insert_watchpoint (char type, CORE_ADDR addr, int len)
       /* Trigger on read.  */
       bp_ctrl |= (1 << (2 + bp * 4));
     }
-  if (type == '2' || type == '4') 
+  if (type == '2' || type == '4')
     {
       /* Trigger on write.  */
       bp_ctrl |= (2 << (2 + bp * 4));
     }
-  
+
   /* Setup the configuration register.  */
-  supply_register_by_name ("s0", &bp_ctrl);
-  
+  supply_register_by_name (regcache, "s0", &bp_ctrl);
+
   /* Setup the range.  */
   start = addr;
   end = addr + len - 1;
 
   /* Configure the watchpoint register.  */
-  cris_write_data_breakpoint (bp, start, end);
+  cris_write_data_breakpoint (regcache, bp, start, end);
 
-  collect_register_by_name ("ccs", &ccs);
+  collect_register_by_name (regcache, "ccs", &ccs);
   /* Set the S1 flag to enable watchpoints.  */
   ccs |= (1 << 19);
-  supply_register_by_name ("ccs", &ccs);
+  supply_register_by_name (regcache, "ccs", &ccs);
 
   return 0;
 }
 
 static int
-cris_remove_watchpoint (char type, CORE_ADDR addr, int len)
+cris_remove_point (char type, CORE_ADDR addr, int len)
 {
   int bp;
   unsigned long bp_ctrl;
   unsigned long start, end;
-  
+  struct regcache *regcache;
+
   /* Breakpoint/watchpoint types:
      0 = memory breakpoint for instructions
      (not supported; done via memory write instead)
@@ -234,18 +241,20 @@ cris_remove_watchpoint (char type, CORE_ADDR addr, int len)
      4 = access watchpoint (supported).  */
   if (type < '2' || type > '4')
     return -1;
-  
+
+  regcache = get_thread_regcache (current_inferior, 1);
+
   /* Read watchpoints are set as access watchpoints, because of GDB's
      inability to deal with pure read watchpoints.  */
   if (type == '3')
     type = '4';
-  
+
   /* Get the configuration register.  */
-  collect_register_by_name ("s0", &bp_ctrl);
+  collect_register_by_name (regcache, "s0", &bp_ctrl);
 
   /* Try to find a watchpoint that is configured for the
      specified range, then check that read/write also matches.  */
-  
+
   /* Ugly pointer arithmetic, since I cannot rely on a
      single switch (addr) as there may be several watchpoints with
      the same start address for example.  */
@@ -253,32 +262,32 @@ cris_remove_watchpoint (char type, CORE_ADDR addr, int len)
   unsigned long bp_d_regs[12];
 
   /* Get all range registers to simplify search.  */
-  collect_register_by_name ("s3", &bp_d_regs[0]);
-  collect_register_by_name ("s4", &bp_d_regs[1]);
-  collect_register_by_name ("s5", &bp_d_regs[2]);
-  collect_register_by_name ("s6", &bp_d_regs[3]);
-  collect_register_by_name ("s7", &bp_d_regs[4]);
-  collect_register_by_name ("s8", &bp_d_regs[5]);
-  collect_register_by_name ("s9", &bp_d_regs[6]);
-  collect_register_by_name ("s10", &bp_d_regs[7]);
-  collect_register_by_name ("s11", &bp_d_regs[8]);
-  collect_register_by_name ("s12", &bp_d_regs[9]);
-  collect_register_by_name ("s13", &bp_d_regs[10]);
-  collect_register_by_name ("s14", &bp_d_regs[11]);
-
-  for (bp = 0; bp < 6; bp++) 
+  collect_register_by_name (regcache, "s3", &bp_d_regs[0]);
+  collect_register_by_name (regcache, "s4", &bp_d_regs[1]);
+  collect_register_by_name (regcache, "s5", &bp_d_regs[2]);
+  collect_register_by_name (regcache, "s6", &bp_d_regs[3]);
+  collect_register_by_name (regcache, "s7", &bp_d_regs[4]);
+  collect_register_by_name (regcache, "s8", &bp_d_regs[5]);
+  collect_register_by_name (regcache, "s9", &bp_d_regs[6]);
+  collect_register_by_name (regcache, "s10", &bp_d_regs[7]);
+  collect_register_by_name (regcache, "s11", &bp_d_regs[8]);
+  collect_register_by_name (regcache, "s12", &bp_d_regs[9]);
+  collect_register_by_name (regcache, "s13", &bp_d_regs[10]);
+  collect_register_by_name (regcache, "s14", &bp_d_regs[11]);
+
+  for (bp = 0; bp < 6; bp++)
     {
-      if (bp_d_regs[bp * 2] == addr 
+      if (bp_d_regs[bp * 2] == addr
          && bp_d_regs[bp * 2 + 1] == (addr + len - 1)) {
        /* Matching range.  */
        int bitpos = 2 + bp * 4;
        int rw_bits;
-      
+
        /* Read/write bits for this BP.  */
        rw_bits = (bp_ctrl & (0x3 << bitpos)) >> bitpos;
-      
+
        if ((type == '3' && rw_bits == 0x1)
-           || (type == '2' && rw_bits == 0x2) 
+           || (type == '2' && rw_bits == 0x2)
            || (type == '4' && rw_bits == 0x3))
          {
            /* Read/write matched.  */
@@ -286,23 +295,23 @@ cris_remove_watchpoint (char type, CORE_ADDR addr, int len)
          }
       }
     }
-    
+
   if (bp > 5)
     {
       /* No watchpoint matched.  */
       return -1;
     }
-    
+
   /* Found a matching watchpoint.  Now, deconfigure it by
      both disabling read/write in bp_ctrl and zeroing its
      start/end addresses.  */
   bp_ctrl &= ~(3 << (2 + (bp * 4)));
   /* Setup the configuration register.  */
-  supply_register_by_name ("s0", &bp_ctrl);
+  supply_register_by_name (regcache, "s0", &bp_ctrl);
 
   start = end = 0;
   /* Configure the watchpoint register.  */
-  cris_write_data_breakpoint (bp, start, end);
+  cris_write_data_breakpoint (regcache, bp, start, end);
 
   /* Note that we don't clear the S1 flag here.  It's done when continuing.  */
   return 0;
@@ -356,16 +365,19 @@ cris_store_gregset (const void *buf)
 typedef unsigned long elf_gregset_t[cris_num_regs];
 
 struct regset_info target_regsets[] = {
-  { PTRACE_GETREGS, PTRACE_SETREGS, sizeof (elf_gregset_t),
+  { PTRACE_GETREGS, PTRACE_SETREGS, 0, sizeof (elf_gregset_t),
     GENERAL_REGS, cris_fill_gregset, cris_store_gregset },
-  { 0, 0, -1, -1, NULL, NULL }
+  { 0, 0, 0, -1, -1, NULL, NULL }
 };
 
 struct linux_target_ops the_low_target = {
+  init_register_crisv32,
   -1,
   NULL,
   NULL,
   NULL,
+  NULL,
+  NULL, /* fetch_register */
   cris_get_pc,
   cris_set_pc,
   (const unsigned char *) &cris_breakpoint,
@@ -373,8 +385,8 @@ struct linux_target_ops the_low_target = {
   cris_reinsert_addr,
   0,
   cris_breakpoint_at,
-  cris_insert_watchpoint,
-  cris_remove_watchpoint,
+  cris_insert_point,
+  cris_remove_point,
   cris_stopped_by_watchpoint,
   cris_stopped_data_address,
 };
This page took 0.030563 seconds and 4 git commands to generate.