gdb: bfin: new port
authorMike Frysinger <vapier@gentoo.org>
Wed, 29 Dec 2010 16:11:49 +0000 (16:11 +0000)
committerMike Frysinger <vapier@gentoo.org>
Wed, 29 Dec 2010 16:11:49 +0000 (16:11 +0000)
Initial support for Blackfin processors.  This supports the standard ABI.

Signed-off-by: Jie Zhang <jie.zhang@analog.com>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
gdb/ChangeLog
gdb/Makefile.in
gdb/NEWS
gdb/bfin-linux-tdep.c [new file with mode: 0644]
gdb/bfin-tdep.c [new file with mode: 0644]
gdb/bfin-tdep.h [new file with mode: 0644]
gdb/configure.tgt
gdb/syscalls/bfin-linux.xml [new file with mode: 0644]

index e57926cd1d2fd8c6da5a7795d44fa24b232beac9..88cdd75f97ceeb0a116dbc5e4f169e9434743a0f 100644 (file)
@@ -1,3 +1,14 @@
+2010-12-29  Jie Zhang  <jie.zhang@analog.com>
+           Mike Frysinger  <vapier@gentoo.org>
+
+       * Makefile.in (ALLDEPFILES): Add bfin-linux-tdep.c and bfin-tdep.c.
+       (HFILES_NO_SRCDIR): Add bfin-tdep.h.
+       (ALL_TARGET_OBS): Add bfin-linux-tdep.o and bfin-tdep.o.
+       * NEWS: Mention new Blackfin port.
+       * bfin-tdep.c, bfin-tdep.h, bfin-linux-tdep.c,
+       syscalls/bfin-linux.xml: New files.
+       * configure.tgt (bfin-*-*): Handle bfin targets.
+
 2010-12-29  Hui Zhu  <teawater@gmail.com>
 
        * ax-gdb.c (gen_expr): Change error message.
index ff1003947817b4ecca93832b03ccd52dc7b6f08e..e0f66367c5f8065e91d3384dc4ccdc117f9fee3d 100644 (file)
@@ -508,6 +508,7 @@ ALL_TARGET_OBS = \
        armnbsd-tdep.o armobsd-tdep.o \
        arm-tdep.o arm-wince-tdep.o \
        avr-tdep.o \
+       bfin-linux-tdep.o bfin-tdep.o \
        cris-tdep.o \
        dicos-tdep.o \
        frv-linux-tdep.o frv-tdep.o \
@@ -782,7 +783,7 @@ annotate.h sim-regno.h dictionary.h dfp.h main.h frame-unwind.h     \
 remote-fileio.h i386-linux-tdep.h vax-tdep.h objc-lang.h \
 sentinel-frame.h bcache.h symfile.h windows-tdep.h linux-tdep.h \
 gdb_usleep.h jit.h xml-syscall.h ada-operator.inc microblaze-tdep.h \
-psymtab.h psympriv.h progspace.h
+psymtab.h psympriv.h progspace.h bfin-tdep.h
 
 # Header files that already have srcdir in them, or which are in objdir.
 
@@ -1420,6 +1421,7 @@ ALLDEPFILES = \
        arm-linux-nat.c arm-linux-tdep.c arm-symbian-tdep.c arm-tdep.c \
        armnbsd-nat.c armbsd-tdep.c armnbsd-tdep.c armobsd-tdep.c \
        avr-tdep.c \
+       bfin-linux-tdep.c bfin-tdep.c \
        bsd-uthread.c bsd-kvm.c \
        core-regset.c corelow.c \
        dcache.c dicos-tdep.c darwin-nat.c \
index 91f183510acb88b761478b77c114d41414900c21..96b6f05b6fe1254cf31df032b0419a7f6732559c 100644 (file)
--- a/gdb/NEWS
+++ b/gdb/NEWS
   ** GDBserver is now supported on PowerPC LynxOS (versions 4.x and 5.x),
      and i686 LynxOS (version 5.x).
 
+* New targets:
+
+Analog Devices, Inc. Blackfin Processor        bfin-*
+
 * Ada task switching is now supported on sparc-elf targets when
   debugging a program using the Ravenscar Profile.  For more information,
   see the "Tasking Support when using the Ravenscar Profile" section
