* [PATCH 2/2] gdb: gdbserver: bfin: new port
2010-11-16 0:34 [PATCH 1/2] gdb: bfin: new port Mike Frysinger
@ 2010-11-16 0:34 ` Mike Frysinger
2010-12-08 21:38 ` Joel Brobecker
2010-11-21 21:29 ` [PATCH 1/2] gdb: " Mike Frysinger
2010-12-08 21:25 ` Joel Brobecker
2 siblings, 1 reply; 9+ messages in thread
From: Mike Frysinger @ 2010-11-16 0:34 UTC (permalink / raw)
To: gdb-patches; +Cc: Jie Zhang
From: Jie Zhang <jie.zhang@analog.com>
Signed-off-by: Jie Zhang <jie.zhang@analog.com>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
gdb/:
2010-11-16 Jie Zhang <jie.zhang@analog.com>
* configure.tgt (bfin-*-*): Set build_gdbserver to yes.
* NEWS: Mention new Blackfin support.
* regformats/reg-bfin.dat: New file.
gdbserver/:
2010-11-16 Jie Zhang <jie.zhang@analog.com>
* configure.srv (bfin-*-*): Handle bfin targets.
* linux-bfin-low.c: New file.
* linux-low.c: Define PT_TEXT_ADDR, PT_TEXT_END_ADDR, and
PT_DATA_ADDR for BFIN targets.
* Makefile.in (SFILES): Add linux-bfin-low.c.
(clean): Remove reg-bfin.c.
(linux-bfin-low.o, reg-bfin.o, reg-bfin.c): New targets.
* README: Mention supported Blackfin targets.
---
gdb/NEWS | 2 +
gdb/configure.tgt | 1 +
gdb/gdbserver/Makefile.in | 10 +++-
gdb/gdbserver/README | 2 +
gdb/gdbserver/configure.srv | 5 ++
gdb/gdbserver/linux-bfin-low.c | 103 ++++++++++++++++++++++++++++++++++++++++
gdb/gdbserver/linux-low.c | 4 ++
gdb/regformats/reg-bfin.dat | 63 ++++++++++++++++++++++++
8 files changed, 187 insertions(+), 3 deletions(-)
create mode 100644 gdb/gdbserver/linux-bfin-low.c
create mode 100644 gdb/regformats/reg-bfin.dat
diff --git a/gdb/NEWS b/gdb/NEWS
index dcf6025..69bd1b5 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -90,6 +90,8 @@
** GDBserver is now supported on PowerPC LynxOS (versions 4.x and 5.x),
and i686 LynxOS (version 5.x).
+ ** GDBserver is now supported on Blackfin Linux.
+
* New targets:
Analog Devices, Inc. Blackfin Processor bfin-*
diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index c6c31e3..9997ec4 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -109,6 +109,7 @@ avr-*-*)
bfin-*-*)
# Target: Blackfin
gdb_target_obs="bfin-tdep.o"
+ build_gdbserver=yes
;;
cris*)
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index 7cf68da..44187eb 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -111,8 +111,8 @@ SFILES= $(srcdir)/gdbreplay.c $(srcdir)/inferiors.c \
$(srcdir)/proc-service.list $(srcdir)/regcache.c \
$(srcdir)/remote-utils.c $(srcdir)/server.c $(srcdir)/target.c \
$(srcdir)/thread-db.c $(srcdir)/utils.c \
- $(srcdir)/linux-arm-low.c $(srcdir)/linux-cris-low.c \
- $(srcdir)/linux-crisv32-low.c \
+ $(srcdir)/linux-arm-low.c $(srcdir)/linux-bfin-low.c \
+ $(srcdir)/linux-cris-low.c $(srcdir)/linux-crisv32-low.c \
${srcdir}/i386-low.c $(srcdir)/i387-fp.c \
$(srcdir)/linux-ia64-low.c $(srcdir)/linux-low.c \
$(srcdir)/linux-m32r-low.c \
@@ -263,7 +263,7 @@ clean:
rm -f version.c
rm -f gdbserver$(EXEEXT) gdbreplay$(EXEEXT) core make.log
rm -f $(IPA_LIB)
- rm -f reg-arm.c i386.c reg-ia64.c reg-m32r.c reg-m68k.c
+ rm -f reg-arm.c reg-bfin.c i386.c reg-ia64.c reg-m32r.c reg-m68k.c
rm -f reg-sh.c reg-sparc.c reg-spu.c amd64.c i386-linux.c
rm -f reg-cris.c reg-crisv32.c amd64-linux.c reg-xtensa.c
rm -f arm-with-iwmmxt.c
@@ -413,6 +413,7 @@ linux-low.o: linux-low.c $(linux_low_h) $(server_h)
linux-arm-low.o: linux-arm-low.c $(linux_low_h) $(server_h) \
$(gdb_proc_service_h)
+linux-bfin-low.o: linux-bfin-low.c $(linux_low_h) $(server_h)
linux-cris-low.o: linux-cris-low.c $(linux_low_h) $(server_h)
linux-crisv32-low.o: linux-crisv32-low.c $(linux_low_h) $(server_h)
linux-ia64-low.o: linux-ia64-low.c $(linux_low_h) $(server_h)
@@ -455,6 +456,9 @@ arm-with-vfpv3.c : $(srcdir)/../regformats/arm-with-vfpv3.dat $(regdat_sh)
arm-with-neon.o : arm-with-neon.c $(regdef_h)
arm-with-neon.c : $(srcdir)/../regformats/arm-with-neon.dat $(regdat_sh)
$(SHELL) $(regdat_sh) $(srcdir)/../regformats/arm-with-neon.dat arm-with-neon.c
+reg-bfin.o : reg-bfin.c $(regdef_h)
+reg-bfin.c : $(srcdir)/../regformats/reg-bfin.dat $(regdat_sh)
+ $(SHELL) $(regdat_sh) $(srcdir)/../regformats/reg-bfin.dat reg-bfin.c
reg-cris.o : reg-cris.c $(regdef_h)
reg-cris.c : $(srcdir)/../regformats/reg-cris.dat $(regdat_sh)
$(SHELL) $(regdat_sh) $(srcdir)/../regformats/reg-cris.dat reg-cris.c
diff --git a/gdb/gdbserver/README b/gdb/gdbserver/README
index 6debbd8..3eaeb61 100644
--- a/gdb/gdbserver/README
+++ b/gdb/gdbserver/README
@@ -81,6 +81,8 @@ Building GDBserver:
The supported targets as of November 2006 are:
arm-*-linux*
+ bfin-*-uclinux
+ bfin-*-linux-uclibc
crisv32-*-linux*
cris-*-linux*
i[34567]86-*-cygwin*
diff --git a/gdb/gdbserver/configure.srv b/gdb/gdbserver/configure.srv
index 1e8fa30..ccf8381 100644
--- a/gdb/gdbserver/configure.srv
+++ b/gdb/gdbserver/configure.srv
@@ -67,6 +67,11 @@ case "${target}" in
srv_mingw=yes
srv_mingwce=yes
;;
+ bfin-*-*) srv_regobj=reg-bfin.o
+ srv_tgtobj="linux-low.o linux-bfin-low.o"
+ srv_linux_usrregs=yes
+ srv_linux_thread_db=yes
+ ;;
crisv32-*-linux*) srv_regobj=reg-crisv32.o
srv_tgtobj="linux-low.o linux-crisv32-low.o"
srv_linux_regsets=yes
diff --git a/gdb/gdbserver/linux-bfin-low.c b/gdb/gdbserver/linux-bfin-low.c
new file mode 100644
index 0000000..9ef22ea
--- /dev/null
+++ b/gdb/gdbserver/linux-bfin-low.c
@@ -0,0 +1,103 @@
+/* GNU/Linux/BFIN specific low level interface, for the remote server for GDB.
+
+ Copyright (C) 2005, 2006, 2007, 2009, 2010 Free Software Foundation, Inc.
+ Contributed by Analog Devices.
+
+ 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 "server.h"
+#include "linux-low.h"
+#include <asm/ptrace.h>
+
+/* Defined in auto-generated file reg-bfin.c. */
+void init_registers_bfin (void);
+
+static int bfin_regmap[] =
+{
+ PT_R0, PT_R1, PT_R2, PT_R3, PT_R4, PT_R5, PT_R6, PT_R7,
+ PT_P0, PT_P1, PT_P2, PT_P3, PT_P4, PT_P5, PT_USP, PT_FP,
+ PT_I0, PT_I1, PT_I2, PT_I3, PT_M0, PT_M1, PT_M2, PT_M3,
+ PT_B0, PT_B1, PT_B2, PT_B3, PT_L0, PT_L1, PT_L2, PT_L3,
+ PT_A0X, PT_A0W, PT_A1X, PT_A1W, PT_ASTAT, PT_RETS,
+ PT_LC0, PT_LT0, PT_LB0, PT_LC1, PT_LT1, PT_LB1,
+ -1 /* PT_CYCLES */, -1 /* PT_CYCLES2 */,
+ -1 /* PT_USP */, PT_SEQSTAT, PT_SYSCFG, PT_PC, PT_RETX, PT_RETN, PT_RETE,
+ PT_PC, -1 /* PT_CC */, PT_TEXT_ADDR, PT_TEXT_END_ADDR, PT_DATA_ADDR,
+ PT_FDPIC_EXEC, PT_FDPIC_INTERP,
+ PT_IPEND
+};
+
+#define bfin_num_regs (sizeof(bfin_regmap) / sizeof(bfin_regmap[0]))
+
+static int
+bfin_cannot_store_register (int regno)
+{
+ return (regno >= bfin_num_regs);
+}
+
+static int
+bfin_cannot_fetch_register (int regno)
+{
+ return (regno >= bfin_num_regs);
+}
+
+static CORE_ADDR
+bfin_get_pc (struct regcache *regcache)
+{
+ unsigned long pc;
+ collect_register_by_name (regcache, "pc", &pc);
+ return pc;
+}
+
+static void
+bfin_set_pc (struct regcache *regcache, CORE_ADDR pc)
+{
+ unsigned long newpc = pc;
+ supply_register_by_name (regcache, "pc", &newpc);
+}
+
+#define bfin_breakpoint_len 2
+static const unsigned char bfin_breakpoint[bfin_breakpoint_len]={0xa1, 0x00};
+
+static int
+bfin_breakpoint_at (CORE_ADDR where)
+{
+ unsigned char insn[bfin_breakpoint_len];
+
+ read_inferior_memory(where, insn, bfin_breakpoint_len);
+ if (insn[0] == bfin_breakpoint[0]
+ && insn[1] == bfin_breakpoint[1])
+ return 1;
+
+ /* If necessary, recognize more trap instructions here. GDB only uses the
+ one. */
+ return 0;
+}
+
+struct linux_target_ops the_low_target = {
+ init_registers_bfin,
+ bfin_num_regs,
+ bfin_regmap,
+ bfin_cannot_fetch_register,
+ bfin_cannot_store_register,
+ bfin_get_pc,
+ bfin_set_pc,
+ bfin_breakpoint,
+ bfin_breakpoint_len,
+ 0,
+ 2,
+ bfin_breakpoint_at,
+};
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index b798c16..7c50251 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -4373,6 +4373,10 @@ linux_stopped_data_address (void)
#define PT_TEXT_ADDR 49*4
#define PT_DATA_ADDR 50*4
#define PT_TEXT_END_ADDR 51*4
+#elif defined(BFIN)
+#define PT_TEXT_ADDR 220
+#define PT_TEXT_END_ADDR 224
+#define PT_DATA_ADDR 228
#endif
/* Under uClinux, programs are loaded at non-zero offsets, which we need
diff --git a/gdb/regformats/reg-bfin.dat b/gdb/regformats/reg-bfin.dat
new file mode 100644
index 0000000..38dca22
--- /dev/null
+++ b/gdb/regformats/reg-bfin.dat
@@ -0,0 +1,63 @@
+name:bfin
+expedite:pc,sp,fp
+32:r0
+32:r1
+32:r2
+32:r3
+32:r4
+32:r5
+32:r6
+32:r7
+32:p0
+32:p1
+32:p2
+32:p3
+32:p4
+32:p5
+32:sp
+32:fp
+32:i0
+32:i1
+32:i2
+32:i3
+32:m0
+32:m1
+32:m2
+32:m3
+32:b0
+32:b1
+32:b2
+32:b3
+32:l0
+32:l1
+32:l2
+32:l3
+32:a0x
+32:a0w
+32:a1x
+32:a1w
+32:astat
+32:rets
+32:lc0
+32:lt0
+32:lb0
+32:lc1
+32:lt1
+32:lb1
+32:cycles
+32:cycles2
+32:usp
+32:seqstat
+32:syscfg
+32:reti
+32:retx
+32:retn
+32:rete
+32:pc
+32:cc
+32:text_addr
+32:text_end_addr
+32:data_addr
+32:fdpic_exec
+32:fdpic_interp
+32:ipend
--
1.7.3.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/2] gdb: bfin: new port
@ 2010-11-16 0:34 Mike Frysinger
2010-11-16 0:34 ` [PATCH 2/2] gdb: gdbserver: " Mike Frysinger
` (2 more replies)
0 siblings, 3 replies; 9+ messages in thread
From: Mike Frysinger @ 2010-11-16 0:34 UTC (permalink / raw)
To: gdb-patches; +Cc: Jie Zhang
From: Jie Zhang <jie.zhang@analog.com>
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>
/:
2010-11-16 Jie Zhang <jie.zhang@analog.com>
* configure.ac (bfin-*-*): Remove gdb from noconfigdirs.
* configure: Regenerate.
gdb/:
2010-11-16 Jie Zhang <jie.zhang@analog.com>
* MAINTAINERS: Add Blackfin port.
* Makefile.in (ALLDEPFILES): Add bfin-tdep.c.
(HFILES_NO_SRCDIR): Add bfin-tdep.h.
* NEWS: Mention new Blackfin port.
* bfin-tdep.c, bfin-tdep.h, config/bfin/bfin.mt: New files.
* configure.tgt (bfin-*-*): Handle bfin targets.
---
configure | 2 +-
configure.ac | 2 +-
gdb/MAINTAINERS | 3 +
gdb/Makefile.in | 3 +-
gdb/NEWS | 4 +
gdb/bfin-tdep.c | 1050 +++++++++++++++++++++++++++++++++++++++++++++++
gdb/bfin-tdep.h | 168 ++++++++
gdb/config/bfin/bfin.mt | 1 +
gdb/configure.tgt | 5 +
9 files changed, 1235 insertions(+), 3 deletions(-)
create mode 100644 gdb/bfin-tdep.c
create mode 100644 gdb/bfin-tdep.h
create mode 100644 gdb/config/bfin/bfin.mt
diff --git a/configure b/configure
index f3bfee2..ad90175 100755
--- a/configure
+++ b/configure
@@ -3173,7 +3173,7 @@ case "${target}" in
;;
bfin-*-*)
unsupported_languages="$unsupported_languages java"
- noconfigdirs="$noconfigdirs target-boehm-gc gdb"
+ noconfigdirs="$noconfigdirs target-boehm-gc"
if test x${is_cross_compiler} != xno ; then
target_configdirs="${target_configdirs} target-bsp target-cygmon"
fi
diff --git a/configure.ac b/configure.ac
index c0e7384..e50549f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -651,7 +651,7 @@ case "${target}" in
;;
bfin-*-*)
unsupported_languages="$unsupported_languages java"
- noconfigdirs="$noconfigdirs target-boehm-gc gdb"
+ noconfigdirs="$noconfigdirs target-boehm-gc"
if test x${is_cross_compiler} != xno ; then
target_configdirs="${target_configdirs} target-bsp target-cygmon"
fi
diff --git a/gdb/MAINTAINERS b/gdb/MAINTAINERS
index e739838..2516d8b 100644
--- a/gdb/MAINTAINERS
+++ b/gdb/MAINTAINERS
@@ -260,6 +260,9 @@ the native maintainer when resolving ABI issues.
avr --target=avr ,-Werror
Tristan Gingold gingold@adacore.com
+ bfin --target=bfin-elf ,-Werror
+ Mike Frysinger vapier@gentoo.org
+
cris --target=cris-elf ,-Werror ,
(sim does not build with -Werror)
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 550badf..ec2d5e7 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -782,7 +782,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 +1420,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-tdep.c \
bsd-uthread.c bsd-kvm.c \
core-regset.c corelow.c \
dcache.c dicos-tdep.c darwin-nat.c \
diff --git a/gdb/NEWS b/gdb/NEWS
index 38478c4..dcf6025 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -90,6 +90,10 @@
** 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-tdep.c b/gdb/bfin-tdep.c
new file mode 100644
index 0000000..ff13918
--- /dev/null
+++ b/gdb/bfin-tdep.c
@@ -0,0 +1,1050 @@
+/* Target-dependent code for Analog Devices Blackfin processer, for GDB.
+
+ Copyright (C) 2005-2010 Free Software Foundation, Inc.
+ Contributed by Analog Devices.
+
+ 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 "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
+
+/* Macros used for signal handling */
+/* Instruction 1 for signal */
+#define P_SIGNAL_INS_1 0x00ADE128
+/* Instruction 2 for signal */
+#define P_SIGNAL_INS_2 0x000000A0
+
+/* The maximum bytes we search to skip the prologue. */
+#define UPPER_LIMIT 40
+
+#define RETS_OFFSET 4
+
+/* Initial value: Register names used in BFIN's ISA documentation. */
+
+static const char *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",
+ "text_addr", "text_end_addr", "data_addr", "fdpic_exec", "fdpic_interp",
+ "ipend"
+};
+
+
+#define NUM_BFIN_REGNAMES \
+ (sizeof (bfin_register_name_strings) / sizeof (char *))
+
+
+/* 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. */
+
+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
+};
+
+
+#define SIGCONTEXT_OFFSET 168
+
+
+/* From <asm/sigcontext.h>. */
+
+static 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 */
+ -1, /* %cc */
+ -1, /* %text_addr */
+ -1, /* %text_end_addr*/
+ -1, /* %data_addr*/
+ -1 /* %ipend */
+};
+
+/* Get info about saved registers in sigtramp. */
+
+struct bfin_linux_sigtramp_info
+{
+ /* Address of context. */
+ CORE_ADDR context_addr;
+
+ /* Offset of registers in `struct sigcontext'. */
+ int *sc_reg_offset;
+};
+
+/* Return non-zero if PC points into the signal trampoline. For the
+ sake of bfin_linux_get_sigtramp_info. */
+
+static int
+bfin_linux_pc_in_sigtramp (struct frame_info *this_frame, CORE_ADDR pc)
+{
+ struct gdbarch *gdbarch = get_frame_arch (this_frame);
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ gdb_byte buf[10];
+ gdb_byte *p;
+ unsigned long insn1, insn2;
+
+ if (pc > (CORE_ADDR) 0x7ffffffe
+ /* When the core is locked, the PC is unavailable.
+ It makes no sense to check further. */
+ || regcache_valid_p (get_current_regcache (), BFIN_PC_REGNUM) < 0
+ || !safe_frame_unwind_memory (this_frame, pc, buf + 4, 2))
+ return 0;
+
+ insn1 = extract_unsigned_integer (buf + 4, 2, byte_order);
+
+ if (insn1 == (P_SIGNAL_INS_1 & 0xffff))
+ {
+ if (pc > (CORE_ADDR) 0x7ffffffa
+ || !safe_frame_unwind_memory (this_frame, pc + 2, buf + 6, 4))
+ return 0;
+ p = buf + 4;
+ }
+ else if (insn1 == P_SIGNAL_INS_2)
+ {
+ if (pc < (CORE_ADDR) 4
+ || !safe_frame_unwind_memory (this_frame, pc - 4, buf, 4))
+ return 0;
+ p = buf;
+ }
+ else
+ return 0;
+
+ insn1 = extract_unsigned_integer (p, 4, byte_order);
+ insn2 = extract_unsigned_integer (p + 4, 2, byte_order);
+
+ if (insn1 == P_SIGNAL_INS_1 && insn2 == P_SIGNAL_INS_2)
+ return 1;
+
+ return 0;
+}
+
+static struct bfin_linux_sigtramp_info
+bfin_linux_get_sigtramp_info (struct frame_info *this_frame)
+{
+ CORE_ADDR sp;
+ int ret;
+ struct bfin_linux_sigtramp_info info;
+
+ sp = frame_unwind_register_unsigned (this_frame, BFIN_SP_REGNUM);
+ ret = bfin_linux_pc_in_sigtramp (this_frame, get_frame_pc (this_frame));
+
+ if (ret == 1)
+ {
+ /* Get sigcontext address. */
+ info.context_addr = sp + SIGCONTEXT_OFFSET;
+ }
+ else
+ internal_error (__FILE__, __LINE__, _("not a sigtramp\n"));
+
+ info.sc_reg_offset = bfin_linux_sigcontext_reg_offset;
+ return info;
+}
+
+/* Signal trampolines. */
+
+static struct trad_frame_cache *
+bfin_linux_sigtramp_frame_cache (struct frame_info *this_frame,
+ void **this_cache)
+{
+ struct frame_id this_id;
+ struct trad_frame_cache *cache;
+ struct bfin_linux_sigtramp_info info;
+ CORE_ADDR sp;
+ int i;
+
+ if (*this_cache)
+ return *this_cache;
+
+ cache = trad_frame_cache_zalloc (this_frame);
+
+ /* The frame ID's code address should be the start-address of the
+ signal trampoline and not the current PC within that trampoline. */
+ sp = get_frame_register_unsigned (this_frame, BFIN_SP_REGNUM);
+
+ /* This would come after the LINK instruction in the ret_from_signal ()
+ function, hence the frame id would be SP + 8. */
+ this_id = frame_id_build (sp + 8, get_frame_pc (this_frame));
+ trad_frame_set_id (cache, this_id);
+
+ info = bfin_linux_get_sigtramp_info (this_frame);
+
+ for (i = 0; i < BFIN_NUM_REGS; i++)
+ if (info.sc_reg_offset[i] != -1)
+ trad_frame_set_reg_addr (cache, i,
+ info.context_addr + info.sc_reg_offset[i]);
+
+ *this_cache = cache;
+ return cache;
+}
+
+static void
+bfin_linux_sigtramp_frame_this_id (struct frame_info *this_frame,
+ void **this_cache,
+ struct frame_id *this_id)
+{
+ struct trad_frame_cache *cache;
+
+ cache = bfin_linux_sigtramp_frame_cache (this_frame, this_cache);
+ trad_frame_get_id (cache, this_id);
+}
+
+static struct value *
+bfin_linux_sigtramp_frame_prev_register (struct frame_info *this_frame,
+ void **this_cache,
+ int regnum)
+{
+ struct trad_frame_cache *cache;
+
+ cache = bfin_linux_sigtramp_frame_cache (this_frame, this_cache);
+ return trad_frame_get_register (cache, this_frame, regnum);
+}
+
+static int
+bfin_linux_sigtramp_frame_sniffer (const struct frame_unwind *self,
+ struct frame_info *this_frame,
+ void **this_cache)
+{
+ CORE_ADDR pc = get_frame_pc (this_frame);
+
+ if (bfin_linux_pc_in_sigtramp (this_frame, pc))
+ return 1;
+
+ return 0;
+}
+
+static const struct frame_unwind bfin_linux_sigtramp_frame_unwind =
+{
+ SIGTRAMP_FRAME,
+ bfin_linux_sigtramp_frame_this_id,
+ bfin_linux_sigtramp_frame_prev_register,
+ NULL,
+ bfin_linux_sigtramp_frame_sniffer
+};
+
+
+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);
+#ifdef _DEBUG
+ fprintf (stderr, "frameless pc case base %x\n", cache->base);
+#endif
+ 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
+};
+
+/* The following functions are for function prologue length calculations. */
+
+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;
+}
+
+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)
+ {
+ fprintf (stderr, "Function Prologue not recognised. pc will point to ENTRY_POINT of the function\n");
+ 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)
+ return builtin_type (gdbarch)->builtin_func_ptr;
+
+ return builtin_type (gdbarch)->builtin_int32;
+}
+
+/* We currently only support passing parameters in integer registers. This
+ conforms with GCC's default model. Several other variants exist and
+ we should probably support some of them based on the selected ABI. */
+
+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 paramters */
+
+ 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 > sizeof (map_gcc_gdb) / sizeof (int))
+ 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. */
+
+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 non-zero, read the appropriate value from REGCACHE,
+ and copy it into READBUF. If WRITEBUF is non-zero, 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 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);
+}
+
+CORE_ADDR
+bfin_frame_align (struct gdbarch *gdbarch, CORE_ADDR address)
+{
+ return (address & ~0x3);
+}
+
+/* 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_num_pseudo_regs (gdbarch, 0);
+ 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;
+}
+
+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
index 0000000..fcdc940
--- /dev/null
+++ b/gdb/bfin-tdep.h
@@ -0,0 +1,168 @@
+/* Target-dependent code for Analog Devices Blackfin processer, for GDB.
+
+ Copyright (C) 2005-2010 Free Software Foundation, Inc.
+ Contributed by Analog Devices.
+
+ 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 */
+ BFIN_PC_REGNUM,
+ BFIN_CC_REGNUM,
+ BFIN_TEXT_ADDR, /* Address of .text section. */
+ BFIN_TEXT_END_ADDR, /* Address of the end of .text section. */
+ BFIN_DATA_ADDR, /* Address of .data section. */
+
+ BFIN_FDPIC_EXEC_REGNUM,
+ BFIN_FDPIC_INTERP_REGNUM,
+
+ /* MMRs */
+ BFIN_IPEND_REGNUM,
+
+ /* LAST ENTRY SHOULD NOT BE CHANGED. */
+ BFIN_NUM_REGS /* The number of all registers. */
+};
+
+enum gcc_regnum {
+ BFIN_GCC_R0_REGNUM = 0,
+ BFIN_GCC_R1_REGNUM,
+ BFIN_GCC_R2_REGNUM,
+ BFIN_GCC_R3_REGNUM,
+ BFIN_GCC_R4_REGNUM,
+ BFIN_GCC_R5_REGNUM,
+ BFIN_GCC_R6_REGNUM,
+ BFIN_GCC_R7_REGNUM,
+ BFIN_GCC_P0_REGNUM,
+ BFIN_GCC_P1_REGNUM,
+ BFIN_GCC_P2_REGNUM,
+ BFIN_GCC_P3_REGNUM,
+ BFIN_GCC_P4_REGNUM,
+ BFIN_GCC_P5_REGNUM,
+ BFIN_GCC_SP_REGNUM,
+ BFIN_GCC_FP_REGNUM,
+ BFIN_GCC_I0_REGNUM,
+ BFIN_GCC_I1_REGNUM,
+ BFIN_GCC_I2_REGNUM,
+ BFIN_GCC_I3_REGNUM,
+ BFIN_GCC_B0_REGNUM,
+ BFIN_GCC_B1_REGNUM,
+ BFIN_GCC_B2_REGNUM,
+ BFIN_GCC_B3_REGNUM,
+ BFIN_GCC_L0_REGNUM,
+ BFIN_GCC_L1_REGNUM,
+ BFIN_GCC_L2_REGNUM,
+ BFIN_GCC_L3_REGNUM,
+ BFIN_GCC_M0_REGNUM,
+ BFIN_GCC_M1_REGNUM,
+ BFIN_GCC_M2_REGNUM,
+ BFIN_GCC_M3_REGNUM,
+ BFIN_GCC_A0_REGNUM,
+ BFIN_GCC_A1_REGNUM,
+ BFIN_GCC_CC_REGNUM,
+ BFIN_GCC_RETS_REGNUM,
+ BFIN_GCC_RETI_REGNUM,
+ BFIN_GCC_RETX_REGNUM,
+ BFIN_GCC_RETN_REGNUM,
+ BFIN_GCC_RETE_REGNUM,
+ BFIN_GCC_ASTAT_REGNUM,
+ BFIN_GCC_SEQSTAT_REGNUM,
+ BFIN_GCC_USP_REGNUM,
+ BFIN_GCC_ARGP_REGNUM,
+ BFIN_GCC_LT0_REGNUM,
+ BFIN_GCC_LT1_REGNUM,
+ BFIN_GCC_LC0_REGNUM,
+ BFIN_GCC_LC1_REGNUM,
+ BFIN_GCC_LB0_REGNUM,
+ BFIN_GCC_LB1_REGNUM
+};
+
+/* 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;
+};
+
+/* in opcodes/bfin-dis.c */
+extern int print_insn_bfin (bfd_vma pc, struct disassemble_info *outf);
+
+/* Return the Blackfin ABI associated with GDBARCH. */
+static inline enum bfin_abi
+bfin_abi (struct gdbarch *gdbarch)
+{
+ return gdbarch_tdep (gdbarch)->bfin_abi;
+}
diff --git a/gdb/config/bfin/bfin.mt b/gdb/config/bfin/bfin.mt
new file mode 100644
index 0000000..2df8fb8
--- /dev/null
+++ b/gdb/config/bfin/bfin.mt
@@ -0,0 +1 @@
+TDEPFILES= bfin-tdep.o
diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index 24a6bf9..c6c31e3 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -106,6 +106,11 @@ avr-*-*)
gdb_sim=../sim/avr/libsim.a
;;
+bfin-*-*)
+ # Target: Blackfin
+ gdb_target_obs="bfin-tdep.o"
+ ;;
+
cris*)
# Target: CRIS
gdb_target_obs="cris-tdep.o corelow.o solib.o solib-svr4.o"
--
1.7.3.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] gdb: bfin: new port
2010-11-16 0:34 [PATCH 1/2] gdb: bfin: new port Mike Frysinger
2010-11-16 0:34 ` [PATCH 2/2] gdb: gdbserver: " Mike Frysinger
@ 2010-11-21 21:29 ` Mike Frysinger
2010-11-29 23:49 ` Mike Frysinger
2010-12-08 21:25 ` Joel Brobecker
2 siblings, 1 reply; 9+ messages in thread
From: Mike Frysinger @ 2010-11-21 21:29 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: Type: Text/Plain, Size: 255 bytes --]
On Monday, November 15, 2010 19:32:26 Mike Frysinger wrote:
> Initial support for Blackfin processors. This supports the standard ABI.
so if i get no feedback, does that mean i may commit the new port (since i'm
listed as the maintainer) ?
-mike
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] gdb: bfin: new port
2010-11-21 21:29 ` [PATCH 1/2] gdb: " Mike Frysinger
@ 2010-11-29 23:49 ` Mike Frysinger
2010-12-06 10:56 ` Mike Frysinger
0 siblings, 1 reply; 9+ messages in thread
From: Mike Frysinger @ 2010-11-29 23:49 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: Type: Text/Plain, Size: 336 bytes --]
On Sunday, November 21, 2010 16:26:59 Mike Frysinger wrote:
> On Monday, November 15, 2010 19:32:26 Mike Frysinger wrote:
> > Initial support for Blackfin processors. This supports the standard ABI.
>
> so if i get no feedback, does that mean i may commit the new port (since
> i'm listed as the maintainer) ?
ping :/
-mike
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] gdb: bfin: new port
2010-11-29 23:49 ` Mike Frysinger
@ 2010-12-06 10:56 ` Mike Frysinger
0 siblings, 0 replies; 9+ messages in thread
From: Mike Frysinger @ 2010-12-06 10:56 UTC (permalink / raw)
To: Jim Blandy, Joel Brobecker, Eli Zaretskii, Daniel Jacobowitz,
Doug Evans, Jan Kratochvil
Cc: gdb-patches
[-- Attachment #1: Type: Text/Plain, Size: 457 bytes --]
On Monday, November 29, 2010 18:38:08 Mike Frysinger wrote:
> On Sunday, November 21, 2010 16:26:59 Mike Frysinger wrote:
> > On Monday, November 15, 2010 19:32:26 Mike Frysinger wrote:
> > > Initial support for Blackfin processors. This supports the standard
> > > ABI.
> >
> > so if i get no feedback, does that mean i may commit the new port (since
> > i'm listed as the maintainer) ?
>
> ping :/
random global maintainer ping ...
-mike
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] gdb: bfin: new port
2010-11-16 0:34 [PATCH 1/2] gdb: bfin: new port Mike Frysinger
2010-11-16 0:34 ` [PATCH 2/2] gdb: gdbserver: " Mike Frysinger
2010-11-21 21:29 ` [PATCH 1/2] gdb: " Mike Frysinger
@ 2010-12-08 21:25 ` Joel Brobecker
2010-12-08 21:36 ` Eli Zaretskii
2010-12-09 3:35 ` Mike Frysinger
2 siblings, 2 replies; 9+ messages in thread
From: Joel Brobecker @ 2010-12-08 21:25 UTC (permalink / raw)
To: Mike Frysinger; +Cc: gdb-patches, Jie Zhang
Mike,
First of all, I apologize of the delay in reviewing this. Overall,
I think that this is very good work. I can't really help with the
correctness of the code, since I don't know the bfin architecture.
> 2010-11-16 Jie Zhang <jie.zhang@analog.com>
>
> * configure.ac (bfin-*-*): Remove gdb from noconfigdirs.
> * configure: Regenerate.
This should be sent to gcc-patches....
> gdb/:
> 2010-11-16 Jie Zhang <jie.zhang@analog.com>
>
> * MAINTAINERS: Add Blackfin port.
> * Makefile.in (ALLDEPFILES): Add bfin-tdep.c.
> (HFILES_NO_SRCDIR): Add bfin-tdep.h.
> * NEWS: Mention new Blackfin port.
> * bfin-tdep.c, bfin-tdep.h, config/bfin/bfin.mt: New files.
> * configure.tgt (bfin-*-*): Handle bfin targets.
Minor comments below...
> + bfin --target=bfin-elf ,-Werror
> + Mike Frysinger vapier@gentoo.org
> +
We usually wait to see a few contributions before inviting a contributor
to become the official maintainer. So, would you mind taking that hunk
out of your patch?
> --- a/gdb/Makefile.in
> +++ b/gdb/Makefile.in
I think you will also want to add bfin-tdep.o to ALL_TARGET_OBS.
Otherwise, bfin gets left out when you build with --enable-targets=all.
I don't see a reason why we shouldn't include it.
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
This part gets approved by Eli Zaretski, our documentation maintainer.
Can you maybe ping him about it? He has always been extremely responsive,
so he probably just missed the fact that this patch had some documentation
changes for him to review.
> +#define NUM_BFIN_REGNAMES \
> + (sizeof (bfin_register_name_strings) / sizeof (char *))
There is a macro called ARRAY_SIZE that you can use...
> +int map_gcc_gdb[] =
Can this be made static?
> +/* Return non-zero if PC points into the signal trampoline. For the
> + sake of bfin_linux_get_sigtramp_info. */
This is a detail, but `nonzero' is spelled without the dash in the
middle. It's a detail because it's spelled your way everywhere...
> +static int
> +bfin_linux_pc_in_sigtramp (struct frame_info *this_frame, CORE_ADDR pc)
> +{
[...]
> + gdb_byte buf[10];
The use of that buffer is most peculiar. You first start by reading
a 2-byte instruction and storing it at buf+4. Then, depending on
the instruction, you you extract the other instruction either at
buf or buf+6. If it works, then no need to change...
I'm also wondering whether you know about tramp-frame.h, and whether
that might be sufficient for your needs...
> + if (ret == 1)
> + {
> + /* Get sigcontext address. */
> + info.context_addr = sp + SIGCONTEXT_OFFSET;
> + }
> + else
> + internal_error (__FILE__, __LINE__, _("not a sigtramp\n"));
You should use a gdb_assert(), in this case.
> + /* This would come after the LINK instruction in the ret_from_signal ()
> + function, hence the frame id would be SP + 8. */
Please remove the `()' - it is used only when talking about the function
call...
> + /* 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. */
Missing space after a period (2 instances).
> + cache->saved_regs[BFIN_PC_REGNUM] = get_frame_register_unsigned (this_frame, BFIN_RETS_REGNUM);
This line is too long (over 78 characters).
> +#ifdef _DEBUG
> + fprintf (stderr, "frameless pc case base %x\n", cache->base);
> +#endif
Can you avoid the #ifdef? I personally that debugging logs are a good
idea. But I don't think they should only be activated (or not) at
compile time. The typical way of doing this is to conditionalize this
on a global variable controlled by a setting. For instance, how about
(gdb) set debug bfin
(see `set debug infrun' for instance).
> +/* The following functions are for function prologue length calculations. */
Each function needs to be documented.
> +static int
> +is_minus_minus_sp (int op)
Just out of curiosity: Why two 'minus' in the name?
> +CORE_ADDR
> +bfin_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
This function should be made static.
> + fprintf (stderr, "Function Prologue not recognised. pc will point to ENTRY_POINT of the function\n");
No call to fprintf. In this case, I think you can use the `warning'
function.
> +/* We currently only support passing parameters in integer registers. This
> + conforms with GCC's default model. Several other variants exist and
> + we should probably support some of them based on the selected ABI. */
I think that this comment will be less surprising if you place it at
the start of the function, inside the function body...
> + 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;
Empty line after local variable declarations.
> + 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);
Likewise.
> + if (reg > sizeof (map_gcc_gdb) / sizeof (int))
You can use ARRAY_SIZE...
> +/* This function implements the BREAKPOINT_FROM_PC macro. It returns
^^^^ missing space
> +const unsigned char *
> +bfin_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, int *lenptr)
Should be made static.
> + and copy it into READBUF. If WRITEBUF is non-zero, write the value
^^^^^^^^
> +CORE_ADDR
> +bfin_frame_align (struct gdbarch *gdbarch, CORE_ADDR address)
Make static?
> +enum gcc_regnum {
> + BFIN_GCC_R0_REGNUM = 0,
What is this used for?
> +/* 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;
> +};
Why is this used, since there is only one ABI?
> +/* Return the Blackfin ABI associated with GDBARCH. */
> +static inline enum bfin_abi
> +bfin_abi (struct gdbarch *gdbarch)
> +{
> + return gdbarch_tdep (gdbarch)->bfin_abi;
> +}
Please - no code in .h files. I doubt that making that function inline
is bringing any measurable benefit - is it?
--
Joel
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] gdb: bfin: new port
2010-12-08 21:25 ` Joel Brobecker
@ 2010-12-08 21:36 ` Eli Zaretskii
2010-12-09 3:35 ` Mike Frysinger
1 sibling, 0 replies; 9+ messages in thread
From: Eli Zaretskii @ 2010-12-08 21:36 UTC (permalink / raw)
To: Joel Brobecker; +Cc: vapier, gdb-patches, jie.zhang
> Date: Wed, 8 Dec 2010 22:25:38 +0100
> From: Joel Brobecker <brobecker@adacore.com>
> Cc: gdb-patches@sourceware.org, Jie Zhang <jie.zhang@analog.com>
>
> > --- a/gdb/NEWS
> > +++ b/gdb/NEWS
>
> This part gets approved by Eli Zaretski, our documentation maintainer.
It's okay.
> Can you maybe ping him about it? He has always been extremely responsive,
> so he probably just missed the fact that this patch had some documentation
> changes for him to review.
Yes, I did, sorry.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] gdb: gdbserver: bfin: new port
2010-11-16 0:34 ` [PATCH 2/2] gdb: gdbserver: " Mike Frysinger
@ 2010-12-08 21:38 ` Joel Brobecker
0 siblings, 0 replies; 9+ messages in thread
From: Joel Brobecker @ 2010-12-08 21:38 UTC (permalink / raw)
To: Mike Frysinger; +Cc: gdb-patches, pedro
> gdb/:
> 2010-11-16 Jie Zhang <jie.zhang@analog.com>
>
> * configure.tgt (bfin-*-*): Set build_gdbserver to yes.
> * NEWS: Mention new Blackfin support.
> * regformats/reg-bfin.dat: New file.
>
> gdbserver/:
> 2010-11-16 Jie Zhang <jie.zhang@analog.com>
>
> * configure.srv (bfin-*-*): Handle bfin targets.
> * linux-bfin-low.c: New file.
> * linux-low.c: Define PT_TEXT_ADDR, PT_TEXT_END_ADDR, and
> PT_DATA_ADDR for BFIN targets.
> * Makefile.in (SFILES): Add linux-bfin-low.c.
> (clean): Remove reg-bfin.c.
> (linux-bfin-low.o, reg-bfin.o, reg-bfin.c): New targets.
> * README: Mention supported Blackfin targets.
The best person to approve your change is either Daniel or Pedro.
Pedro has been doing most of the approvals in that area, lately.
Nonetheless, I had a look.
Overall, I don't see anything wrong with the code.
> +#define bfin_num_regs (sizeof(bfin_regmap) / sizeof(bfin_regmap[0]))
You can use ARRAY_SIZE.
> + unsigned long pc;
> + collect_register_by_name (regcache, "pc", &pc);
> + return pc;
Empty line after local variable declarations... There are several
instances in your patch.
--
Joel
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] gdb: bfin: new port
2010-12-08 21:25 ` Joel Brobecker
2010-12-08 21:36 ` Eli Zaretskii
@ 2010-12-09 3:35 ` Mike Frysinger
1 sibling, 0 replies; 9+ messages in thread
From: Mike Frysinger @ 2010-12-09 3:35 UTC (permalink / raw)
To: gdb-patches; +Cc: Joel Brobecker
[-- Attachment #1: Type: Text/Plain, Size: 4341 bytes --]
On Wednesday, December 08, 2010 16:25:38 Joel Brobecker wrote:
> First of all, I apologize of the delay in reviewing this. Overall,
> I think that this is very good work. I can't really help with the
> correctness of the code, since I don't know the bfin architecture.
np. if there's any feedback i didnt respond to here, it's because i just did
as asked since it made perfect sense.
> > + bfin --target=bfin-elf ,-Werror
> > + Mike Frysinger vapier@gentoo.org
> > +
>
> We usually wait to see a few contributions before inviting a contributor
> to become the official maintainer. So, would you mind taking that hunk
> out of your patch?
i thought people would want to know how to find out who knows the Blackfin
code in case they had a question. ive made contributions in the past to gdb,
but more so to the binutils project. but if you want me to leave it out for
now, that's obviously your call.
> > +static int
> > +bfin_linux_pc_in_sigtramp (struct frame_info *this_frame, CORE_ADDR pc)
> > +{
> [...]
> > + gdb_byte buf[10];
>
> The use of that buffer is most peculiar. You first start by reading
> a 2-byte instruction and storing it at buf+4. Then, depending on
> the instruction, you you extract the other instruction either at
> buf or buf+6. If it works, then no need to change...
i think the idea is for buf[] to reflect the actual code to make debugging
this code easier. i'm sure the buffer could be compacted, but i dont think
it'd have any sort of profound savings, so i'd prefer to leave it be.
> I'm also wondering whether you know about tramp-frame.h, and whether
> that might be sufficient for your needs...
this port was originally written against an older version of gdb which didnt
have tramp-frame stuff. i'll log this into our tracker to get this updated.
> > +#ifdef _DEBUG
> > + fprintf (stderr, "frameless pc case base %x\n", cache->base);
> > +#endif
>
> Can you avoid the #ifdef? I personally that debugging logs are a good
> idea. But I don't think they should only be activated (or not) at
> compile time. The typical way of doing this is to conditionalize this
> on a global variable controlled by a setting. For instance, how about
>
> (gdb) set debug bfin
>
> (see `set debug infrun' for instance).
i'll drop it for now, but i like the idea of runtime debug in this code, and i
have more stuff i could sprinkle throughout.
> > +static int
> > +is_minus_minus_sp (int op)
>
> Just out of curiosity: Why two 'minus' in the name?
the actual insn is "[--SP] = ...;"
> > +enum gcc_regnum {
> > + BFIN_GCC_R0_REGNUM = 0,
>
> What is this used for?
that's a good question. looking through the history, it doesnt seem to be
referenced when it was first added over 5 years ago. i cant really ask the
guy who committed it as it was a contractor who hasnt worked for us in a very
long time. considering the current dwarf/gdb map seems to work, i'll just
punt it.
> > +/* 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;
> > +};
>
> Why is this used, since there is only one ABI?
i have a follow up patch to add the FDPIC ABI, but it requires rework in the
FRV FDPIC, and the frame parsing doesnt work quite right when going through
the PLT after we updated from our older gdb version. since these issues are
taking time, i'd like to get the core Blackfin code merged as people are using
that today for various targets.
> > +/* Return the Blackfin ABI associated with GDBARCH. */
> > +static inline enum bfin_abi
> > +bfin_abi (struct gdbarch *gdbarch)
> > +{
> > + return gdbarch_tdep (gdbarch)->bfin_abi;
> > +}
>
> Please - no code in .h files.
it's used by both the core Blackfin code and the FDPIC solib code (which isnt
part of this patch per above). i could duplicate the function in two files,
but it seems to make more sense to have one shared instance.
> I doubt that making that function inline is bringing any measurable benefit
> - is it?
it avoids warnings when people include this header but dont use the func
-mike
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2010-12-09 3:35 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-11-16 0:34 [PATCH 1/2] gdb: bfin: new port Mike Frysinger
2010-11-16 0:34 ` [PATCH 2/2] gdb: gdbserver: " Mike Frysinger
2010-12-08 21:38 ` Joel Brobecker
2010-11-21 21:29 ` [PATCH 1/2] gdb: " Mike Frysinger
2010-11-29 23:49 ` Mike Frysinger
2010-12-06 10:56 ` Mike Frysinger
2010-12-08 21:25 ` Joel Brobecker
2010-12-08 21:36 ` Eli Zaretskii
2010-12-09 3:35 ` Mike Frysinger
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox