From 1525d5452d720e163509decda467b5de11a141e8 Mon Sep 17 00:00:00 2001 From: Maxim Grigoriev Date: Mon, 11 Feb 2008 22:00:31 +0000 Subject: [PATCH] 2008-02-11 Maxim Grigoriev * gdbserver/Makefile.in (SFILES): Add linux-xtensa-low.c. (clean): Add reg-xtensa.c. (linux-xtensa-low.o, reg-xtensa.o, reg-xtensa.c): New dependencies. * gdbserver/configure.srv (xtensa*-*-linux*) New target. * gdbserver/linux-xtensa-low.c: New. * gdbserver/xtensa-xtregs.c: New. --- gdb/gdbserver/ChangeLog | 9 ++ gdb/gdbserver/Makefile.in | 8 +- gdb/gdbserver/configure.srv | 4 + gdb/gdbserver/linux-xtensa-low.c | 187 +++++++++++++++++++++++++++++++ gdb/gdbserver/xtensa-xtregs.c | 37 ++++++ 5 files changed, 243 insertions(+), 2 deletions(-) create mode 100644 gdb/gdbserver/linux-xtensa-low.c create mode 100644 gdb/gdbserver/xtensa-xtregs.c diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index 07f0a447c56..05869664379 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,12 @@ +2008-02-11 Maxim Grigoriev + + * gdbserver/Makefile.in (SFILES): Add linux-xtensa-low.c. + (clean): Add reg-xtensa.c. + (linux-xtensa-low.o, reg-xtensa.o, reg-xtensa.c): New dependencies. + * gdbserver/configure.srv (xtensa*-*-linux*) New target. + * gdbserver/linux-xtensa-low.c: New. + * gdbserver/xtensa-xtregs.c: New. + 2008-02-01 Pedro Alves * hostio.c: Don't include errno.h. diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in index d643bdf379c..2c7cb75920a 100644 --- a/gdb/gdbserver/Makefile.in +++ b/gdb/gdbserver/Makefile.in @@ -129,6 +129,7 @@ SFILES= $(srcdir)/gdbreplay.c $(srcdir)/inferiors.c \ $(srcdir)/linux-ppc-low.c $(srcdir)/linux-ppc64-low.c \ $(srcdir)/linux-s390-low.c \ $(srcdir)/linux-sh-low.c $(srcdir)/linux-x86-64-low.c \ + $(srcdir)/linux-xtensa-low.c \ $(srcdir)/win32-arm-low.c $(srcdir)/win32-i386-low.c \ $(srcdir)/win32-low.c $(srcdir)/wincecompat.c \ $(srcdir)/hostio.c $(srcdir)/hostio-errno.c @@ -218,7 +219,7 @@ clean: rm -f gdbserver$(EXEEXT) gdbreplay$(EXEEXT) core make.log rm -f reg-arm.c reg-i386.c reg-ia64.c reg-m32r.c reg-m68k.c rm -f reg-ppc.c reg-sh.c reg-spu.c reg-x86-64.c reg-i386-linux.c - rm -f reg-cris.c reg-crisv32.c reg-x86-64-linux.c + rm -f reg-cris.c reg-crisv32.c reg-x86-64-linux.c reg-xtensa.c rm -f arm-with-iwmmxt.c mips-linux.c mips64-linux.c rm -f powerpc-32.c powerpc-64.c powerpc-e500.c rm -f xml-builtin.c stamp-xml target.xml @@ -316,6 +317,7 @@ linux-s390-low.o: linux-s390-low.c $(linux_low_h) $(server_h) linux-sh-low.o: linux-sh-low.c $(linux_low_h) $(server_h) linux-x86-64-low.o: linux-x86-64-low.c $(linux_low_h) $(server_h) \ $(gdb_proc_service_h) +linux-xtensa-low.o: linux-xtensa-low.c xtensa-xtregs.c $(linux_low_h) $(server_h) win32_low_h = $(srcdir)/win32-low.h @@ -392,5 +394,7 @@ reg-x86-64.c : $(srcdir)/../regformats/reg-x86-64.dat $(regdat_sh) reg-x86-64-linux.o : reg-x86-64-linux.c $(regdef_h) reg-x86-64-linux.c : $(srcdir)/../regformats/reg-x86-64-linux.dat $(regdat_sh) $(SHELL) $(regdat_sh) $(srcdir)/../regformats/reg-x86-64-linux.dat reg-x86-64-linux.c - +reg-xtensa.o : reg-xtensa.c $(regdef_h) +reg-xtensa.c : $(srcdir)/../regformats/reg-xtensa.dat $(regdat_sh) + $(SHELL) $(regdat_sh) $(srcdir)/../regformats/reg-xtensa.dat reg-xtensa.c # This is the end of "Makefile.in". diff --git a/gdb/gdbserver/configure.srv b/gdb/gdbserver/configure.srv index b57c8a50ce1..4f1c22b3aa4 100644 --- a/gdb/gdbserver/configure.srv +++ b/gdb/gdbserver/configure.srv @@ -170,6 +170,10 @@ case "${target}" in srv_linux_usrregs=yes srv_linux_thread_db=yes ;; + xtensa*-*-linux*) srv_regobj=reg-xtensa.o + srv_tgtobj="linux-low.o linux-xtensa-low.o" + srv_linux_regsets=yes + ;; *) echo "Error: target not supported by gdbserver." exit 1 ;; diff --git a/gdb/gdbserver/linux-xtensa-low.c b/gdb/gdbserver/linux-xtensa-low.c new file mode 100644 index 00000000000..cbf5a514b65 --- /dev/null +++ b/gdb/gdbserver/linux-xtensa-low.c @@ -0,0 +1,187 @@ +/* GNU/Linux/Xtensa specific low level interface, for the remote server for GDB. + Copyright 2007, 2008 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 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 . */ + + +#include "server.h" +#include "linux-low.h" + +#include +#include + +#include "xtensa-xtregs.c" + +enum regnum { + R_PC=0, R_PS, + R_LBEG, R_LEND, R_LCOUNT, + R_SAR, + R_WS, R_WB, + R_A0 = 64 +}; + +static void +xtensa_fill_gregset (void *buf) +{ + elf_greg_t* rset = (elf_greg_t*)buf; + int ar0_regnum; + char *ptr; + int i; + + /* Take care of AR registers. */ + + ar0_regnum = find_regno ("ar0"); + ptr = (char*)&rset[R_A0]; + + for (i = ar0_regnum; i < ar0_regnum + XCHAL_NUM_AREGS; i++) + { + collect_register (i, ptr); + ptr += register_size(i); + } + + /* Loop registers, if hardware has it. */ + +#if XCHAL_HAVE_LOOP + collect_register_by_name ("lbeg", (char*)&rset[R_LBEG]); + collect_register_by_name ("lend", (char*)&rset[R_LEND]); + collect_register_by_name ("lcount", (char*)&rset[R_LCOUNT]); +#endif + + collect_register_by_name ("sar", (char*)&rset[R_SAR]); + collect_register_by_name ("pc", (char*)&rset[R_PC]); + collect_register_by_name ("ps", (char*)&rset[R_PS]); + collect_register_by_name ("windowbase", (char*)&rset[R_WB]); + collect_register_by_name ("windowstart", (char*)&rset[R_WS]); +} + +static void +xtensa_store_gregset (const void *buf) +{ + const elf_greg_t* rset = (const elf_greg_t*)buf; + int ar0_regnum; + char *ptr; + int i; + + /* Take care of AR registers. */ + + ar0_regnum = find_regno ("ar0"); + ptr = (char *)&rset[R_A0]; + + for (i = ar0_regnum; i < ar0_regnum + XCHAL_NUM_AREGS; i++) + { + supply_register (i, ptr); + ptr += register_size(i); + } + + /* Loop registers, if hardware has it. */ + +#if XCHAL_HAVE_LOOP + supply_register_by_name ("lbeg", (char*)&rset[R_LBEG]); + supply_register_by_name ("lend", (char*)&rset[R_LEND]); + supply_register_by_name ("lcount", (char*)&rset[R_LCOUNT]); +#endif + + supply_register_by_name ("sar", (char*)&rset[R_SAR]); + supply_register_by_name ("pc", (char*)&rset[R_PC]); + supply_register_by_name ("ps", (char*)&rset[R_PS]); + supply_register_by_name ("windowbase", (char*)&rset[R_WB]); + supply_register_by_name ("windowstart", (char*)&rset[R_WS]); +} + +/* Xtensa GNU/Linux PTRACE interface includes extended register set. */ + +static void +xtensa_fill_xtregset (void *buf) +{ + const xtensa_regtable_t *ptr; + + for (ptr = xtensa_regmap_table; ptr->name; ptr++) + { + collect_register_by_name (ptr->name, + (char*)buf + ptr->ptrace_offset); + } +} + +static void +xtensa_store_xtregset (const void *buf) +{ + const xtensa_regtable_t *ptr; + + for (ptr = xtensa_regmap_table; ptr->name; ptr++) + { + supply_register_by_name (ptr->name, + (char*)buf + ptr->ptrace_offset); + } +} + +struct regset_info target_regsets[] = { + { PTRACE_GETREGS, PTRACE_SETREGS, sizeof (elf_gregset_t), + GENERAL_REGS, + xtensa_fill_gregset, xtensa_store_gregset }, + { PTRACE_GETXTREGS, PTRACE_SETXTREGS, XTENSA_ELF_XTREG_SIZE, + EXTENDED_REGS, + xtensa_fill_xtregset, xtensa_store_xtregset }, + { 0, 0, -1, -1, NULL, NULL } +}; + +#if XCHAL_HAVE_BE +#define XTENSA_BREAKPOINT {0xd2,0x0f} +#else +#define XTENSA_BREAKPOINT {0x2d,0xf0} +#endif + +static const unsigned char xtensa_breakpoint[] = XTENSA_BREAKPOINT; +#define xtensa_breakpoint_len 2 + +static CORE_ADDR +xtensa_get_pc (void) +{ + unsigned long pc; + + collect_register_by_name ("pc", &pc); + return pc; +} + +static void +xtensa_set_pc (CORE_ADDR pc) +{ + unsigned long newpc = pc; + supply_register_by_name ("pc", &newpc); +} + +static int +xtensa_breakpoint_at (CORE_ADDR where) +{ + unsigned long insn; + + (*the_target->read_memory) (where, (unsigned char *) &insn, + xtensa_breakpoint_len); + return memcmp((char *)&insn, xtensa_breakpoint, xtensa_breakpoint_len) == 0; +} + +struct linux_target_ops the_low_target = { + 0, + 0, + 0, + 0, + xtensa_get_pc, + xtensa_set_pc, + xtensa_breakpoint, + xtensa_breakpoint_len, + NULL, + 0, + xtensa_breakpoint_at, +}; diff --git a/gdb/gdbserver/xtensa-xtregs.c b/gdb/gdbserver/xtensa-xtregs.c new file mode 100644 index 00000000000..9faa50df2f0 --- /dev/null +++ b/gdb/gdbserver/xtensa-xtregs.c @@ -0,0 +1,37 @@ +/* Table mapping between kernel xtregset and GDB register cache. + Copyright 2007, 2008 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (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 . */ + + +typedef struct { + int gdb_regnum; + int gdb_offset; + int ptrace_cp_offset; + int ptrace_offset; + int size; + int coproc; + int dbnum; + char* name +;} xtensa_regtable_t; + +#define XTENSA_ELF_XTREG_SIZE 0 + +const xtensa_regtable_t xtensa_regmap_table[] = { + /* gnum,gofs,cpofs,ofs,siz,cp, dbnum, name */ + { 0 } +}; + -- 2.30.2