diff --git a/gdb/bfin-linux-tdep.c b/gdb/bfin-linux-tdep.c
new file mode 100644 (file)
index 0000000..545bdcf
--- /dev/null
@@ -0,0 +1,175 @@
+/* Target-dependent code for Analog Devices Blackfin processor, for GDB.
+
+   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010
+   Free Software Foundation, Inc.
+
+   Contributed by Analog Devices, 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 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   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, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "arch-utils.h"
+#include "regcache.h"
+#include "tramp-frame.h"
+#include "trad-frame.h"
+#include "osabi.h"
+#include "xml-syscall.h"
+#include "linux-tdep.h"
+#include "bfin-tdep.h"
+
+/* From <asm/sigcontext.h>.  */
+
+#define SIGCONTEXT_OFFSET      168
+
+static const int bfin_linux_sigcontext_reg_offset[BFIN_NUM_REGS] =
+{
+  0 * 4,       /* %r0 */
+  1 * 4,       /* %r1 */
+  2 * 4,       /* %r2 */
+  3 * 4,       /* %r3 */
+  4 * 4,       /* %r4 */
+  5 * 4,       /* %r5 */
+  6 * 4,       /* %r6 */
+  7 * 4,       /* %r7 */
+  8 * 4,       /* %p0 */
+  9 * 4,       /* %p1 */
+  10 * 4,      /* %p2 */
+  11 * 4,      /* %p3 */
+  12 * 4,      /* %p4 */
+  13 * 4,      /* %p5 */
+  14 * 4,      /* %sp */
+  23 * 4,      /* %fp */
+  24 * 4,      /* %i0 */
+  25 * 4,      /* %i1 */
+  26 * 4,      /* %i2 */
+  27 * 4,      /* %i3 */
+  28 * 4,      /* %m0 */
+  29 * 4,      /* %m1 */
+  30 * 4,      /* %m2 */
+  31 * 4,      /* %m3 */
+  36 * 4,      /* %b0 */
+  37 * 4,      /* %b1 */
+  38 * 4,      /* %b2 */
+  39 * 4,      /* %b3 */
+  32 * 4,      /* %l0 */
+  33 * 4,      /* %l1 */
+  34 * 4,      /* %l2 */
+  35 * 4,      /* %l3 */
+  17 * 4,      /* %a0x */
+  15 * 4,      /* %a0w */
+  18 * 4,      /* %a1x */
+  16 * 4,      /* %a1w */
+  19 * 4,      /* %astat */
+  20 * 4,      /* %rets */
+  40 * 4,      /* %lc0 */
+  42 * 4,      /* %lt0 */
+  44 * 4,      /* %lb0 */
+  41 * 4,      /* %lc1 */
+  43 * 4,      /* %lt1 */
+  45 * 4,      /* %lb1 */
+  -1,          /* %cycles */
+  -1,          /* %cycles2 */
+  -1,          /* %usp */
+  46 * 4,      /* %seqstat */
+  -1,          /* syscfg */
+  21 * 4,      /* %reti */
+  22 * 4,      /* %retx */
+  -1,          /* %retn */
+  -1,          /* %rete */
+  21 * 4,      /* %pc */
+};
+
+/* Signal trampolines.  */
+
+static void
+bfin_linux_sigframe_init (const struct tramp_frame *self,
+                         struct frame_info *this_frame,
+                         struct trad_frame_cache *this_cache,
+                         CORE_ADDR func)
+{
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
+  CORE_ADDR sp = get_frame_sp (this_frame);
+  CORE_ADDR pc = get_frame_pc (this_frame);
+  CORE_ADDR sigcontext = sp + SIGCONTEXT_OFFSET;
+  struct frame_id this_id;
+  const int *reg_offset = bfin_linux_sigcontext_reg_offset;
+  int i;
+
+  for (i = 0; i < BFIN_NUM_REGS; i++)
+    if (reg_offset[i] != -1)
+      trad_frame_set_reg_addr (this_cache, i, sigcontext + reg_offset[i]);
+
+  /* This would come after the LINK instruction in the ret_from_signal
+     function, hence the frame id would be SP + 8.  */
+  trad_frame_set_id (this_cache, frame_id_build (sp + 8, pc));
+}
+
+static const struct tramp_frame bfin_linux_sigframe =
+{
+  SIGTRAMP_FRAME,
+  4,
+  {
+    { 0x00ADE128, 0xffffffff },        /* P0 = __NR_rt_sigreturn; */
+    { 0x00A0, 0xffff },                /* EXCPT 0; */
+    { TRAMP_SENTINEL_INSN, -1 },
+  },
+  bfin_linux_sigframe_init,
+};
+
+static LONGEST
+bfin_linux_get_syscall_number (struct gdbarch *gdbarch,
+                               ptid_t ptid)
+{
+  struct regcache *regcache = get_thread_regcache (ptid);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  /* The content of a register.  */
+  gdb_byte buf[4];
+  /* The result.  */
+  LONGEST ret;
+
+  /* Getting the system call number from the register.
+     When dealing with Blackfin architecture, this information
+     is stored at %p0 register.  */
+  regcache_cooked_read (regcache, BFIN_P0_REGNUM, buf);
+
+  ret = extract_signed_integer (buf, 4, byte_order);
+
+  return ret;
+}
+
+static void
+bfin_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  linux_init_abi (info, gdbarch);
+
+  /* Set the sigtramp frame sniffer.  */
+  tramp_frame_prepend_unwinder (gdbarch, &bfin_linux_sigframe);
+
+  /* Functions for 'catch syscall'.  */
+  set_xml_syscall_file_name ("syscalls/bfin-linux.xml");
+  set_gdbarch_get_syscall_number (gdbarch,
+                                  bfin_linux_get_syscall_number);
+}
+
+/* Provide a prototype to silence -Wmissing-prototypes.  */
+extern initialize_file_ftype _initialize_bfin_linux_tdep;
+
+void
+_initialize_bfin_linux_tdep (void)
+{
+  gdbarch_register_osabi (bfd_arch_bfin, 0, GDB_OSABI_LINUX,
+                          bfin_linux_init_abi);
+}
diff --git a/gdb/bfin-tdep.c b/gdb/bfin-tdep.c
new file mode 100644 (file)
index 0000000..ddebdf9
--- /dev/null
@@ -0,0 +1,862 @@
+/* Target-dependent code for Analog Devices Blackfin processor, for GDB.
+
+   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010
+   Free Software Foundation, Inc.
+
+   Contributed by Analog Devices, 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 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   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, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "gdb_string.h"
+#include "inferior.h"
+#include "gdbcore.h"
+#include "arch-utils.h"
+#include "regcache.h"
+#include "frame.h"
+#include "frame-unwind.h"
+#include "frame-base.h"
+#include "trad-frame.h"
+#include "dis-asm.h"
+#include "gdb_assert.h"
+#include "dwarf2-frame.h"
+#include "symtab.h"
+#include "elf-bfd.h"
+#include "elf/bfin.h"
+#include "osabi.h"
+#include "infcall.h"
+#include "xml-syscall.h"
+#include "bfin-tdep.h"
+
+/* Macros used by prologue functions.  */
+#define P_LINKAGE                      0xE800
+#define P_MINUS_SP1                    0x0140
+#define P_MINUS_SP2                    0x05C0
+#define P_MINUS_SP3                    0x0540
+#define P_MINUS_SP4                    0x04C0
+#define P_SP_PLUS                      0x6C06
+#define P_P2_LOW                       0xE10A
+#define P_P2_HIGH                      0XE14A
+#define P_SP_EQ_SP_PLUS_P2             0X5BB2
+#define P_SP_EQ_P2_PLUS_SP             0x5B96
+#define P_MINUS_MINUS_SP_EQ_RETS       0x0167
+
+/* Macros used for program flow control.  */
+/* 16 bit instruction, max  */
+#define P_16_BIT_INSR_MAX              0xBFFF
+/* 32 bit instruction, min  */
+#define P_32_BIT_INSR_MIN              0xC000
+/* 32 bit instruction, max  */
+#define P_32_BIT_INSR_MAX              0xE801
+/* jump (preg), 16-bit, min  */
+#define P_JUMP_PREG_MIN                        0x0050
+/* jump (preg), 16-bit, max  */
+#define P_JUMP_PREG_MAX                        0x0057
+/* jump (pc+preg), 16-bit, min  */
+#define P_JUMP_PC_PLUS_PREG_MIN                0x0080
+/* jump (pc+preg), 16-bit, max  */
+#define P_JUMP_PC_PLUS_PREG_MAX                0x0087
+/* jump.s pcrel13m2, 16-bit, min  */
+#define P_JUMP_S_MIN                   0x2000
+/* jump.s pcrel13m2, 16-bit, max  */
+#define P_JUMP_S_MAX                   0x2FFF
+/* jump.l pcrel25m2, 32-bit, min  */
+#define P_JUMP_L_MIN                   0xE200
+/* jump.l pcrel25m2, 32-bit, max  */
+#define P_JUMP_L_MAX                   0xE2FF
+/* conditional jump pcrel11m2, 16-bit, min  */
+#define P_IF_CC_JUMP_MIN               0x1800
+/* conditional jump pcrel11m2, 16-bit, max  */
+#define P_IF_CC_JUMP_MAX               0x1BFF
+/* conditional jump(bp) pcrel11m2, 16-bit, min  */
+#define P_IF_CC_JUMP_BP_MIN            0x1C00
+/* conditional jump(bp) pcrel11m2, 16-bit, max  */
+#define P_IF_CC_JUMP_BP_MAX            0x1FFF
+/* conditional !jump pcrel11m2, 16-bit, min  */
+#define P_IF_NOT_CC_JUMP_MIN           0x1000
+/* conditional !jump pcrel11m2, 16-bit, max  */
+#define P_IF_NOT_CC_JUMP_MAX           0x13FF
+/* conditional jump(bp) pcrel11m2, 16-bit, min  */
+#define P_IF_NOT_CC_JUMP_BP_MIN                0x1400
+/* conditional jump(bp) pcrel11m2, 16-bit, max  */
+#define P_IF_NOT_CC_JUMP_BP_MAX                0x17FF
+/* call (preg), 16-bit, min  */
+#define P_CALL_PREG_MIN                        0x0060
+/* call (preg), 16-bit, max  */
+#define P_CALL_PREG_MAX                        0x0067
+/* call (pc+preg), 16-bit, min  */
+#define P_CALL_PC_PLUS_PREG_MIN                0x0070
+/* call (pc+preg), 16-bit, max  */
+#define P_CALL_PC_PLUS_PREG_MAX                0x0077
+/* call pcrel25m2, 32-bit, min  */
+#define P_CALL_MIN                     0xE300
+/* call pcrel25m2, 32-bit, max  */
+#define P_CALL_MAX                     0xE3FF
+/* RTS  */
+#define P_RTS                          0x0010
+/* MNOP  */
+#define P_MNOP                         0xC803
+/* EXCPT, 16-bit, min  */
+#define P_EXCPT_MIN                    0x00A0
+/* EXCPT, 16-bit, max  */
+#define P_EXCPT_MAX                    0x00AF
+/* multi instruction mask 1, 16-bit  */
+#define P_BIT_MULTI_INS_1              0xC000
+/* multi instruction mask 2, 16-bit  */
+#define P_BIT_MULTI_INS_2              0x0800
+
+/* The maximum bytes we search to skip the prologue.  */
+#define UPPER_LIMIT                    40
+
+/* ASTAT bits  */
+#define ASTAT_CC_POS                   5
+#define ASTAT_CC                       (1 << ASTAT_CC_POS)
+
+/* Initial value: Register names used in BFIN's ISA documentation.  */
+
+static const char * const bfin_register_name_strings[] =
+{
+  "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+  "p0", "p1", "p2", "p3", "p4", "p5", "sp", "fp",
+  "i0", "i1", "i2", "i3", "m0", "m1", "m2", "m3",
+  "b0", "b1", "b2", "b3", "l0", "l1", "l2", "l3",
+  "a0x", "a0w", "a1x", "a1w", "astat", "rets",
+  "lc0", "lt0", "lb0", "lc1", "lt1", "lb1", "cycles", "cycles2",
+  "usp", "seqstat", "syscfg", "reti", "retx", "retn", "rete",
+  "pc", "cc",
+};
+
+#define NUM_BFIN_REGNAMES ARRAY_SIZE (bfin_register_name_strings)
+
+
+/* In this diagram successive memory locations increase downwards or the
+   stack grows upwards with negative indices.  (PUSH analogy for stack.)
+
+   The top frame is the "frame" of the current function being executed.
+
+     +--------------+ SP    -
+     |  local vars  |       ^
+     +--------------+       |
+     |  save regs   |       |
+     +--------------+ FP    |
+     |   old FP    -|--    top
+     +--------------+  |  frame
+     |    RETS      |  |    |
+     +--------------+  |    |
+     |   param 1    |  |    |
+     |   param 2    |  |    |
+     |    ...       |  |    V
+     +--------------+  |    -
+     |  local vars  |  |    ^
+     +--------------+  |    |
+     |  save regs   |  |    |
+     +--------------+<-     |
+     |   old FP    -|--   next
+     +--------------+  |  frame
+     |    RETS      |  |    |
+     +--------------+  |    |
+     |   param 1    |  |    |
+     |   param 2    |  |    |
+     |    ...       |  |    V
+     +--------------+  |    -
+     |  local vars  |  |    ^
+     +--------------+  |    |
+     |  save regs   |  |    |
+     +--------------+<-  next frame
+     |   old FP     |       |
+     +--------------+       |
+     |    RETS      |       V
+     +--------------+       -
+
+   The frame chain is formed as following:
+
+     FP has the topmost frame.
+     FP + 4 has the previous FP and so on.  */
+
+
+/* Map from DWARF2 register number to GDB register number.  */
+
+static const int map_gcc_gdb[] =
+{
+  BFIN_R0_REGNUM,
+  BFIN_R1_REGNUM,
+  BFIN_R2_REGNUM,
+  BFIN_R3_REGNUM,
+  BFIN_R4_REGNUM,
+  BFIN_R5_REGNUM,
+  BFIN_R6_REGNUM,
+  BFIN_R7_REGNUM,
+  BFIN_P0_REGNUM,
+  BFIN_P1_REGNUM,
+  BFIN_P2_REGNUM,
+  BFIN_P3_REGNUM,
+  BFIN_P4_REGNUM,
+  BFIN_P5_REGNUM,
+  BFIN_SP_REGNUM,
+  BFIN_FP_REGNUM,
+  BFIN_I0_REGNUM,
+  BFIN_I1_REGNUM,
+  BFIN_I2_REGNUM,
+  BFIN_I3_REGNUM,
+  BFIN_B0_REGNUM,
+  BFIN_B1_REGNUM,
+  BFIN_B2_REGNUM,
+  BFIN_B3_REGNUM,
+  BFIN_L0_REGNUM,
+  BFIN_L1_REGNUM,
+  BFIN_L2_REGNUM,
+  BFIN_L3_REGNUM,
+  BFIN_M0_REGNUM,
+  BFIN_M1_REGNUM,
+  BFIN_M2_REGNUM,
+  BFIN_M3_REGNUM,
+  BFIN_A0_DOT_X_REGNUM,
+  BFIN_A1_DOT_X_REGNUM,
+  BFIN_CC_REGNUM,
+  BFIN_RETS_REGNUM,
+  BFIN_RETI_REGNUM,
+  BFIN_RETX_REGNUM,
+  BFIN_RETN_REGNUM,
+  BFIN_RETE_REGNUM,
+  BFIN_ASTAT_REGNUM,
+  BFIN_SEQSTAT_REGNUM,
+  BFIN_USP_REGNUM,
+  BFIN_LT0_REGNUM,
+  BFIN_LT1_REGNUM,
+  BFIN_LC0_REGNUM,
+  BFIN_LC1_REGNUM,
+  BFIN_LB0_REGNUM,
+  BFIN_LB1_REGNUM
+};
+
+
+struct bfin_frame_cache
+{
+  /* Base address.  */
+  CORE_ADDR base;
+  CORE_ADDR sp_offset;
+  CORE_ADDR pc;
+  int frameless_pc_value;
+
+  /* Saved registers.  */
+  CORE_ADDR saved_regs[BFIN_NUM_REGS];
+  CORE_ADDR saved_sp;
+
+  /* Stack space reserved for local variables.  */
+  long locals;
+};
+
+/* Allocate and initialize a frame cache.  */
+
+static struct bfin_frame_cache *
+bfin_alloc_frame_cache (void)
+{
+  struct bfin_frame_cache *cache;
+  int i;
+
+  cache = FRAME_OBSTACK_ZALLOC (struct bfin_frame_cache);
+
+  /* Base address.  */
+  cache->base = 0;
+  cache->sp_offset = -4;
+  cache->pc = 0;
+  cache->frameless_pc_value = 0;
+
+  /* Saved registers.  We initialize these to -1 since zero is a valid
+     offset (that's where fp is supposed to be stored).  */
+  for (i = 0; i < BFIN_NUM_REGS; i++)
+    cache->saved_regs[i] = -1;
+
+  /* Frameless until proven otherwise.  */
+  cache->locals = -1;
+
+  return cache;
+}
+
+static struct bfin_frame_cache *
+bfin_frame_cache (struct frame_info *this_frame, void **this_cache)
+{
+  struct bfin_frame_cache *cache;
+  int i;
+
+  if (*this_cache)
+    return *this_cache;
+
+  cache = bfin_alloc_frame_cache ();
+  *this_cache = cache;
+
+  cache->base = get_frame_register_unsigned (this_frame, BFIN_FP_REGNUM);
+  if (cache->base == 0)
+    return cache;
+
+  /* For normal frames, PC is stored at [FP + 4].  */
+  cache->saved_regs[BFIN_PC_REGNUM] = 4;
+  cache->saved_regs[BFIN_FP_REGNUM] = 0;
+
+  /* Adjust all the saved registers such that they contain addresses
+     instead of offsets.  */
+  for (i = 0; i < BFIN_NUM_REGS; i++)
+    if (cache->saved_regs[i] != -1)
+      cache->saved_regs[i] += cache->base;
+
+  cache->pc = get_frame_func (this_frame) ;
+  if (cache->pc == 0 || cache->pc == get_frame_pc (this_frame))
+    {
+      /* Either there is no prologue (frameless function) or we are at
+        the start of a function.  In short we do not have a frame.
+        PC is stored in rets register.  FP points to previous frame.  */
+
+      cache->saved_regs[BFIN_PC_REGNUM] =
+       get_frame_register_unsigned (this_frame, BFIN_RETS_REGNUM);
+      cache->frameless_pc_value = 1;
+      cache->base = get_frame_register_unsigned (this_frame, BFIN_FP_REGNUM);
+      cache->saved_regs[BFIN_FP_REGNUM] = cache->base;
+      cache->saved_sp = cache->base;
+    }
+  else
+    {
+      cache->frameless_pc_value = 0;
+
+      /* Now that we have the base address for the stack frame we can
+        calculate the value of SP in the calling frame.  */
+      cache->saved_sp = cache->base + 8;
+    }
+
+  return cache;
+}
+
+static void
+bfin_frame_this_id (struct frame_info *this_frame,
+                   void **this_cache,
+                   struct frame_id *this_id)
+{
+  struct bfin_frame_cache *cache = bfin_frame_cache (this_frame, this_cache);
+
+  /* This marks the outermost frame.  */
+  if (cache->base == 0)
+    return;
+
+  /* See the end of bfin_push_dummy_call.  */
+  *this_id = frame_id_build (cache->base + 8, cache->pc);
+}
+
+static struct value *
+bfin_frame_prev_register (struct frame_info *this_frame,
+                         void **this_cache,
+                         int regnum)
+{
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
+  struct bfin_frame_cache *cache = bfin_frame_cache (this_frame, this_cache);
+
+  if (regnum == gdbarch_sp_regnum (gdbarch) && cache->saved_sp)
+    return frame_unwind_got_constant (this_frame, regnum, cache->saved_sp);
+
+  if (regnum < BFIN_NUM_REGS && cache->saved_regs[regnum] != -1)
+    return frame_unwind_got_memory (this_frame, regnum,
+                                   cache->saved_regs[regnum]);
+
+  return frame_unwind_got_register (this_frame, regnum, regnum);
+}
+
+static const struct frame_unwind bfin_frame_unwind =
+{
+  NORMAL_FRAME,
+  bfin_frame_this_id,
+  bfin_frame_prev_register,
+  NULL,
+  default_frame_sniffer
+};
+
+/* Check for "[--SP] = <reg>;" insns.  These are appear in function
+   prologues to save misc registers onto the stack.  */
+
+static int
+is_minus_minus_sp (int op)
+{
+  op &= 0xFFC0;
+
+  if ((op == P_MINUS_SP1) || (op == P_MINUS_SP2)
+      || (op == P_MINUS_SP3) || (op == P_MINUS_SP4))
+    return 1;
+
+  return 0;
+}
+
+/* Skip all the insns that appear in generated function prologues.  */
+
+static CORE_ADDR
+bfin_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  int op = read_memory_unsigned_integer (pc, 2, byte_order);
+  CORE_ADDR orig_pc = pc;
+  int done = 0;
+
+  /* The new gcc prologue generates the register saves BEFORE the link
+     or RETS saving instruction.
+     So, our job is to stop either at those instructions or some upper
+     limit saying there is no frame!  */
+
+  while (!done)
+    {
+      if (is_minus_minus_sp (op))
+       {
+         while (is_minus_minus_sp (op))
+           {
+             pc += 2;
+             op = read_memory_unsigned_integer (pc, 2, byte_order);
+           }
+
+         if (op == P_LINKAGE)
+           pc += 4;
+
+         done = 1;
+       }
+      else if (op == P_LINKAGE)
+       {
+         pc += 4;
+         done = 1;
+       }
+      else if (op == P_MINUS_MINUS_SP_EQ_RETS)
+       {
+         pc += 2;
+         done = 1;
+       }
+      else if (op == P_RTS)
+       {
+         done = 1;
+       }
+      else if ((op >= P_JUMP_PREG_MIN && op <= P_JUMP_PREG_MAX)
+              || (op >= P_JUMP_PC_PLUS_PREG_MIN
+                  && op <= P_JUMP_PC_PLUS_PREG_MAX)
+              || (op == P_JUMP_S_MIN && op <= P_JUMP_S_MAX))
+       {
+         done = 1;
+       }
+      else if (pc - orig_pc >= UPPER_LIMIT)
+       {
+         warning (_("Function Prologue not recognised; "
+                    "pc will point to ENTRY_POINT of the function"));
+         pc = orig_pc + 2;
+         done = 1;
+       }
+      else
+       {
+         pc += 2; /* Not a terminating instruction go on.  */
+         op = read_memory_unsigned_integer (pc, 2, byte_order);
+       }
+    }
+
+   /* TODO:
+      Dwarf2 uses entry point value AFTER some register initializations.
+      We should perhaps skip such asssignments as well (R6 = R1, ...).  */
+
+  return pc;
+}
+
+/* Return the GDB type object for the "standard" data type of data in
+   register N.  This should be void pointer for P0-P5, SP, FP;
+   void pointer to function for PC; int otherwise.  */
+
+static struct type *
+bfin_register_type (struct gdbarch *gdbarch, int regnum)
+{
+  if ((regnum >= BFIN_P0_REGNUM && regnum <= BFIN_FP_REGNUM)
+      || regnum == BFIN_USP_REGNUM)
+    return builtin_type (gdbarch)->builtin_data_ptr;
+
+  if (regnum == BFIN_PC_REGNUM || regnum == BFIN_RETS_REGNUM ||
+      regnum == BFIN_RETI_REGNUM || regnum == BFIN_RETX_REGNUM ||
+      regnum == BFIN_RETN_REGNUM || regnum == BFIN_RETE_REGNUM ||
+      regnum == BFIN_LT0_REGNUM || regnum == BFIN_LB0_REGNUM ||
+      regnum == BFIN_LT1_REGNUM || regnum == BFIN_LB1_REGNUM)
+    return builtin_type (gdbarch)->builtin_func_ptr;
+
+  return builtin_type (gdbarch)->builtin_int32;
+}
+
+static CORE_ADDR
+bfin_push_dummy_call (struct gdbarch *gdbarch,
+                     struct value *function,
+                     struct regcache *regcache,
+                     CORE_ADDR bp_addr,
+                     int nargs,
+                     struct value **args,
+                     CORE_ADDR sp,
+                     int struct_return,
+                     CORE_ADDR struct_addr)
+{
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  char buf[4];
+  int i;
+  long reg_r0, reg_r1, reg_r2;
+  int total_len = 0;
+  enum bfin_abi abi = bfin_abi (gdbarch);
+  CORE_ADDR func_addr = find_function_addr (function, NULL);
+
+  for (i = nargs - 1; i >= 0; i--)
+    {
+      struct type *value_type = value_enclosing_type (args[i]);
+      int len = TYPE_LENGTH (value_type);
+
+      total_len += (len + 3) & ~3;
+    }
+
+  /* At least twelve bytes of stack space must be allocated for the function's
+     arguments, even for functions that have less than 12 bytes of argument
+     data.  */
+
+  if (total_len < 12)
+    sp -= 12 - total_len;
+
+  /* Push arguments in reverse order.  */
+
+  for (i = nargs - 1; i >= 0; i--)
+    {
+      struct type *value_type = value_enclosing_type (args[i]);
+      struct type *arg_type = check_typedef (value_type);
+      int len = TYPE_LENGTH (value_type);
+      int container_len = (len + 3) & ~3;
+
+      sp -= container_len;
+      write_memory (sp, value_contents_writeable (args[i]), container_len);
+    }
+
+  /* Initialize R0, R1, and R2 to the first 3 words of parameters.  */
+
+  reg_r0 = read_memory_integer (sp, 4, byte_order);
+  regcache_cooked_write_unsigned (regcache, BFIN_R0_REGNUM, reg_r0);
+  reg_r1 = read_memory_integer (sp + 4, 4, byte_order);
+  regcache_cooked_write_unsigned (regcache, BFIN_R1_REGNUM, reg_r1);
+  reg_r2 = read_memory_integer (sp + 8, 4, byte_order);
+  regcache_cooked_write_unsigned (regcache, BFIN_R2_REGNUM, reg_r2);
+
+  /* Store struct value address.  */
+
+  if (struct_return)
+    regcache_cooked_write_unsigned (regcache, BFIN_P0_REGNUM, struct_addr);
+
+  /* Set the dummy return value to bp_addr.
+     A dummy breakpoint will be setup to execute the call.  */
+
+  regcache_cooked_write_unsigned (regcache, BFIN_RETS_REGNUM, bp_addr);
+
+  /* Finally, update the stack pointer.  */
+
+  regcache_cooked_write_unsigned (regcache, BFIN_SP_REGNUM, sp);
+
+  return sp;
+}
+
+/* Convert DWARF2 register number REG to the appropriate register number
+   used by GDB.  */
+
+static int
+bfin_reg_to_regnum (struct gdbarch *gdbarch, int reg)
+{
+  if (reg > ARRAY_SIZE (map_gcc_gdb))
+    return 0;
+
+  return map_gcc_gdb[reg];
+}
+
+/* This function implements the BREAKPOINT_FROM_PC macro.  It returns
+   a pointer to a string of bytes that encode a breakpoint instruction,
+   stores the length of the string to *lenptr, and adjusts the program
+   counter (if necessary) to point to the actual memory location where
+   the breakpoint should be inserted.  */
+
+static const unsigned char *
+bfin_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, int *lenptr)
+{
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  unsigned short iw;
+  static unsigned char bfin_breakpoint[] = {0xa1, 0x00, 0x00, 0x00};
+  static unsigned char bfin_sim_breakpoint[] = {0x25, 0x00, 0x00, 0x00};
+
+  iw = read_memory_unsigned_integer (*pcptr, 2, byte_order);
+
+  if ((iw & 0xf000) >= 0xc000)
+    /* 32-bit instruction.  */
+    *lenptr = 4;
+  else
+    *lenptr = 2;
+
+  if (strcmp (target_shortname, "sim") == 0)
+    return bfin_sim_breakpoint;
+  else
+    return bfin_breakpoint;
+}
+
+static void
+bfin_extract_return_value (struct type *type,
+                          struct regcache *regs,
+                          gdb_byte *dst)
+{
+  struct gdbarch *gdbarch = get_regcache_arch (regs);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  bfd_byte *valbuf = dst;
+  int len = TYPE_LENGTH (type);
+  ULONGEST tmp;
+  int regno = BFIN_R0_REGNUM;
+
+  gdb_assert (len <= 8);
+
+  while (len > 0)
+    {
+      regcache_cooked_read_unsigned (regs, regno++, &tmp);
+      store_unsigned_integer (valbuf, (len > 4 ? 4 : len), tmp, byte_order);
+      len -= 4;
+      valbuf += 4;
+    }
+}
+
+/* Write into appropriate registers a function return value of type
+   TYPE, given in virtual format.  */
+
+static void
+bfin_store_return_value (struct type *type,
+                        struct regcache *regs,
+                        const gdb_byte *src)
+{
+  const bfd_byte *valbuf = src;
+
+  /* Integral values greater than one word are stored in consecutive
+     registers starting with R0.  This will always be a multiple of
+     the register size.  */
+
+  int len = TYPE_LENGTH (type);
+  int regno = BFIN_R0_REGNUM;
+
+  gdb_assert (len <= 8);
+
+  while (len > 0)
+    {
+      regcache_cooked_write (regs, regno++, valbuf);
+      len -= 4;
+      valbuf += 4;
+    }
+}
+
+/* Determine, for architecture GDBARCH, how a return value of TYPE
+   should be returned.  If it is supposed to be returned in registers,
+   and READBUF is nonzero, read the appropriate value from REGCACHE,
+   and copy it into READBUF.  If WRITEBUF is nonzero, write the value
+   from WRITEBUF into REGCACHE.  */
+
+static enum return_value_convention
+bfin_return_value (struct gdbarch *gdbarch,
+                  struct type *func_type,
+                  struct type *type,
+                  struct regcache *regcache,
+                  gdb_byte *readbuf,
+                  const gdb_byte *writebuf)
+{
+  if (TYPE_LENGTH (type) > 8)
+    return RETURN_VALUE_STRUCT_CONVENTION;
+
+  if (readbuf)
+    bfin_extract_return_value (type, regcache, readbuf);
+
+  if (writebuf)
+    bfin_store_return_value (type, regcache, writebuf);
+
+  return RETURN_VALUE_REGISTER_CONVENTION;
+}
+
+/* Return the BFIN register name corresponding to register I.  */
+
+static const char *
+bfin_register_name (struct gdbarch *gdbarch, int i)
+{
+  return bfin_register_name_strings[i];
+}
+
+static void
+bfin_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+                          int regnum, gdb_byte *buffer)
+{
+  gdb_byte *buf = (gdb_byte *) alloca (MAX_REGISTER_SIZE);
+
+  if (regnum != BFIN_CC_REGNUM)
+    internal_error (__FILE__, __LINE__,
+                   _("invalid register number %d"), regnum);
+
+  /* Extract the CC bit from the ASTAT register.  */
+  regcache_raw_read (regcache, BFIN_ASTAT_REGNUM, buf);
+  buffer[1] = buffer[2] = buffer[3] = 0;
+  buffer[0] = !!(buf[0] & ASTAT_CC);
+}
+
+static void
+bfin_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
+                           int regnum, const gdb_byte *buffer)
+{
+  gdb_byte *buf = (gdb_byte *) alloca (MAX_REGISTER_SIZE);
+
+  if (regnum != BFIN_CC_REGNUM)
+    internal_error (__FILE__, __LINE__,
+                   _("invalid register number %d"), regnum);
+
+  /* Overlay the CC bit in the ASTAT register.  */
+  regcache_raw_read (regcache, BFIN_ASTAT_REGNUM, buf);
+  buf[0] = (buf[0] & ~ASTAT_CC) | ((buffer[0] & 1) << ASTAT_CC_POS);
+  regcache_raw_write (regcache, BFIN_ASTAT_REGNUM, buf);
+}
+
+static CORE_ADDR
+bfin_frame_base_address (struct frame_info *this_frame, void **this_cache)
+{
+  struct bfin_frame_cache *cache = bfin_frame_cache (this_frame, this_cache);
+
+  return cache->base;
+}
+
+static CORE_ADDR
+bfin_frame_local_address (struct frame_info *this_frame, void **this_cache)
+{
+  struct bfin_frame_cache *cache = bfin_frame_cache (this_frame, this_cache);
+
+  return cache->base - 4;
+}
+
+static CORE_ADDR
+bfin_frame_args_address (struct frame_info *this_frame, void **this_cache)
+{
+  struct bfin_frame_cache *cache = bfin_frame_cache (this_frame, this_cache);
+
+  return cache->base + 8;
+}
+
+static const struct frame_base bfin_frame_base =
+{
+  &bfin_frame_unwind,
+  bfin_frame_base_address,
+  bfin_frame_local_address,
+  bfin_frame_args_address
+};
+
+static struct frame_id
+bfin_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
+{
+  CORE_ADDR sp;
+
+  sp = get_frame_register_unsigned (this_frame, BFIN_SP_REGNUM);
+
+  return frame_id_build (sp, get_frame_pc (this_frame));
+}
+
+static CORE_ADDR
+bfin_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
+{
+  return frame_unwind_register_unsigned (next_frame, BFIN_PC_REGNUM);
+}
+
+static CORE_ADDR
+bfin_frame_align (struct gdbarch *gdbarch, CORE_ADDR address)
+{
+  return (address & ~0x3);
+}
+
+enum bfin_abi
+bfin_abi (struct gdbarch *gdbarch)
+{
+  return gdbarch_tdep (gdbarch)->bfin_abi;
+}
+
+/* Initialize the current architecture based on INFO.  If possible,
+   re-use an architecture from ARCHES, which is a list of
+   architectures already created during this debugging session.
+
+   Called e.g. at program startup, when reading a core file, and when
+   reading a binary file.  */
+
+static struct gdbarch *
+bfin_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
+{
+  struct gdbarch_tdep *tdep;
+  struct gdbarch *gdbarch;
+  int elf_flags;
+  enum bfin_abi abi;
+
+  /* Extract the ELF flags, if available.  */
+  if (info.abfd && bfd_get_flavour (info.abfd) == bfd_target_elf_flavour)
+    elf_flags = elf_elfheader (info.abfd)->e_flags;
+  else
+    elf_flags = 0;
+
+  abi = BFIN_ABI_FLAT;
+
+  /* If there is already a candidate, use it.  */
+
+  for (arches = gdbarch_list_lookup_by_info (arches, &info);
+       arches != NULL;
+       arches = gdbarch_list_lookup_by_info (arches->next, &info))
+    {
+      if (gdbarch_tdep (arches->gdbarch)->bfin_abi != abi)
+       continue;
+      return arches->gdbarch;
+    }
+
+  tdep = XMALLOC (struct gdbarch_tdep);
+  gdbarch = gdbarch_alloc (&info, tdep);
+
+  tdep->bfin_abi = abi;
+
+  set_gdbarch_num_regs (gdbarch, BFIN_NUM_REGS);
+  set_gdbarch_pseudo_register_read (gdbarch, bfin_pseudo_register_read);
+  set_gdbarch_pseudo_register_write (gdbarch, bfin_pseudo_register_write);
+  set_gdbarch_num_pseudo_regs (gdbarch, BFIN_NUM_PSEUDO_REGS);
+  set_gdbarch_sp_regnum (gdbarch, BFIN_SP_REGNUM);
+  set_gdbarch_pc_regnum (gdbarch, BFIN_PC_REGNUM);
+  set_gdbarch_ps_regnum (gdbarch, BFIN_ASTAT_REGNUM);
+  set_gdbarch_dwarf2_reg_to_regnum (gdbarch, bfin_reg_to_regnum);
+  set_gdbarch_register_name (gdbarch, bfin_register_name);
+  set_gdbarch_register_type (gdbarch, bfin_register_type);
+  set_gdbarch_dummy_id (gdbarch, bfin_dummy_id);
+  set_gdbarch_push_dummy_call (gdbarch, bfin_push_dummy_call);
+  set_gdbarch_believe_pcc_promotion (gdbarch, 1);
+  set_gdbarch_return_value (gdbarch, bfin_return_value);
+  set_gdbarch_skip_prologue (gdbarch, bfin_skip_prologue);
+  set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
+  set_gdbarch_breakpoint_from_pc (gdbarch, bfin_breakpoint_from_pc);
+  set_gdbarch_decr_pc_after_break (gdbarch, 2);
+  set_gdbarch_frame_args_skip (gdbarch, 8);
+  set_gdbarch_unwind_pc (gdbarch, bfin_unwind_pc);
+  set_gdbarch_frame_align (gdbarch, bfin_frame_align);
+  set_gdbarch_print_insn (gdbarch, print_insn_bfin);
+
+  /* Hook in ABI-specific overrides, if they have been registered.  */
+  gdbarch_init_osabi (info, gdbarch);
+
+  dwarf2_append_unwinders (gdbarch);
+
+  frame_base_set_default (gdbarch, &bfin_frame_base);
+
+  frame_unwind_append_unwinder (gdbarch, &bfin_frame_unwind);
+
+  return gdbarch;
+}
+
+/* Provide a prototype to silence -Wmissing-prototypes.  */
+extern initialize_file_ftype _initialize_bfin_tdep;
+
+void
+_initialize_bfin_tdep (void)
+{
+  register_gdbarch_init (bfd_arch_bfin, bfin_gdbarch_init);
+}
diff --git a/gdb/bfin-tdep.h b/gdb/bfin-tdep.h
new file mode 100644 (file)
index 0000000..ecc46d2
--- /dev/null
@@ -0,0 +1,102 @@
+/* Target-dependent code for Analog Devices Blackfin processor, for GDB.
+
+   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010
+   Free Software Foundation, Inc.
+
+   Contributed by Analog Devices, 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 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   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, see <http://www.gnu.org/licenses/>.  */
+
+enum gdb_regnum {
+  /* Core Registers */
+  BFIN_R0_REGNUM = 0,
+  BFIN_R1_REGNUM,
+  BFIN_R2_REGNUM,
+  BFIN_R3_REGNUM,
+  BFIN_R4_REGNUM,
+  BFIN_R5_REGNUM,
+  BFIN_R6_REGNUM,
+  BFIN_R7_REGNUM,
+  BFIN_P0_REGNUM,
+  BFIN_P1_REGNUM,
+  BFIN_P2_REGNUM,
+  BFIN_P3_REGNUM,
+  BFIN_P4_REGNUM,
+  BFIN_P5_REGNUM,
+  BFIN_SP_REGNUM,
+  BFIN_FP_REGNUM,
+  BFIN_I0_REGNUM,
+  BFIN_I1_REGNUM,
+  BFIN_I2_REGNUM,
+  BFIN_I3_REGNUM,
+  BFIN_M0_REGNUM,
+  BFIN_M1_REGNUM,
+  BFIN_M2_REGNUM,
+  BFIN_M3_REGNUM,
+  BFIN_B0_REGNUM,
+  BFIN_B1_REGNUM,
+  BFIN_B2_REGNUM,
+  BFIN_B3_REGNUM,
+  BFIN_L0_REGNUM,
+  BFIN_L1_REGNUM,
+  BFIN_L2_REGNUM,
+  BFIN_L3_REGNUM,
+  BFIN_A0_DOT_X_REGNUM,
+  BFIN_AO_DOT_W_REGNUM,
+  BFIN_A1_DOT_X_REGNUM,
+  BFIN_A1_DOT_W_REGNUM,
+  BFIN_ASTAT_REGNUM,
+  BFIN_RETS_REGNUM,
+  BFIN_LC0_REGNUM,
+  BFIN_LT0_REGNUM,
+  BFIN_LB0_REGNUM,
+  BFIN_LC1_REGNUM,
+  BFIN_LT1_REGNUM,
+  BFIN_LB1_REGNUM,
+  BFIN_CYCLES_REGNUM,
+  BFIN_CYCLES2_REGNUM,
+  BFIN_USP_REGNUM,
+  BFIN_SEQSTAT_REGNUM,
+  BFIN_SYSCFG_REGNUM,
+  BFIN_RETI_REGNUM,
+  BFIN_RETX_REGNUM,
+  BFIN_RETN_REGNUM,
+  BFIN_RETE_REGNUM,
+
+  /* Pseudo Registers managed remotely.  */
+  BFIN_PC_REGNUM,
+
+  /* Pseudo Registers managed locally.  */
+  BFIN_CC_REGNUM
+};
+#define BFIN_NUM_REGS (BFIN_PC_REGNUM + 1)
+#define BFIN_NUM_PSEUDO_REGS (1)
+
+/* The ABIs for Blackfin.  */
+enum bfin_abi
+{
+  BFIN_ABI_FLAT
+};
+
+/* Target-dependent structure in gdbarch.  */
+struct gdbarch_tdep
+{
+  /* Which ABI is in use?  */
+  enum bfin_abi bfin_abi;
+};
+
+/* Return the Blackfin ABI associated with GDBARCH.  */
+extern enum bfin_abi bfin_abi (struct gdbarch *gdbarch);
index 161cbdcadfb6ed8e946c9f177a1d35750e518b3c..ef9b7831503710c68480799e97f2d2647c732d03 100644 (file)
@@ -106,6 +106,15 @@ avr-*-*)
        gdb_sim=../sim/avr/libsim.a
        ;;
 
+bfin-*-*linux*)
+       # Target: Blackfin Linux
+       gdb_target_obs="bfin-tdep.o bfin-linux-tdep.o linux-tdep.o"
+       ;;
+bfin-*-*)
+       # Target: Blackfin processor
+       gdb_target_obs="bfin-tdep.o"
+       ;;
+
 cris*)
        # Target: CRIS
        gdb_target_obs="cris-tdep.o corelow.o solib.o solib-svr4.o"
diff --git a/gdb/syscalls/bfin-linux.xml b/gdb/syscalls/bfin-linux.xml
new file mode 100644 (file)
index 0000000..0fd3a96
--- /dev/null
@@ -0,0 +1,326 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2010 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE feature SYSTEM "gdb-syscalls.dtd">
+
+<!-- This file was generated using the following file:
+
+     gawk '$2 ~ /^__NR_/ { gsub(/__NR_/,""); print "  <syscall name=\"" $2 "\" number=\"" $3 "\"/>" }'
+     /usr/src/linux/arch/blackfin/include/asm/unistd.h
+
+     The file mentioned above belongs to the Linux Kernel.  -->
+
+<syscalls_info>
+  <syscall name="restart_syscall" number="0"/>
+  <syscall name="exit" number="1"/>
+  <syscall name="fork" number="2"/>
+  <syscall name="read" number="3"/>
+  <syscall name="write" number="4"/>
+  <syscall name="open" number="5"/>
+  <syscall name="close" number="6"/>
+  <syscall name="creat" number="8"/>
+  <syscall name="link" number="9"/>
+  <syscall name="unlink" number="10"/>
+  <syscall name="execve" number="11"/>
+  <syscall name="chdir" number="12"/>
+  <syscall name="time" number="13"/>
+  <syscall name="mknod" number="14"/>
+  <syscall name="chmod" number="15"/>
+  <syscall name="chown" number="16"/>
+  <syscall name="lseek" number="19"/>
+  <syscall name="getpid" number="20"/>
+  <syscall name="mount" number="21"/>
+  <syscall name="setuid" number="23"/>
+  <syscall name="getuid" number="24"/>
+  <syscall name="stime" number="25"/>
+  <syscall name="ptrace" number="26"/>
+  <syscall name="alarm" number="27"/>
+  <syscall name="pause" number="29"/>
+  <syscall name="access" number="33"/>
+  <syscall name="nice" number="34"/>
+  <syscall name="sync" number="36"/>
+  <syscall name="kill" number="37"/>
+  <syscall name="rename" number="38"/>
+  <syscall name="mkdir" number="39"/>
+  <syscall name="rmdir" number="40"/>
+  <syscall name="dup" number="41"/>
+  <syscall name="pipe" number="42"/>
+  <syscall name="times" number="43"/>
+  <syscall name="brk" number="45"/>
+  <syscall name="setgid" number="46"/>
+  <syscall name="getgid" number="47"/>
+  <syscall name="geteuid" number="49"/>
+  <syscall name="getegid" number="50"/>
+  <syscall name="acct" number="51"/>
+  <syscall name="umount2" number="52"/>
+  <syscall name="ioctl" number="54"/>
+  <syscall name="fcntl" number="55"/>
+  <syscall name="setpgid" number="57"/>
+  <syscall name="umask" number="60"/>
+  <syscall name="chroot" number="61"/>
+  <syscall name="ustat" number="62"/>
+  <syscall name="dup2" number="63"/>
+  <syscall name="getppid" number="64"/>
+  <syscall name="getpgrp" number="65"/>
+  <syscall name="setsid" number="66"/>
+  <syscall name="sgetmask" number="68"/>
+  <syscall name="ssetmask" number="69"/>
+  <syscall name="setreuid" number="70"/>
+  <syscall name="setregid" number="71"/>
+  <syscall name="sethostname" number="74"/>
+  <syscall name="setrlimit" number="75"/>
+  <syscall name="getrusage" number="77"/>
+  <syscall name="gettimeofday" number="78"/>
+  <syscall name="settimeofday" number="79"/>
+  <syscall name="getgroups" number="80"/>
+  <syscall name="setgroups" number="81"/>
+  <syscall name="symlink" number="83"/>
+  <syscall name="readlink" number="85"/>
+  <syscall name="reboot" number="88"/>
+  <syscall name="munmap" number="91"/>
+  <syscall name="truncate" number="92"/>
+  <syscall name="ftruncate" number="93"/>
+  <syscall name="fchmod" number="94"/>
+  <syscall name="fchown" number="95"/>
+  <syscall name="getpriority" number="96"/>
+  <syscall name="setpriority" number="97"/>
+  <syscall name="statfs" number="99"/>
+  <syscall name="fstatfs" number="100"/>
+  <syscall name="syslog" number="103"/>
+  <syscall name="setitimer" number="104"/>
+  <syscall name="getitimer" number="105"/>
+  <syscall name="stat" number="106"/>
+  <syscall name="lstat" number="107"/>
+  <syscall name="fstat" number="108"/>
+  <syscall name="vhangup" number="111"/>
+  <syscall name="wait4" number="114"/>
+  <syscall name="sysinfo" number="116"/>
+  <syscall name="fsync" number="118"/>
+  <syscall name="clone" number="120"/>
+  <syscall name="setdomainname" number="121"/>
+  <syscall name="uname" number="122"/>
+  <syscall name="adjtimex" number="124"/>
+  <syscall name="mprotect" number="125"/>
+  <syscall name="init_module" number="128"/>
+  <syscall name="delete_module" number="129"/>
+  <syscall name="quotactl" number="131"/>
+  <syscall name="getpgid" number="132"/>
+  <syscall name="fchdir" number="133"/>
+  <syscall name="bdflush" number="134"/>
+  <syscall name="personality" number="136"/>
+  <syscall name="setfsuid" number="138"/>
+  <syscall name="setfsgid" number="139"/>
+  <syscall name="_llseek" number="140"/>
+  <syscall name="getdents" number="141"/>
+  <syscall name="flock" number="143"/>
+  <syscall name="readv" number="145"/>
+  <syscall name="writev" number="146"/>
+  <syscall name="getsid" number="147"/>
+  <syscall name="fdatasync" number="148"/>
+  <syscall name="_sysctl" number="149"/>
+  <syscall name="sched_setparam" number="154"/>
+  <syscall name="sched_getparam" number="155"/>
+  <syscall name="sched_setscheduler" number="156"/>
+  <syscall name="sched_getscheduler" number="157"/>
+  <syscall name="sched_yield" number="158"/>
+  <syscall name="sched_get_priority_max" number="159"/>
+  <syscall name="sched_get_priority_min" number="160"/>
+  <syscall name="sched_rr_get_interval" number="161"/>
+  <syscall name="nanosleep" number="162"/>
+  <syscall name="mremap" number="163"/>
+  <syscall name="setresuid" number="164"/>
+  <syscall name="getresuid" number="165"/>
+  <syscall name="nfsservctl" number="169"/>
+  <syscall name="setresgid" number="170"/>
+  <syscall name="getresgid" number="171"/>
+  <syscall name="prctl" number="172"/>
+  <syscall name="rt_sigreturn" number="173"/>
+  <syscall name="rt_sigaction" number="174"/>
+  <syscall name="rt_sigprocmask" number="175"/>
+  <syscall name="rt_sigpending" number="176"/>
+  <syscall name="rt_sigtimedwait" number="177"/>
+  <syscall name="rt_sigqueueinfo" number="178"/>
+  <syscall name="rt_sigsuspend" number="179"/>
+  <syscall name="pread" number="180"/>
+  <syscall name="pwrite" number="181"/>
+  <syscall name="lchown" number="182"/>
+  <syscall name="getcwd" number="183"/>
+  <syscall name="capget" number="184"/>
+  <syscall name="capset" number="185"/>
+  <syscall name="sigaltstack" number="186"/>
+  <syscall name="sendfile" number="187"/>
+  <syscall name="vfork" number="190"/>
+  <syscall name="getrlimit" number="191"/>
+  <syscall name="mmap2" number="192"/>
+  <syscall name="truncate64" number="193"/>
+  <syscall name="ftruncate64" number="194"/>
+  <syscall name="stat64" number="195"/>
+  <syscall name="lstat64" number="196"/>
+  <syscall name="fstat64" number="197"/>
+  <syscall name="chown32" number="198"/>
+  <syscall name="getuid32" number="199"/>
+  <syscall name="getgid32" number="200"/>
+  <syscall name="geteuid32" number="201"/>
+  <syscall name="getegid32" number="202"/>
+  <syscall name="setreuid32" number="203"/>
+  <syscall name="setregid32" number="204"/>
+  <syscall name="getgroups32" number="205"/>
+  <syscall name="setgroups32" number="206"/>
+  <syscall name="fchown32" number="207"/>
+  <syscall name="setresuid32" number="208"/>
+  <syscall name="getresuid32" number="209"/>
+  <syscall name="setresgid32" number="210"/>
+  <syscall name="getresgid32" number="211"/>
+  <syscall name="lchown32" number="212"/>
+  <syscall name="setuid32" number="213"/>
+  <syscall name="setgid32" number="214"/>
+  <syscall name="setfsuid32" number="215"/>
+  <syscall name="setfsgid32" number="216"/>
+  <syscall name="pivot_root" number="217"/>
+  <syscall name="getdents64" number="220"/>
+  <syscall name="fcntl64" number="221"/>
+  <syscall name="gettid" number="224"/>
+  <syscall name="readahead" number="225"/>
+  <syscall name="setxattr" number="226"/>
+  <syscall name="lsetxattr" number="227"/>
+  <syscall name="fsetxattr" number="228"/>
+  <syscall name="getxattr" number="229"/>
+  <syscall name="lgetxattr" number="230"/>
+  <syscall name="fgetxattr" number="231"/>
+  <syscall name="listxattr" number="232"/>
+  <syscall name="llistxattr" number="233"/>
+  <syscall name="flistxattr" number="234"/>
+  <syscall name="removexattr" number="235"/>
+  <syscall name="lremovexattr" number="236"/>
+  <syscall name="fremovexattr" number="237"/>
+  <syscall name="tkill" number="238"/>
+  <syscall name="sendfile64" number="239"/>
+  <syscall name="futex" number="240"/>
+  <syscall name="sched_setaffinity" number="241"/>
+  <syscall name="sched_getaffinity" number="242"/>
+  <syscall name="io_setup" number="245"/>
+  <syscall name="io_destroy" number="246"/>
+  <syscall name="io_getevents" number="247"/>
+  <syscall name="io_submit" number="248"/>
+  <syscall name="io_cancel" number="249"/>
+  <syscall name="exit_group" number="252"/>
+  <syscall name="lookup_dcookie" number="253"/>
+  <syscall name="bfin_spinlock" number="254"/>
+  <syscall name="epoll_create" number="255"/>
+  <syscall name="epoll_ctl" number="256"/>
+  <syscall name="epoll_wait" number="257"/>
+  <syscall name="set_tid_address" number="259"/>
+  <syscall name="timer_create" number="260"/>
+  <syscall name="timer_settime" number="261"/>
+  <syscall name="timer_gettime" number="262"/>
+  <syscall name="timer_getoverrun" number="263"/>
+  <syscall name="timer_delete" number="264"/>
+  <syscall name="clock_settime" number="265"/>
+  <syscall name="clock_gettime" number="266"/>
+  <syscall name="clock_getres" number="267"/>
+  <syscall name="clock_nanosleep" number="268"/>
+  <syscall name="statfs64" number="269"/>
+  <syscall name="fstatfs64" number="270"/>
+  <syscall name="tgkill" number="271"/>
+  <syscall name="utimes" number="272"/>
+  <syscall name="fadvise64_64" number="273"/>
+  <syscall name="mq_open" number="278"/>
+  <syscall name="mq_unlink" number="279"/>
+  <syscall name="mq_timedsend" number="280"/>
+  <syscall name="mq_timedreceive" number="281"/>
+  <syscall name="mq_notify" number="282"/>
+  <syscall name="mq_getsetattr" number="283"/>
+  <syscall name="kexec_load" number="284"/>
+  <syscall name="waitid" number="285"/>
+  <syscall name="add_key" number="286"/>
+  <syscall name="request_key" number="287"/>
+  <syscall name="keyctl" number="288"/>
+  <syscall name="ioprio_set" number="289"/>
+  <syscall name="ioprio_get" number="290"/>
+  <syscall name="inotify_init" number="291"/>
+  <syscall name="inotify_add_watch" number="292"/>
+  <syscall name="inotify_rm_watch" number="293"/>
+  <syscall name="openat" number="295"/>
+  <syscall name="mkdirat" number="296"/>
+  <syscall name="mknodat" number="297"/>
+  <syscall name="fchownat" number="298"/>
+  <syscall name="futimesat" number="299"/>
+  <syscall name="fstatat64" number="300"/>
+  <syscall name="unlinkat" number="301"/>
+  <syscall name="renameat" number="302"/>
+  <syscall name="linkat" number="303"/>
+  <syscall name="symlinkat" number="304"/>
+  <syscall name="readlinkat" number="305"/>
+  <syscall name="fchmodat" number="306"/>
+  <syscall name="faccessat" number="307"/>
+  <syscall name="pselect6" number="308"/>
+  <syscall name="ppoll" number="309"/>
+  <syscall name="unshare" number="310"/>
+  <syscall name="sram_alloc" number="311"/>
+  <syscall name="sram_free" number="312"/>
+  <syscall name="dma_memcpy" number="313"/>
+  <syscall name="accept" number="314"/>
+  <syscall name="bind" number="315"/>
+  <syscall name="connect" number="316"/>
+  <syscall name="getpeername" number="317"/>
+  <syscall name="getsockname" number="318"/>
+  <syscall name="getsockopt" number="319"/>
+  <syscall name="listen" number="320"/>
+  <syscall name="recv" number="321"/>
+  <syscall name="recvfrom" number="322"/>
+  <syscall name="recvmsg" number="323"/>
+  <syscall name="send" number="324"/>
+  <syscall name="sendmsg" number="325"/>
+  <syscall name="sendto" number="326"/>
+  <syscall name="setsockopt" number="327"/>
+  <syscall name="shutdown" number="328"/>
+  <syscall name="socket" number="329"/>
+  <syscall name="socketpair" number="330"/>
+  <syscall name="semctl" number="331"/>
+  <syscall name="semget" number="332"/>
+  <syscall name="semop" number="333"/>
+  <syscall name="msgctl" number="334"/>
+  <syscall name="msgget" number="335"/>
+  <syscall name="msgrcv" number="336"/>
+  <syscall name="msgsnd" number="337"/>
+  <syscall name="shmat" number="338"/>
+  <syscall name="shmctl" number="339"/>
+  <syscall name="shmdt" number="340"/>
+  <syscall name="shmget" number="341"/>
+  <syscall name="splice" number="342"/>
+  <syscall name="sync_file_range" number="343"/>
+  <syscall name="tee" number="344"/>
+  <syscall name="vmsplice" number="345"/>
+  <syscall name="epoll_pwait" number="346"/>
+  <syscall name="utimensat" number="347"/>
+  <syscall name="signalfd" number="348"/>
+  <syscall name="timerfd_create" number="349"/>
+  <syscall name="eventfd" number="350"/>
+  <syscall name="pread64" number="351"/>
+  <syscall name="pwrite64" number="352"/>
+  <syscall name="fadvise64" number="353"/>
+  <syscall name="set_robust_list" number="354"/>
+  <syscall name="get_robust_list" number="355"/>
+  <syscall name="fallocate" number="356"/>
+  <syscall name="semtimedop" number="357"/>
+  <syscall name="timerfd_settime" number="358"/>
+  <syscall name="timerfd_gettime" number="359"/>
+  <syscall name="signalfd4" number="360"/>
+  <syscall name="eventfd2" number="361"/>
+  <syscall name="epoll_create1" number="362"/>
+  <syscall name="dup3" number="363"/>
+  <syscall name="pipe2" number="364"/>
+  <syscall name="inotify_init1" number="365"/>
+  <syscall name="preadv" number="366"/>
+  <syscall name="pwritev" number="367"/>
+  <syscall name="rt_tgsigqueueinfo" number="368"/>
+  <syscall name="perf_event_open" number="369"/>
+  <syscall name="recvmmsg" number="370"/>
+  <syscall name="fanotify_init" number="371"/>
+  <syscall name="fanotify_mark" number="372"/>
+  <syscall name="prlimit64" number="373"/>
+</syscalls_info>