diff options
Diffstat (limited to 'package/gdb')
| -rw-r--r-- | package/gdb/Makefile | 23 | ||||
| -rw-r--r-- | package/gdb/patches/microblaze.patch | 1842 | 
2 files changed, 1854 insertions, 11 deletions
| diff --git a/package/gdb/Makefile b/package/gdb/Makefile index 9fc0b48fa..e282052e3 100644 --- a/package/gdb/Makefile +++ b/package/gdb/Makefile @@ -20,27 +20,28 @@ TARGET_CFLAGS+=         -static  CONFIGURE_ARGS+=	--enable-static  endif -TARGET_CFLAGS:=         $(filter-out -flto,$(TARGET_CFLAGS))  TARGET_CFLAGS+=		${TARGET_CPPFLAGS} -fPIC -CONFIGURE_ARGS+=	--without-uiout --enable-gdbmi \ -			--disable-tui --disable-gdbtk --without-x \ -			--without-included-gettext --disable-sim \ -			--with-curses --disable-werror \ -			--without-auto-load-safe-path \ +CONFIGURE_ARGS+=	--without-uiout \ +			--disable-tui \ +			--disable-gdbtk \ +			--without-x \ +			--disable-sim \ +			--disable-werror \  			--disable-gdbserver \ -			--without-python +			--without-python \ +			--without-included-gettext \ +			--without-auto-load-safe-path \ +			--with-curses \ +			--enable-gdbmi +  XAKE_FLAGS+=		LDFLAGS='${TARGET_LDFLAGS}'  # disable honour cflags stuff  XAKE_FLAGS+=		GCC_HONOUR_COPTS:=s -post-extract: -	-mv $(STAGING_TARGET_DIR)/usr/lib/libiberty.a $(STAGING_TARGET_DIR)/usr/lib/libiberty.a.bak -  gdb-install:  	${INSTALL_DIR} ${IDIR_GDB}/usr/bin  	${INSTALL_BIN} ${WRKINST}/usr/bin/gdb ${IDIR_GDB}/usr/bin/  	# shipped libbfd conflicts with system wide one  	rm -f ${WRKINST}/usr/lib/libbfd* -	-mv $(STAGING_TARGET_DIR)/usr/lib/libiberty.a.bak $(STAGING_TARGET_DIR)/usr/lib/libiberty.a  include ${TOPDIR}/mk/pkg-bottom.mk diff --git a/package/gdb/patches/microblaze.patch b/package/gdb/patches/microblaze.patch new file mode 100644 index 000000000..ce3f9b35b --- /dev/null +++ b/package/gdb/patches/microblaze.patch @@ -0,0 +1,1842 @@ +diff -Nur gdb-7.7.orig/bfd/bfd-in2.h gdb-7.7/bfd/bfd-in2.h +--- gdb-7.7.orig/bfd/bfd-in2.h	2014-02-06 03:21:29.000000000 +0100 ++++ gdb-7.7/bfd/bfd-in2.h	2014-03-26 19:43:36.000000000 +0100 +@@ -5378,6 +5378,11 @@ + expressions of the form "Symbol Op Symbol"  */ +   BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM, +  ++/* This is a 32 bit reloc that stores the 32 bit pc relative ++value in two words (with an imm instruction).  No relocation is  ++done here - only used for relaxing  */ ++  BFD_RELOC_MICROBLAZE_32_NONE, ++ + /* This is a 64 bit reloc that stores the 32 bit pc relative + value in two words (with an imm instruction).  No relocation is + done here - only used for relaxing  */ +diff -Nur gdb-7.7.orig/bfd/elf32-microblaze.c gdb-7.7/bfd/elf32-microblaze.c +--- gdb-7.7.orig/bfd/elf32-microblaze.c	2013-12-08 05:55:47.000000000 +0100 ++++ gdb-7.7/bfd/elf32-microblaze.c	2014-03-27 08:30:48.000000000 +0100 +@@ -177,6 +177,20 @@ +           FALSE), 		/* PC relative offset?  */ +  +    /* This reloc does nothing.  Used for relaxation.  */ ++   HOWTO (R_MICROBLAZE_32_NONE,	/* Type.  */ ++          0,			/* Rightshift.  */ ++          2,			/* Size (0 = byte, 1 = short, 2 = long).  */ ++          32,			/* Bitsize.  */ ++          TRUE,			/* PC_relative.  */ ++          0,			/* Bitpos.  */ ++          complain_overflow_bitfield,  /* Complain on overflow.  */ ++          NULL,                  /* Special Function.  */ ++          "R_MICROBLAZE_32_NONE",/* Name.  */ ++          FALSE,		/* Partial Inplace.  */ ++          0,			/* Source Mask.  */ ++          0,			/* Dest Mask.  */ ++          FALSE),		/* PC relative offset?  */ ++ +    HOWTO (R_MICROBLAZE_64_NONE,	/* Type.  */ +           0,			/* Rightshift.  */ +           2,			/* Size (0 = byte, 1 = short, 2 = long).  */ +@@ -532,7 +546,10 @@ +     case BFD_RELOC_NONE: +       microblaze_reloc = R_MICROBLAZE_NONE; +       break; +-    case BFD_RELOC_MICROBLAZE_64_NONE: ++    case BFD_RELOC_MICROBLAZE_32_NONE: ++      microblaze_reloc = R_MICROBLAZE_32_NONE; ++      break; ++     case BFD_RELOC_MICROBLAZE_64_NONE: +       microblaze_reloc = R_MICROBLAZE_64_NONE; +       break; +     case BFD_RELOC_32: +@@ -668,6 +685,67 @@ +   return _bfd_elf_is_local_label_name (abfd, name); + } +  ++/* Support for core dump NOTE sections.  */ ++static bfd_boolean ++microblaze_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) ++{ ++  int offset; ++  unsigned int size; ++ ++  switch (note->descsz) ++    { ++      default: ++        return FALSE; ++ ++      case 228:         /* Linux/MicroBlaze */ ++        /* pr_cursig */ ++        elf_tdata (abfd)->core->signal = bfd_get_16 (abfd, note->descdata + 12); ++ ++        /* pr_pid */ ++        elf_tdata (abfd)->core->pid = bfd_get_32 (abfd, note->descdata + 24); ++ ++        /* pr_reg */ ++        offset = 72; ++        size = 50 * 4; ++ ++        break; ++    } ++ ++  /* Make a ".reg/999" section.  */ ++  return _bfd_elfcore_make_pseudosection (abfd, ".reg", ++                                          size, note->descpos + offset); ++} ++ ++static bfd_boolean ++microblaze_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) ++{ ++  switch (note->descsz) ++    { ++      default: ++        return FALSE; ++ ++      case 128:         /* Linux/MicroBlaze elf_prpsinfo */ ++        elf_tdata (abfd)->core->program ++         = _bfd_elfcore_strndup (abfd, note->descdata + 32, 16); ++        elf_tdata (abfd)->core->command ++         = _bfd_elfcore_strndup (abfd, note->descdata + 48, 80); ++    } ++ ++  /* Note that for some reason, a spurious space is tacked ++     onto the end of the args in some (at least one anyway) ++     implementations, so strip it off if it exists.  */ ++ ++  { ++    char *command = elf_tdata (abfd)->core->command; ++    int n = strlen (command); ++ ++    if (0 < n && command[n - 1] == ' ') ++      command[n - 1] = '\0'; ++  } ++ ++  return TRUE; ++} ++ + /* The microblaze linker (like many others) needs to keep track of +    the number of relocs that it decides to copy as dynamic relocs in +    check_relocs for each symbol. This is so that it can later discard +@@ -1023,7 +1101,7 @@ + 	    { + 	      /* External symbol.  */ + 	      bfd_boolean warned ATTRIBUTE_UNUSED; +-	      bfd_boolean ignored ATTRIBUTE_UNUSED; ++	      bfd_boolean ignored; +  + 	      RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, + 				       r_symndx, symtab_hdr, sym_hashes, +@@ -1852,14 +1930,22 @@ + 	        } + 	      break; + 	    case R_MICROBLAZE_NONE: ++	    case R_MICROBLAZE_32_NONE: + 	      { + 	        /* This was a PC-relative instruction that was +  		   completely resolved.  */ + 	        int sfix, efix; ++		unsigned int val; + 	        bfd_vma target_address; + 	        target_address = irel->r_addend + irel->r_offset; + 	        sfix = calc_fixup (irel->r_offset, 0, sec); + 	        efix = calc_fixup (target_address, 0, sec); ++ ++                /* Validate the in-band val.  */ ++                val = bfd_get_32 (abfd, contents + irel->r_offset); ++                if (val != irel->r_addend && ELF32_R_TYPE (irel->r_info) == R_MICROBLAZE_32_NONE) { ++                    fprintf(stderr, "%d: CORRUPT relax reloc %x %lx\n", __LINE__, val, irel->r_addend); ++                } + 	        irel->r_addend -= (efix - sfix); + 	        /* Should use HOWTO.  */ + 	        microblaze_bfd_write_imm_value_32 (abfd, contents + irel->r_offset, +@@ -1907,6 +1993,49 @@ +           irelscanend = irelocs + o->reloc_count; +           for (irelscan = irelocs; irelscan < irelscanend; irelscan++) +             { ++              if (1 && ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32_NONE) ++                { ++                  unsigned int val; ++ ++                  isym = isymbuf + ELF32_R_SYM (irelscan->r_info); ++ ++                  /* hax: We only do the following fixup for debug location lists.  */ ++                  if (strcmp(".debug_loc", o->name)) ++                    continue; ++ ++                  /* This was a PC-relative instruction that was completely resolved.  */ ++                  if (ocontents == NULL) ++                    { ++		      if (elf_section_data (o)->this_hdr.contents != NULL) ++		          ocontents = elf_section_data (o)->this_hdr.contents; ++		      else ++		        { ++		          /* We always cache the section contents. ++			     Perhaps, if info->keep_memory is FALSE, we ++			     should free them, if we are permitted to.  */ ++ ++		          if (o->rawsize == 0) ++			      o->rawsize = o->size; ++		          ocontents = (bfd_byte *) bfd_malloc (o->rawsize); ++		          if (ocontents == NULL) ++			      goto error_return; ++		          if (!bfd_get_section_contents (abfd, o, ocontents, ++                                                         (file_ptr) 0, ++                                                         o->rawsize)) ++                              goto error_return; ++		          elf_section_data (o)->this_hdr.contents = ocontents; ++		        } ++		    } ++ ++                  val = bfd_get_32 (abfd, ocontents + irelscan->r_offset); ++                  if (val != irelscan->r_addend) { ++			fprintf(stderr, "%d: CORRUPT relax reloc! %x %lx\n", __LINE__, val, irelscan->r_addend); ++                  } ++ ++                  irelscan->r_addend -= calc_fixup (irelscan->r_addend, 0, sec); ++                  microblaze_bfd_write_imm_value_32 (abfd, ocontents + irelscan->r_offset, ++                                                     irelscan->r_addend); ++              } +               if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32) +                 { + 	          isym = isymbuf + ELF32_R_SYM (irelscan->r_info); +@@ -1966,7 +2095,7 @@ + 			      elf_section_data (o)->this_hdr.contents = ocontents; + 			    } + 			} +-		      irelscan->r_addend -= calc_fixup (irel->r_addend ++		      irelscan->r_addend -= calc_fixup (irelscan->r_addend + 							+ isym->st_value, + 							0, + 							sec); +@@ -3506,4 +3635,7 @@ + #define elf_backend_size_dynamic_sections       microblaze_elf_size_dynamic_sections + #define elf_backend_add_symbol_hook		microblaze_elf_add_symbol_hook +  ++#define elf_backend_grok_prstatus               microblaze_elf_grok_prstatus ++#define elf_backend_grok_psinfo                 microblaze_elf_grok_psinfo ++ + #include "elf32-target.h" +diff -Nur gdb-7.7.orig/bfd/libbfd.h gdb-7.7/bfd/libbfd.h +--- gdb-7.7.orig/bfd/libbfd.h	2014-02-06 03:21:29.000000000 +0100 ++++ gdb-7.7/bfd/libbfd.h	2014-03-26 20:02:00.000000000 +0100 +@@ -2615,6 +2615,7 @@ +   "BFD_RELOC_MICROBLAZE_32_ROSDA", +   "BFD_RELOC_MICROBLAZE_32_RWSDA", +   "BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM", ++  "BFD_RELOC_MICROBLAZE_32_NONE", +   "BFD_RELOC_MICROBLAZE_64_NONE", +   "BFD_RELOC_MICROBLAZE_64_GOTPC", +   "BFD_RELOC_MICROBLAZE_64_GOT", +diff -Nur gdb-7.7.orig/gdb/Makefile.in gdb-7.7/gdb/Makefile.in +--- gdb-7.7.orig/gdb/Makefile.in	2014-02-06 03:21:29.000000000 +0100 ++++ gdb-7.7/gdb/Makefile.in	2014-03-26 20:33:32.000000000 +0100 +@@ -849,7 +849,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 microblaze-tdep.h \ ++gdb_usleep.h jit.h xml-syscall.h microblaze-tdep.h microblaze-linux-tdep.h \ + psymtab.h psympriv.h progspace.h bfin-tdep.h ia64-hpux-tdep.h \ + amd64-darwin-tdep.h charset-list.h \ + config/djgpp/langinfo.h config/djgpp/nl_types.h darwin-nat.h \ +@@ -1547,7 +1547,7 @@ + 	m68kbsd-nat.c m68kbsd-tdep.c \ + 	m68klinux-nat.c m68klinux-tdep.c \ + 	m88k-tdep.c m88kbsd-nat.c \ +-	microblaze-tdep.c microblaze-linux-tdep.c \ ++	microblaze-tdep.c microblaze-linux-nat.c microblaze-linux-tdep.c \ + 	mingw-hdep.c \ + 	mips-linux-nat.c mips-linux-tdep.c \ + 	mips-irix-tdep.c \ +diff -Nur gdb-7.7.orig/gdb/config/microblaze/linux.mh gdb-7.7/gdb/config/microblaze/linux.mh +--- gdb-7.7.orig/gdb/config/microblaze/linux.mh	1970-01-01 01:00:00.000000000 +0100 ++++ gdb-7.7/gdb/config/microblaze/linux.mh	2014-03-24 15:52:56.000000000 +0100 +@@ -0,0 +1,10 @@ ++# Host: Microblaze, running Linux ++ ++NAT_FILE= config/nm-linux.h ++NATDEPFILES= inf-ptrace.o fork-child.o \ ++	microblaze-linux-nat.o proc-service.o linux-thread-db.o \ ++	linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o \ ++	linux-waitpid.o ++NAT_CDEPS = $(srcdir)/proc-service.list ++ ++LOADLIBES = -ldl $(RDYNAMIC) +diff -Nur gdb-7.7.orig/gdb/configure.host gdb-7.7/gdb/configure.host +--- gdb-7.7.orig/gdb/configure.host	2013-12-08 05:55:47.000000000 +0100 ++++ gdb-7.7/gdb/configure.host	2014-03-26 20:34:44.000000000 +0100 +@@ -59,6 +59,7 @@ + m68*)			gdb_host_cpu=m68k ;; + m88*)			gdb_host_cpu=m88k ;; + mips*)			gdb_host_cpu=mips ;; ++microblaze*)		gdb_host_cpu=microblaze ;; + powerpc* | rs6000)	gdb_host_cpu=powerpc ;; + sparcv9 | sparc64)	gdb_host_cpu=sparc ;; + s390*)			gdb_host_cpu=s390 ;; +@@ -133,6 +134,8 @@ + 			gdb_host=nbsd ;; + mips64*-*-openbsd*)	gdb_host=obsd64 ;; +  ++microblaze*-*linux*)    gdb_host=linux ;; ++ + powerpc-*-aix* | rs6000-*-* | powerpc64-*-aix*) + 			gdb_host=aix ;; + powerpc*-*-freebsd*)	gdb_host=fbsd ;; +diff -Nur gdb-7.7.orig/gdb/configure.tgt gdb-7.7/gdb/configure.tgt +--- gdb-7.7.orig/gdb/configure.tgt	2014-02-06 03:21:29.000000000 +0100 ++++ gdb-7.7/gdb/configure.tgt	2014-03-26 20:36:23.000000000 +0100 +@@ -340,9 +340,10 @@ +  + microblaze*-linux-*|microblaze*-*-linux*) + 	# Target: Xilinx MicroBlaze running Linux +-	gdb_target_obs="microblaze-tdep.o microblaze-linux-tdep.o microblaze-rom.o \ ++	gdb_target_obs="microblaze-tdep.o microblaze-linux-tdep.o microblaze-rom.o glibc-tdep.o \ + 			monitor.o dsrec.o solib-svr4.o symfile-mem.o linux-tdep.o" + 	gdb_sim=../sim/microblaze/libsim.a ++	build_gdbserver=yes + 	;; + microblaze*-*-*) + 	# Target: Xilinx MicroBlaze running standalone +diff -Nur gdb-7.7.orig/gdb/gdbserver/Makefile.in gdb-7.7/gdb/gdbserver/Makefile.in +--- gdb-7.7.orig/gdb/gdbserver/Makefile.in	2014-02-06 03:21:29.000000000 +0100 ++++ gdb-7.7/gdb/gdbserver/Makefile.in	2014-03-26 20:39:22.000000000 +0100 +@@ -148,6 +148,7 @@ + 	$(srcdir)/linux-ia64-low.c $(srcdir)/linux-low.c \ + 	$(srcdir)/linux-m32r-low.c \ + 	$(srcdir)/linux-m68k-low.c $(srcdir)/linux-mips-low.c \ ++	$(srcdir)/linux-microblaze-low.c \ + 	$(srcdir)/linux-nios2-low.c \ + 	$(srcdir)/linux-ppc-low.c \ + 	$(srcdir)/linux-s390-low.c \ +@@ -328,6 +329,7 @@ + 	rm -f arm-with-iwmmxt.c + 	rm -f arm-with-vfpv2.c arm-with-vfpv3.c arm-with-neon.c + 	rm -f mips-linux.c mips64-linux.c ++	rm -f microblaze-linux.c + 	rm -f nios2-linux.c + 	rm -f powerpc-32.c powerpc-32l.c powerpc-64l.c powerpc-e500l.c + 	rm -f powerpc-altivec32l.c powerpc-cell32l.c powerpc-vsx32l.c +@@ -600,6 +602,8 @@ + 	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/mips64-linux.dat mips64-linux.c + mips64-dsp-linux.c : $(srcdir)/../regformats/mips64-dsp-linux.dat $(regdat_sh) + 	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/mips64-dsp-linux.dat mips64-dsp-linux.c ++microblaze-linux.c : $(srcdir)/../regformats/reg-microblaze.dat $(regdat_sh) ++	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/reg-microblaze.dat microblaze-linux.c + nios2-linux.c :	$(srcdir)/../regformats/nios2-linux.dat $(regdat_sh) + 	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/nios2-linux.dat nios2-linux.c + powerpc-32.c : $(srcdir)/../regformats/rs6000/powerpc-32.dat $(regdat_sh) +diff -Nur gdb-7.7.orig/gdb/gdbserver/configure.srv gdb-7.7/gdb/gdbserver/configure.srv +--- gdb-7.7.orig/gdb/gdbserver/configure.srv	2014-01-08 10:23:36.000000000 +0100 ++++ gdb-7.7/gdb/gdbserver/configure.srv	2014-03-26 20:40:44.000000000 +0100 +@@ -198,6 +198,13 @@ + 			srv_linux_usrregs=yes + 			srv_linux_thread_db=yes + 			;; ++  microblaze*-*-linux*)	srv_regobj=microblaze-linux.o ++			srv_tgtobj="$srv_linux_obj linux-microblaze-low.o" ++			srv_linux_usrregs=yes ++			srv_linux_regsets=yes ++			srv_linux_thread_db=yes ++			;; ++ +   nios2*-*-linux*)	srv_regobj="nios2-linux.o" + 			srv_tgtobj="$srv_linux_obj linux-nios2-low.o" + 			srv_xmlfiles="nios2-linux.xml" +diff -Nur gdb-7.7.orig/gdb/gdbserver/linux-microblaze-low.c gdb-7.7/gdb/gdbserver/linux-microblaze-low.c +--- gdb-7.7.orig/gdb/gdbserver/linux-microblaze-low.c	1970-01-01 01:00:00.000000000 +0100 ++++ gdb-7.7/gdb/gdbserver/linux-microblaze-low.c	2014-03-26 20:41:13.000000000 +0100 +@@ -0,0 +1,228 @@ ++/* GNU/Linux/Microblaze specific low level interface, for the remote server for ++   GDB. ++   Copyright (C) 1995-2013 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 <http://www.gnu.org/licenses/>.  */ ++ ++#include "server.h" ++#include "linux-low.h" ++ ++#include <asm/ptrace.h> ++#include <sys/procfs.h> ++#include <sys/ptrace.h> ++ ++#include "gdb_proc_service.h" ++ ++static int microblaze_regmap[] = ++ {PT_GPR(0),     PT_GPR(1),     PT_GPR(2),     PT_GPR(3), ++  PT_GPR(4),     PT_GPR(5),     PT_GPR(6),     PT_GPR(7), ++  PT_GPR(8),     PT_GPR(9),     PT_GPR(10),    PT_GPR(11), ++  PT_GPR(12),    PT_GPR(13),    PT_GPR(14),    PT_GPR(15), ++  PT_GPR(16),    PT_GPR(17),    PT_GPR(18),    PT_GPR(19), ++  PT_GPR(20),    PT_GPR(21),    PT_GPR(22),    PT_GPR(23), ++  PT_GPR(24),    PT_GPR(25),    PT_GPR(26),    PT_GPR(27), ++  PT_GPR(28),    PT_GPR(29),    PT_GPR(30),    PT_GPR(31), ++  PT_PC,         PT_MSR,        PT_EAR,        PT_ESR, ++  PT_FSR ++  }; ++ ++#define microblaze_num_regs (sizeof microblaze_regmap / sizeof microblaze_regmap[0]) ++ ++/* Defined in auto-generated file microblaze-linux.c.  */ ++void init_registers_microblaze (void); ++extern const struct target_desc *tdesc_microblaze; ++ ++static int ++microblaze_cannot_store_register (int regno) ++{ ++  if (microblaze_regmap[regno] == -1 || regno == 0) ++    return 1; ++ ++  return 0; ++} ++ ++static int ++microblaze_cannot_fetch_register (int regno) ++{ ++  return 0; ++} ++ ++static CORE_ADDR ++microblaze_get_pc (struct regcache *regcache) ++{ ++  unsigned long pc; ++ ++  collect_register_by_name (regcache, "pc", &pc); ++  return (CORE_ADDR) pc; ++} ++ ++static void ++microblaze_set_pc (struct regcache *regcache, CORE_ADDR pc) ++{ ++  unsigned long newpc = pc; ++ ++  supply_register_by_name (regcache, "pc", &newpc); ++} ++ ++/* dbtrap insn */ ++/* brki r16, 0x18; */ ++static const unsigned long microblaze_breakpoint = 0xba0c0018; ++#define microblaze_breakpoint_len 4 ++ ++static int ++microblaze_breakpoint_at (CORE_ADDR where) ++{ ++  unsigned long insn; ++ ++  (*the_target->read_memory) (where, (unsigned char *) &insn, 4); ++  if (insn == microblaze_breakpoint) ++    return 1; ++  /* If necessary, recognize more trap instructions here.  GDB only uses the ++     one.  */ ++  return 0; ++} ++ ++static CORE_ADDR ++microblaze_reinsert_addr (struct regcache *regcache) ++{ ++  unsigned long pc; ++  collect_register_by_name (regcache, "r15", &pc); ++  return pc; ++} ++ ++#ifdef HAVE_PTRACE_GETREGS ++ ++static void ++microblaze_collect_ptrace_register (struct regcache *regcache, int regno, char *buf) ++{ ++  int size = register_size (regcache->tdesc, regno); ++ ++  memset (buf, 0, sizeof (long)); ++ ++  if (size < sizeof (long)) ++    collect_register (regcache, regno, buf + sizeof (long) - size); ++  else ++    collect_register (regcache, regno, buf); ++} ++ ++static void ++microblaze_supply_ptrace_register (struct regcache *regcache, ++			    int regno, const char *buf) ++{ ++  int size = register_size (regcache->tdesc, regno); ++ ++  if (regno == 0) { ++    unsigned long regbuf_0 = 0; ++    /* clobbering r0 so that it is always 0 as enforced by hardware */ ++    supply_register (regcache, regno, (const char*)®buf_0); ++  } else { ++      if (size < sizeof (long)) ++        supply_register (regcache, regno, buf + sizeof (long) - size); ++      else ++        supply_register (regcache, regno, buf); ++  } ++} ++ ++/* Provide only a fill function for the general register set.  ps_lgetregs ++   will use this for NPTL support.  */ ++ ++static void microblaze_fill_gregset (struct regcache *regcache, void *buf) ++{ ++  int i; ++ ++  for (i = 0; i < 32; i++) ++    microblaze_collect_ptrace_register (regcache, i, (char *) buf + microblaze_regmap[i]); ++} ++ ++static void ++microblaze_store_gregset (struct regcache *regcache, const void *buf) ++{ ++  int i; ++ ++  for (i = 0; i < 32; i++) ++    supply_register (regcache, i, (char *) buf + microblaze_regmap[i]); ++} ++ ++#endif /* HAVE_PTRACE_GETREGS */ ++ ++static struct regset_info microblaze_regsets[] = { ++#ifdef HAVE_PTRACE_GETREGS ++  { PTRACE_GETREGS, PTRACE_SETREGS, 0, sizeof (elf_gregset_t), GENERAL_REGS, microblaze_fill_gregset, microblaze_store_gregset }, ++  { 0, 0, 0, -1, -1, NULL, NULL }, ++#endif /* HAVE_PTRACE_GETREGS */ ++  { 0, 0, 0, -1, -1, NULL, NULL } ++}; ++ ++static struct regsets_info microblaze_regsets_info = ++  { ++    microblaze_regsets, /* regsets */ ++    0, /* num_regsets */ ++    NULL, /* disabled_regsets */ ++  }; ++ ++static struct usrregs_info microblaze_usrregs_info = ++  { ++    microblaze_num_regs, ++    microblaze_regmap, ++  }; ++ ++static struct regs_info regs_info = ++  { ++    NULL, /* regset_bitmap */ ++    µblaze_usrregs_info, ++    µblaze_regsets_info ++  }; ++ ++static const struct regs_info * ++microblaze_regs_info (void) ++{ ++  return ®s_info; ++} ++ ++static void ++microblaze_arch_setup (void) ++{ ++  current_process ()->tdesc = tdesc_microblaze; ++} ++ ++struct linux_target_ops the_low_target = { ++  microblaze_arch_setup, ++  microblaze_regs_info, ++  microblaze_cannot_fetch_register, ++  microblaze_cannot_store_register, ++  NULL, /* fetch_register */ ++  microblaze_get_pc, ++  microblaze_set_pc, ++  (const unsigned char *) µblaze_breakpoint, ++  microblaze_breakpoint_len, ++  microblaze_reinsert_addr, ++  0, ++  microblaze_breakpoint_at, ++  NULL, ++  NULL, ++  NULL, ++  NULL, ++  microblaze_collect_ptrace_register, ++  microblaze_supply_ptrace_register, ++}; ++ ++void ++initialize_low_arch (void) ++{ ++  init_registers_microblaze (); ++ ++  initialize_regsets_info (µblaze_regsets_info); ++} +\ No newline at end of file +diff -Nur gdb-7.7.orig/gdb/microblaze-linux-nat.c gdb-7.7/gdb/microblaze-linux-nat.c +--- gdb-7.7.orig/gdb/microblaze-linux-nat.c	1970-01-01 01:00:00.000000000 +0100 ++++ gdb-7.7/gdb/microblaze-linux-nat.c	2014-03-27 09:51:56.000000000 +0100 +@@ -0,0 +1,430 @@ ++/* Microblaze GNU/Linux native support. ++ ++   Copyright (C) 1988-1989, 1991-1992, 1994, 1996, 2000-2012 Free ++   Software Foundation, Inc. ++ ++   This file is part of GDB. ++ ++   This program is free software; you can redistribute it and/or modify ++   it under the terms of the GNU General Public License as published by ++   the Free Software Foundation; either version 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 "dis-asm.h" ++#include "frame.h" ++#include "trad-frame.h" ++#include "symtab.h" ++#include "value.h" ++#include "gdbcmd.h" ++#include "breakpoint.h" ++#include "inferior.h" ++#include "regcache.h" ++#include "target.h" ++#include "frame.h" ++#include "frame-base.h" ++#include "frame-unwind.h" ++#include "dwarf2-frame.h" ++#include "osabi.h" ++ ++#include "gdb_assert.h" ++#include "target-descriptions.h" ++#include "opcodes/microblaze-opcm.h" ++#include "opcodes/microblaze-dis.h" ++ ++#include "linux-nat.h" ++#include "target-descriptions.h" ++ ++#include <sys/user.h> ++#include <sys/utsname.h> ++#include <sys/procfs.h> ++#include <sys/ptrace.h> ++ ++/* Prototypes for supply_gregset etc. */ ++#include "gregset.h" ++ ++#include "microblaze-tdep.h" ++ ++#include <elf/common.h> ++#include "auxv.h" ++ ++/* Defines ps_err_e, struct ps_prochandle.  */ ++#include "gdb_proc_service.h" ++ ++/* On GNU/Linux, threads are implemented as pseudo-processes, in which ++   case we may be tracing more than one process at a time.  In that ++   case, inferior_ptid will contain the main process ID and the ++   individual thread (process) ID.  get_thread_id () is used to get ++   the thread id if it's available, and the process id otherwise.  */ ++ ++int ++get_thread_id (ptid_t ptid) ++{ ++  int tid = ptid_get_lwp (ptid); ++  if (0 == tid) ++    tid = ptid_get_pid (ptid); ++  return tid; ++} ++ ++#define GET_THREAD_ID(PTID)	get_thread_id (PTID) ++ ++/* Non-zero if our kernel may support the PTRACE_GETREGS and ++   PTRACE_SETREGS requests, for reading and writing the ++   general-purpose registers.  Zero if we've tried one of ++   them and gotten an error.  */ ++int have_ptrace_getsetregs = 1; ++ ++static int ++microblaze_register_u_addr (struct gdbarch *gdbarch, int regno) ++{ ++  int u_addr = -1; ++  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); ++  /* NOTE: cagney/2003-11-25: This is the word size used by the ptrace ++     interface, and not the wordsize of the program's ABI.  */ ++  int wordsize = sizeof (long); ++ ++  /* General purpose registers occupy 1 slot each in the buffer.  */ ++  if (regno >= MICROBLAZE_R0_REGNUM ++      && regno <= MICROBLAZE_FSR_REGNUM) ++    u_addr = (regno * wordsize); ++ ++  return u_addr; ++} ++ ++ ++static void ++fetch_register (struct regcache *regcache, int tid, int regno) ++{ ++  struct gdbarch *gdbarch = get_regcache_arch (regcache); ++  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); ++  /* This isn't really an address.  But ptrace thinks of it as one.  */ ++  CORE_ADDR regaddr = microblaze_register_u_addr (gdbarch, regno); ++  int bytes_transferred; ++  unsigned int offset;         /* Offset of registers within the u area.  */ ++  char buf[MAX_REGISTER_SIZE]; ++ ++  if (regaddr == -1) ++  { ++    memset (buf, '\0', register_size (gdbarch, regno));   /* Supply zeroes */ ++    regcache_raw_supply (regcache, regno, buf); ++    return; ++  } ++ ++  /* Read the raw register using sizeof(long) sized chunks.  On a ++     32-bit platform, 64-bit floating-point registers will require two ++     transfers.  */ ++  for (bytes_transferred = 0; ++       bytes_transferred < register_size (gdbarch, regno); ++       bytes_transferred += sizeof (long)) ++  { ++    long l; ++ ++    errno = 0; ++    l = ptrace (PTRACE_PEEKUSER, tid, (PTRACE_TYPE_ARG3) regaddr, 0); ++    regaddr += sizeof (long); ++    if (errno != 0) ++    { ++      char message[128]; ++      sprintf (message, "reading register %s (#%d)", ++               gdbarch_register_name (gdbarch, regno), regno); ++      perror_with_name (message); ++    } ++    memcpy (&buf[bytes_transferred], &l, sizeof (l)); ++  } ++ ++  /* Now supply the register.  Keep in mind that the regcache's idea ++     of the register's size may not be a multiple of sizeof ++     (long).  */ ++  if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_LITTLE) ++  { ++    /* Little-endian values are always found at the left end of the ++       bytes transferred.  */ ++    regcache_raw_supply (regcache, regno, buf); ++  } ++  else if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) ++  { ++    /* Big-endian values are found at the right end of the bytes ++       transferred.  */ ++    size_t padding = (bytes_transferred - register_size (gdbarch, regno)); ++    regcache_raw_supply (regcache, regno, buf + padding); ++  } ++  else ++    internal_error (__FILE__, __LINE__, ++                    _("fetch_register: unexpected byte order: %d"), ++                    gdbarch_byte_order (gdbarch)); ++} ++ ++/* This function actually issues the request to ptrace, telling ++   it to get all general-purpose registers and put them into the ++   specified regset. ++ ++   If the ptrace request does not exist, this function returns 0 ++   and properly sets the have_ptrace_* flag.  If the request fails, ++   this function calls perror_with_name.  Otherwise, if the request ++   succeeds, then the regcache gets filled and 1 is returned.  */ ++static int ++fetch_all_gp_regs (struct regcache *regcache, int tid) ++{ ++  struct gdbarch *gdbarch = get_regcache_arch (regcache); ++  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); ++  gdb_gregset_t gregset; ++ ++  if (ptrace (PTRACE_GETREGS, tid, 0, (void *) &gregset) < 0) ++  { ++    if (errno == EIO) ++    { ++      have_ptrace_getsetregs = 0; ++      return 0; ++    } ++    perror_with_name (_("Couldn't get general-purpose registers.")); ++  } ++ ++  supply_gregset (regcache, (const gdb_gregset_t *) &gregset); ++ ++  return 1; ++} ++ ++ ++/* This is a wrapper for the fetch_all_gp_regs function.  It is ++   responsible for verifying if this target has the ptrace request ++   that can be used to fetch all general-purpose registers at one ++   shot.  If it doesn't, then we should fetch them using the ++   old-fashioned way, which is to iterate over the registers and ++   request them one by one.  */ ++static void ++fetch_gp_regs (struct regcache *regcache, int tid) ++{ ++  struct gdbarch *gdbarch = get_regcache_arch (regcache); ++  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); ++  int i; ++ ++  if (have_ptrace_getsetregs) ++    if (fetch_all_gp_regs (regcache, tid)) ++      return; ++ ++  /* If we've hit this point, it doesn't really matter which ++     architecture we are using.  We just need to read the ++     registers in the "old-fashioned way".  */ ++  for (i = MICROBLAZE_R0_REGNUM; i <= MICROBLAZE_FSR_REGNUM; i++) ++    fetch_register (regcache, tid, i); ++} ++ ++ ++static void ++store_register (const struct regcache *regcache, int tid, int regno) ++{ ++  struct gdbarch *gdbarch = get_regcache_arch (regcache); ++  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); ++  /* This isn't really an address.  But ptrace thinks of it as one.  */ ++  CORE_ADDR regaddr = microblaze_register_u_addr (gdbarch, regno); ++  int i; ++  size_t bytes_to_transfer; ++  char buf[MAX_REGISTER_SIZE]; ++ ++  if (regaddr == -1) ++    return; ++ ++  /* First collect the register.  Keep in mind that the regcache's ++     idea of the register's size may not be a multiple of sizeof ++     (long).  */ ++  memset (buf, 0, sizeof buf); ++  bytes_to_transfer = align_up (register_size (gdbarch, regno), sizeof (long)); ++  if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_LITTLE) ++  { ++    /* Little-endian values always sit at the left end of the buffer.  */ ++    regcache_raw_collect (regcache, regno, buf); ++  } ++  else if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) ++  { ++    /* Big-endian values sit at the right end of the buffer.  */ ++    size_t padding = (bytes_to_transfer - register_size (gdbarch, regno)); ++    regcache_raw_collect (regcache, regno, buf + padding); ++  } ++ ++  for (i = 0; i < bytes_to_transfer; i += sizeof (long)) ++  { ++    long l; ++ ++    memcpy (&l, &buf[i], sizeof (l)); ++    errno = 0; ++    ptrace (PTRACE_POKEUSER, tid, (PTRACE_TYPE_ARG3) regaddr, l); ++    regaddr += sizeof (long); ++ ++    if (errno != 0) ++    { ++      char message[128]; ++      sprintf (message, "writing register %s (#%d)", ++               gdbarch_register_name (gdbarch, regno), regno); ++      perror_with_name (message); ++    } ++  } ++} ++ ++/* This function actually issues the request to ptrace, telling ++   it to store all general-purpose registers present in the specified ++   regset. ++ ++   If the ptrace request does not exist, this function returns 0 ++   and properly sets the have_ptrace_* flag.  If the request fails, ++   this function calls perror_with_name.  Otherwise, if the request ++   succeeds, then the regcache is stored and 1 is returned.  */ ++static int ++store_all_gp_regs (const struct regcache *regcache, int tid, int regno) ++{ ++  struct gdbarch *gdbarch = get_regcache_arch (regcache); ++  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); ++  gdb_gregset_t gregset; ++ ++  if (ptrace (PTRACE_GETREGS, tid, 0, (void *) &gregset) < 0) ++    { ++      if (errno == EIO) ++      { ++        have_ptrace_getsetregs = 0; ++        return 0; ++      } ++      perror_with_name (_("Couldn't get general-purpose registers.")); ++    } ++ ++  fill_gregset (regcache, &gregset, regno); ++ ++  if (ptrace (PTRACE_SETREGS, tid, 0, (void *) &gregset) < 0) ++    { ++      if (errno == EIO) ++      { ++        have_ptrace_getsetregs = 0; ++        return 0; ++      } ++      perror_with_name (_("Couldn't set general-purpose registers.")); ++    } ++ ++  return 1; ++} ++ ++/* This is a wrapper for the store_all_gp_regs function.  It is ++   responsible for verifying if this target has the ptrace request ++   that can be used to store all general-purpose registers at one ++   shot.  If it doesn't, then we should store them using the ++   old-fashioned way, which is to iterate over the registers and ++   store them one by one.  */ ++static void ++store_gp_regs (const struct regcache *regcache, int tid, int regno) ++{ ++  struct gdbarch *gdbarch = get_regcache_arch (regcache); ++  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); ++  int i; ++ ++  if (have_ptrace_getsetregs) ++    if (store_all_gp_regs (regcache, tid, regno)) ++      return; ++ ++  /* If we hit this point, it doesn't really matter which ++     architecture we are using.  We just need to store the ++     registers in the "old-fashioned way".  */ ++  for (i = MICROBLAZE_R0_REGNUM; i <= MICROBLAZE_FSR_REGNUM; i++) ++    store_register (regcache, tid, i); ++} ++ ++ ++/* Fetch registers from the child process.  Fetch all registers if ++   regno == -1, otherwise fetch all general registers or all floating ++   point registers depending upon the value of regno.  */ ++ ++static void ++microblaze_linux_fetch_inferior_registers (struct target_ops *ops, ++				    struct regcache *regcache, int regno) ++{ ++  /* Get the thread id for the ptrace call.  */ ++  int tid = GET_THREAD_ID (inferior_ptid); ++ ++  if (regno == -1) ++    fetch_gp_regs (regcache, tid); ++  else ++    fetch_register (regcache, tid, regno); ++} ++ ++/* Store registers back into the inferior.  Store all registers if ++   regno == -1, otherwise store all general registers or all floating ++   point registers depending upon the value of regno.  */ ++ ++static void ++microblaze_linux_store_inferior_registers (struct target_ops *ops, ++				    struct regcache *regcache, int regno) ++{ ++  /* Get the thread id for the ptrace call.  */ ++  int tid = GET_THREAD_ID (inferior_ptid); ++ ++  if (regno >= 0) ++    store_register (regcache, tid, regno); ++  else ++    store_gp_regs (regcache, tid, -1); ++} ++ ++/* Wrapper functions for the standard regset handling, used by ++   thread debugging.  */ ++ ++void ++fill_gregset (const struct regcache *regcache, ++	      gdb_gregset_t *gregsetp, int regno) ++{ ++  microblaze_collect_gregset (NULL, regcache, regno, gregsetp); ++} ++ ++void ++supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregsetp) ++{ ++  microblaze_supply_gregset (NULL, regcache, -1, gregsetp); ++} ++ ++void ++fill_fpregset (const struct regcache *regcache, ++	      gdb_fpregset_t *fpregsetp, int regno) ++{ ++  /* FIXME. */ ++} ++ ++void ++supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregsetp) ++{ ++  /* FIXME. */ ++} ++ ++static const struct target_desc * ++microblaze_linux_read_description (struct target_ops *ops) ++{ ++  CORE_ADDR microblaze_hwcap = 0; ++ ++  if (target_auxv_search (ops, AT_HWCAP, µblaze_hwcap) != 1) ++    return NULL; ++ ++  return NULL; ++} ++ ++ ++void _initialize_microblaze_linux_nat (void); ++ ++void ++_initialize_microblaze_linux_nat (void) ++{ ++  struct target_ops *t; ++ ++  /* Fill in the generic GNU/Linux methods.  */ ++  t = linux_target (); ++ ++  /* Add our register access methods.  */ ++  t->to_fetch_registers = microblaze_linux_fetch_inferior_registers; ++  t->to_store_registers = microblaze_linux_store_inferior_registers; ++ ++  t->to_read_description = microblaze_linux_read_description; ++ ++  /* Register the target.  */ ++  linux_nat_add_target (t); ++} +diff -Nur gdb-7.7.orig/gdb/microblaze-linux-tdep.c gdb-7.7/gdb/microblaze-linux-tdep.c +--- gdb-7.7.orig/gdb/microblaze-linux-tdep.c	2014-01-08 10:23:36.000000000 +0100 ++++ gdb-7.7/gdb/microblaze-linux-tdep.c	2014-03-26 10:11:41.000000000 +0100 +@@ -1,6 +1,6 @@ + /* Target-dependent code for Xilinx MicroBlaze. +  +-   Copyright (C) 2009-2014 Free Software Foundation, Inc. ++   Copyright (C) 2009-2013 Free Software Foundation, Inc. +  +    This file is part of GDB. +  +@@ -32,11 +32,28 @@ + #include "regset.h" + #include "solib-svr4.h" + #include "microblaze-tdep.h" ++#include "glibc-tdep.h" + #include "trad-frame.h" + #include "frame-unwind.h" + #include "tramp-frame.h" + #include "linux-tdep.h" +  ++static int microblaze_debug_flag = 0; ++ ++static void ++microblaze_debug (const char *fmt, ...) ++{ ++  if (microblaze_debug_flag) ++    { ++       va_list args; ++ ++       va_start (args, fmt); ++       printf_unfiltered ("MICROBLAZE LINUX: "); ++       vprintf_unfiltered (fmt, args); ++       va_end (args); ++    } ++} ++ + static int + microblaze_linux_memory_remove_breakpoint (struct gdbarch *gdbarch,  + 					   struct bp_target_info *bp_tgt) +@@ -46,20 +63,27 @@ +   int val; +   int bplen; +   gdb_byte old_contents[BREAKPOINT_MAX]; ++  struct cleanup *cleanup; +  +   /* Determine appropriate breakpoint contents and size for this address.  */ +   bp = gdbarch_breakpoint_from_pc (gdbarch, &addr, &bplen); +   if (bp == NULL) +     error (_("Software breakpoints not implemented for this target.")); +  ++  /* Make sure we see the memory breakpoints.  */ ++  cleanup = make_show_memory_breakpoints_cleanup (1); +   val = target_read_memory (addr, old_contents, bplen); +  +   /* If our breakpoint is no longer at the address, this means that the +      program modified the code on us, so it is wrong to put back the +      old value.  */ +   if (val == 0 && memcmp (bp, old_contents, bplen) == 0) +-    val = target_write_raw_memory (addr, bp_tgt->shadow_contents, bplen); ++  { ++      val = target_write_raw_memory (addr, bp_tgt->shadow_contents, bplen); ++      microblaze_debug ("microblaze_linux_memory_remove_breakpoint writing back to memory at addr 0x%lx\n", addr); ++  } +  ++  do_cleanups (cleanup); +   return val; + } +  +@@ -116,6 +140,43 @@ +   microblaze_linux_sighandler_cache_init + }; +  ++const struct microblaze_gregset microblaze_linux_core_gregset; ++ ++static void ++microblaze_linux_supply_core_gregset (const struct regset *regset, ++                                   struct regcache *regcache, ++                                   int regnum, const void *gregs, size_t len) ++{ ++  microblaze_supply_gregset (µblaze_linux_core_gregset, regcache, ++                             regnum, gregs); ++} ++ ++static void ++microblaze_linux_collect_core_gregset (const struct regset *regset, ++                                    const struct regcache *regcache, ++                                    int regnum, void *gregs, size_t len) ++{ ++  microblaze_collect_gregset (µblaze_linux_core_gregset, regcache, ++                              regnum, gregs); ++} ++ ++static void ++microblaze_linux_supply_core_fpregset (const struct regset *regset, ++                                    struct regcache *regcache, ++                                    int regnum, const void *fpregs, size_t len) ++{ ++  /* FIXME.  */ ++  microblaze_supply_fpregset (regcache, regnum, fpregs); ++} ++ ++static void ++microblaze_linux_collect_core_fpregset (const struct regset *regset, ++                                     const struct regcache *regcache, ++                                     int regnum, void *fpregs, size_t len) ++{ ++  /* FIXME.  */ ++  microblaze_collect_fpregset (regcache, regnum, fpregs); ++} +  + static void + microblaze_linux_init_abi (struct gdbarch_info info, +@@ -123,6 +184,10 @@ + { +   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); +  ++  tdep->gregset = regset_alloc (gdbarch, microblaze_linux_supply_core_gregset, ++                                microblaze_linux_collect_core_gregset); ++  tdep->sizeof_gregset = 200; ++ +   linux_init_abi (info, gdbarch); +  +   set_gdbarch_memory_remove_breakpoint (gdbarch, +@@ -135,6 +200,25 @@ +   /* Trampolines.  */ +   tramp_frame_prepend_unwinder (gdbarch, + 				µblaze_linux_sighandler_tramp_frame); ++ ++  /* BFD target for core files.  */ ++  if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) ++    set_gdbarch_gcore_bfd_target (gdbarch, "elf32-microblaze"); ++  else ++    set_gdbarch_gcore_bfd_target (gdbarch, "elf32-microblazeel"); ++ ++ ++  /* Shared library handling.  */ ++  set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target); ++  set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver); ++ ++  set_gdbarch_regset_from_core_section (gdbarch, ++					microblaze_regset_from_core_section); ++ ++  /* Enable TLS support.  */ ++  set_gdbarch_fetch_tls_load_module_address (gdbarch, ++                                             svr4_fetch_objfile_link_map); ++ + } +  + /* -Wmissing-prototypes */ +diff -Nur gdb-7.7.orig/gdb/microblaze-rom.c gdb-7.7/gdb/microblaze-rom.c +--- gdb-7.7.orig/gdb/microblaze-rom.c	2014-01-08 10:23:36.000000000 +0100 ++++ gdb-7.7/gdb/microblaze-rom.c	2014-03-27 08:56:48.000000000 +0100 +@@ -1,6 +1,6 @@ + /* Remote debugging interface to Xilinx MicroBlaze. +  +-   Copyright (C) 2009-2014 Free Software Foundation, Inc. ++   Copyright (C) 2009-2013 Free Software Foundation, Inc. +  +    This file is part of GDB. +  +@@ -21,7 +21,6 @@ + #include "gdbcore.h" + #include "target.h" + #include "monitor.h" +-#include <string.h> + #include "serial.h" + #include "regcache.h" +  +diff -Nur gdb-7.7.orig/gdb/microblaze-tdep.c gdb-7.7/gdb/microblaze-tdep.c +--- gdb-7.7.orig/gdb/microblaze-tdep.c	2014-02-06 03:21:29.000000000 +0100 ++++ gdb-7.7/gdb/microblaze-tdep.c	2014-03-27 08:46:21.000000000 +0100 +@@ -1,6 +1,6 @@ + /* Target-dependent code for Xilinx MicroBlaze. +  +-   Copyright (C) 2009-2014 Free Software Foundation, Inc. ++   Copyright (C) 2009-2013 Free Software Foundation, Inc. +  +    This file is part of GDB. +  +@@ -29,13 +29,13 @@ + #include "inferior.h" + #include "regcache.h" + #include "target.h" ++#include "frame.h" + #include "frame-base.h" + #include "frame-unwind.h" + #include "dwarf2-frame.h" + #include "osabi.h" +  + #include "gdb_assert.h" +-#include <string.h> + #include "target-descriptions.h" + #include "opcodes/microblaze-opcm.h" + #include "opcodes/microblaze-dis.h" +@@ -73,7 +73,8 @@ +   "rpc",  "rmsr", "rear", "resr", "rfsr", "rbtr", +   "rpvr0", "rpvr1", "rpvr2", "rpvr3", "rpvr4", "rpvr5", "rpvr6", +   "rpvr7", "rpvr8", "rpvr9", "rpvr10", "rpvr11", +-  "redr", "rpid", "rzpr", "rtlbx", "rtlbsx", "rtlblo", "rtlbhi" ++  "redr", "rpid", "rzpr", "rtlbx", "rtlbsx", "rtlblo", "rtlbhi", ++  "rslr", "rshr" + }; +  + #define MICROBLAZE_NUM_REGS ARRAY_SIZE (microblaze_register_names) +@@ -145,6 +146,14 @@ +   return sp; + } +  ++static CORE_ADDR ++microblaze_store_arguments (struct regcache *regcache, int nargs, ++			    struct value **args, CORE_ADDR sp, ++			    int struct_return, CORE_ADDR struct_addr) ++{ ++  error (_("store_arguments not implemented")); ++  return sp; ++} +  + static CORE_ADDR + microblaze_push_dummy_call (struct gdbarch *gdbarch, struct value *function, +@@ -156,14 +165,52 @@ +   return sp; + } +  ++static int ++microblaze_linux_memory_remove_breakpoint (struct gdbarch *gdbarch, ++				    struct bp_target_info *bp_tgt) ++{ ++  CORE_ADDR addr = bp_tgt->placed_address; ++  const unsigned char *bp; ++  int val; ++  int bplen; ++  gdb_byte old_contents[BREAKPOINT_MAX]; ++  struct cleanup *cleanup; ++ ++  /* Determine appropriate breakpoint contents and size for this address.  */ ++  bp = gdbarch_breakpoint_from_pc (gdbarch, &addr, &bplen); ++  if (bp == NULL) ++    error (_("Software breakpoints not implemented for this target.")); ++ ++  /* Make sure we see the memory breakpoints.  */ ++  cleanup = make_show_memory_breakpoints_cleanup (1); ++  val = target_read_memory (addr, old_contents, bplen); ++ ++  /* If our breakpoint is no longer at the address, this means that the ++     program modified the code on us, so it is wrong to put back the ++     old value.  */ ++  if (val == 0 && memcmp (bp, old_contents, bplen) == 0) ++  { ++    val = target_write_raw_memory (addr, bp_tgt->shadow_contents, bplen); ++    microblaze_debug ("microblaze_linux_memory_remove_breakpoint writing back to memory at addr 0x%lx\n", addr); ++  } ++ ++  do_cleanups (cleanup); ++  return val; ++} ++ + static const gdb_byte * + microblaze_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pc,  + 			       int *len) + { ++  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); +   static gdb_byte break_insn[] = MICROBLAZE_BREAKPOINT; ++  static gdb_byte break_insn_le[] = MICROBLAZE_BREAKPOINT_LE; +  +   *len = sizeof (break_insn); +-  return break_insn; ++  if (byte_order == BFD_ENDIAN_BIG) ++    return break_insn; ++  else ++    return break_insn_le; + } +  + /* Allocate and initialize a frame cache.  */ +@@ -178,6 +225,7 @@ +   /* Base address.  */ +   cache->base = 0; +   cache->pc = 0; ++  cache->saved_sp = 0; +  +   /* Frameless until proven otherwise.  */ +   cache->frameless_p = 1; +@@ -234,6 +282,8 @@ +   int flags = 0; +   int save_hidden_pointer_found = 0; +   int non_stack_instruction_found = 0; ++  int n_insns; ++  unsigned int *insn_block; +  +   /* Find the start of this function.  */ +   find_pc_partial_function (pc, &name, &func_addr, &func_end); +@@ -273,11 +323,18 @@ + 		    name, paddress (gdbarch, func_addr),  + 		    paddress (gdbarch, stop)); +  ++/* Do a block read to minimize the transaction with the Debug Agent */ ++  n_insns = (stop == func_addr) ? 1 : ((stop - func_addr) / INST_WORD_SIZE); ++  insn_block = calloc(n_insns, sizeof(unsigned long)); ++ ++  target_read_memory (func_addr, (void*) insn_block, n_insns * INST_WORD_SIZE ); ++ +   for (addr = func_addr; addr < stop; addr += INST_WORD_SIZE) +     { +       insn = microblaze_fetch_instruction (addr); ++      //insn = insn_block[(addr - func_addr) / INST_WORD_SIZE]; +       op = microblaze_decode_insn (insn, &rd, &ra, &rb, &imm); +-      microblaze_debug ("%s %08lx\n", paddress (gdbarch, pc), insn); ++      microblaze_debug ("%s %08lx op=%x r%d r%d imm=%d\n", paddress (gdbarch, addr), insn, op, rd, ra, imm); +  +       /* This code is very sensitive to what functions are present in the + 	 prologue.  It assumes that the (addi, addik, swi, sw) can be the  +@@ -291,6 +348,7 @@ + 	  cache->frameless_p = 0; /* Frame found.  */ + 	  save_hidden_pointer_found = 0; + 	  non_stack_instruction_found = 0; ++	  cache->register_offsets[rd] = -imm; + 	  continue; + 	} +       else if (IS_SPILL_SP(op, rd, ra)) +@@ -401,8 +459,8 @@ +      part of the prologue.  */ +   if (save_hidden_pointer_found) +     prologue_end_addr -= INST_WORD_SIZE; +- +-  return prologue_end_addr; ++    free(insn_block); ++    return prologue_end_addr; + } +  + static CORE_ADDR +@@ -452,6 +510,7 @@ +   return start_pc; + } +  ++enum { REG_UNAVAIL = (CORE_ADDR) -1 }; + /* Normal frames.  */ +  + static struct microblaze_frame_cache * +@@ -459,7 +518,7 @@ + { +   struct microblaze_frame_cache *cache; +   struct gdbarch *gdbarch = get_frame_arch (next_frame); +-  CORE_ADDR func; ++  CORE_ADDR current_pc; +   int rn; +  +   if (*this_cache) +@@ -473,9 +532,18 @@ +   for (rn = 0; rn < gdbarch_num_regs (gdbarch); rn++) +     cache->register_offsets[rn] = -1; +  +-  func = get_frame_func (next_frame); ++  cache->pc = get_frame_func (next_frame); ++  current_pc = get_frame_pc (next_frame); ++ ++  if (cache->pc) ++    microblaze_analyze_prologue (gdbarch, cache->pc, current_pc, ++	                         cache); +  +-  cache->pc = get_frame_address_in_block (next_frame); ++  cache->base = get_frame_register_unsigned (next_frame, gdbarch_sp_regnum (gdbarch)); ++  cache->saved_sp = cache->base + cache->framesize; ++ ++  cache->register_offsets[MICROBLAZE_PREV_PC_REGNUM] = cache->base; ++  cache->register_offsets[MICROBLAZE_SP_REGNUM] = cache->saved_sp; +  +   return cache; + } +@@ -501,6 +569,14 @@ +   struct microblaze_frame_cache *cache = +     microblaze_frame_cache (this_frame, this_cache); +  ++  if ((regnum == MICROBLAZE_SP_REGNUM && ++      cache->register_offsets[MICROBLAZE_SP_REGNUM]) ++      || (regnum == MICROBLAZE_FP_REGNUM && ++      cache->register_offsets[MICROBLAZE_SP_REGNUM])) ++ ++     return frame_unwind_got_constant (this_frame, regnum, ++                                       cache->register_offsets[MICROBLAZE_SP_REGNUM]); ++ +   if (cache->frameless_p) +     { +       if (regnum == MICROBLAZE_PC_REGNUM) +@@ -508,11 +584,18 @@ +       if (regnum == MICROBLAZE_SP_REGNUM) +         regnum = 1; +       return trad_frame_get_prev_register (this_frame, +-					   cache->saved_regs, regnum); ++            cache->saved_regs, regnum); +     } +-  else +-    return trad_frame_get_prev_register (this_frame, cache->saved_regs, +-					 regnum); ++ ++  if (regnum == MICROBLAZE_PC_REGNUM) ++    { ++      regnum = 15; ++      return frame_unwind_got_memory (this_frame, regnum, ++                                      cache->register_offsets[MICROBLAZE_PREV_PC_REGNUM]); ++    } ++ ++  return trad_frame_get_prev_register (this_frame, cache->saved_regs, ++					regnum); +  + } +  +@@ -536,6 +619,12 @@ +   return cache->base; + } +  ++static const struct frame_unwind * ++microblaze_frame_sniffer (struct frame_info *next_frame) ++{ ++  return µblaze_frame_unwind; ++} ++ + static const struct frame_base microblaze_frame_base = + { +   µblaze_frame_unwind, +@@ -628,6 +717,109 @@ +   return (TYPE_LENGTH (type) == 16); + } +  ++int ++microblaze_software_single_step (struct frame_info *frame) ++{ ++  struct gdbarch *arch = get_frame_arch (frame); ++  struct address_space *aspace = get_frame_address_space (frame); ++  struct gdbarch_tdep *tdep = gdbarch_tdep (arch); ++  static char le_breakp[] = MICROBLAZE_BREAKPOINT_LE; ++  static char be_breakp[] = MICROBLAZE_BREAKPOINT; ++  enum bfd_endian byte_order = gdbarch_byte_order (arch); ++  char *breakp = byte_order == BFD_ENDIAN_BIG ? be_breakp : le_breakp; ++  int ret = 0; ++ ++  /* Save the address and the values of the next_pc and the target */ ++  static struct sstep_breaks ++  { ++    CORE_ADDR address; ++    bfd_boolean valid; ++    /* Shadow contents.  */ ++    char data[INST_WORD_SIZE]; ++  } stepbreaks[2]; ++  int ii; ++ ++  if (1) ++    { ++      CORE_ADDR pc; ++      long insn; ++      enum microblaze_instr minstr; ++      bfd_boolean isunsignednum; ++      enum microblaze_instr_type insn_type; ++      short delay_slots; ++      int imm; ++      bfd_boolean immfound = FALSE; ++ ++      /* Set a breakpoint at the next instruction */ ++      /* If the current instruction is an imm, set it at the inst after */ ++      /* If the instruction has a delay slot, skip the delay slot */ ++      pc = get_frame_pc (frame); ++      insn = microblaze_fetch_instruction (pc); ++      minstr = get_insn_microblaze (insn, &isunsignednum, &insn_type, &delay_slots); ++      if (insn_type == immediate_inst) ++	{ ++	  int rd, ra, rb; ++	  immfound = TRUE; ++	  minstr = microblaze_decode_insn (insn, &rd, &ra, &rb, &imm); ++	  pc = pc + INST_WORD_SIZE; ++	  insn = microblaze_fetch_instruction (pc); ++	  minstr = get_insn_microblaze (insn, &isunsignednum, &insn_type, &delay_slots); ++	} ++      stepbreaks[0].address = pc + (delay_slots * INST_WORD_SIZE) + INST_WORD_SIZE; ++      if (insn_type != return_inst) { ++	stepbreaks[0].valid = TRUE; ++      } else { ++	stepbreaks[0].valid = FALSE; ++      } ++ ++      microblaze_debug ("single-step insn_type=%x insn=%x\n", insn_type, insn); ++      /* Now check for branch or return instructions */ ++      if (insn_type == branch_inst || insn_type == return_inst) { ++	int limm; ++	int lrd, lra, lrb; ++	int ra, rb; ++	bfd_boolean targetvalid; ++	bfd_boolean unconditionalbranch; ++	microblaze_decode_insn(insn, &lrd, &lra, &lrb, &limm); ++	if (lra >= 0 && lra < MICROBLAZE_NUM_REGS) ++	  ra = get_frame_register_unsigned (frame, lra); ++	else ++	  ra = 0; ++	if (lrb >= 0 && lrb < MICROBLAZE_NUM_REGS) ++	  rb = get_frame_register_unsigned (frame, lrb); ++	else ++	  rb = 0; ++ ++	stepbreaks[1].address = microblaze_get_target_address (insn, immfound, imm, pc, ra, rb, &targetvalid, &unconditionalbranch); ++	microblaze_debug ("single-step uncondbr=%d targetvalid=%d target=%x\n", unconditionalbranch, targetvalid, stepbreaks[1].address); ++ ++	if (unconditionalbranch) ++	  stepbreaks[0].valid = FALSE; /* This is a unconditional branch: will not come to the next address */ ++	if (targetvalid && (stepbreaks[0].valid == FALSE || ++			    (stepbreaks[0].address != stepbreaks[1].address)) ++			&& (stepbreaks[1].address != pc)) { ++	  stepbreaks[1].valid = TRUE; ++	} else { ++	  stepbreaks[1].valid = FALSE; ++	} ++      } else { ++	stepbreaks[1].valid = FALSE; ++      } ++ ++      /* Insert the breakpoints */ ++      for (ii = 0; ii < 2; ++ii) ++        { ++ ++          /* ignore invalid breakpoint. */ ++          if (stepbreaks[ii].valid) { ++            insert_single_step_breakpoint (arch, aspace, stepbreaks[ii].address); ++            ret = 1; ++	  } ++	} ++    } ++    return ret; ++} ++ + static void + microblaze_write_pc (struct regcache *regcache, CORE_ADDR pc) + { +@@ -664,6 +856,70 @@ +   return dwarf2_to_reg_map[reg]; + } +  ++ ++void ++microblaze_supply_gregset (const struct microblaze_gregset *gregset, ++                        struct regcache *regcache, ++                        int regnum, const void *gregs) ++{ ++  unsigned int *regs = gregs; ++  if (regnum >= 0) ++    regcache_raw_supply (regcache, regnum, regs + regnum); ++ ++  if (regnum == -1) { ++    int i; ++ ++    for (i = 0; i < 50; i++) { ++      regcache_raw_supply (regcache, i, regs + i); ++    } ++  } ++} ++ ++ ++void ++microblaze_collect_gregset (const struct microblaze_gregset *gregset, ++                         const struct regcache *regcache, ++                         int regnum, void *gregs) ++{ ++   /* FIXME.  */ ++} ++ ++void ++microblaze_supply_fpregset (struct regcache *regcache, ++                         int regnum, const void *fpregs) ++{ ++   /* FIXME.  */ ++} ++ ++void ++microblaze_collect_fpregset (const struct regcache *regcache, ++                          int regnum, void *fpregs) ++{ ++   /* FIXME.  */ ++} ++ ++ ++/* Return the appropriate register set for the core section identified ++   by SECT_NAME and SECT_SIZE.  */ ++ ++const struct regset * ++microblaze_regset_from_core_section (struct gdbarch *gdbarch, ++                                     const char *sect_name, size_t sect_size) ++{ ++  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); ++ ++  microblaze_debug ("microblaze_regset_from_core_section, sect_name = %s\n", sect_name); ++ ++  if (strcmp (sect_name, ".reg") == 0 && sect_size >= tdep->sizeof_gregset) ++    return tdep->gregset; ++ ++  if (strcmp (sect_name, ".reg2") == 0 && sect_size >= tdep->sizeof_fpregset) ++    return tdep->fpregset; ++ ++  microblaze_debug ("microblaze_regset_from_core_section returning null :-( \n"); ++  return NULL; ++} ++ + static struct gdbarch * + microblaze_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) + { +@@ -679,6 +935,11 @@ +   tdep = XMALLOC (struct gdbarch_tdep); +   gdbarch = gdbarch_alloc (&info, tdep); +  ++  tdep->gregset = NULL; ++  tdep->sizeof_gregset = 0; ++  tdep->fpregset = NULL; ++  tdep->sizeof_fpregset = 0; ++ +   set_gdbarch_long_double_bit (gdbarch, 128); +  +   set_gdbarch_num_regs (gdbarch, MICROBLAZE_NUM_REGS); +@@ -706,7 +967,10 @@ +   /* Stack grows downward.  */ +   set_gdbarch_inner_than (gdbarch, core_addr_lessthan); +  ++  set_gdbarch_memory_remove_breakpoint (gdbarch, microblaze_linux_memory_remove_breakpoint); ++ +   set_gdbarch_breakpoint_from_pc (gdbarch, microblaze_breakpoint_from_pc); ++  set_gdbarch_software_single_step (gdbarch, microblaze_software_single_step); +  +   set_gdbarch_frame_args_skip (gdbarch, 8); +  +@@ -725,6 +989,13 @@ +   dwarf2_append_unwinders (gdbarch); +   frame_unwind_append_unwinder (gdbarch, µblaze_frame_unwind); +   frame_base_append_sniffer (gdbarch, dwarf2_frame_base_sniffer); ++  //frame_base_append_sniffer (gdbarch, microblaze_frame_sniffer); ++ ++  /* If we have register sets, enable the generic core file support.  */ ++  if (tdep->gregset) { ++      set_gdbarch_regset_from_core_section (gdbarch, ++                                          microblaze_regset_from_core_section); ++  } +  +   return gdbarch; + } +diff -Nur gdb-7.7.orig/gdb/microblaze-tdep.h gdb-7.7/gdb/microblaze-tdep.h +--- gdb-7.7.orig/gdb/microblaze-tdep.h	2014-01-08 10:23:36.000000000 +0100 ++++ gdb-7.7/gdb/microblaze-tdep.h	2014-03-26 10:11:41.000000000 +0100 +@@ -1,6 +1,6 @@ + /* Target-dependent code for Xilinx MicroBlaze. +  +-   Copyright (C) 2009-2014 Free Software Foundation, Inc. ++   Copyright (C) 2009-2013 Free Software Foundation, Inc. +  +    This file is part of GDB. +  +@@ -22,8 +22,22 @@ +  +  + /* Microblaze architecture-specific information.  */ ++struct microblaze_gregset ++{ ++   unsigned int gregs[32]; ++   unsigned int fpregs[32]; ++   unsigned int pregs[16]; ++}; ++ + struct gdbarch_tdep + { ++  int dummy;		// declare something. ++ ++  /* Register sets.  */ ++  struct regset *gregset; ++  size_t sizeof_gregset; ++  struct regset *fpregset; ++  size_t sizeof_fpregset; + }; +  + struct microblaze_frame_cache +@@ -42,7 +56,8 @@ +   int fp_regnum; +  +   /* Offsets to saved registers.  */ +-  int register_offsets[57];	/* Must match MICROBLAZE_NUM_REGS.  */ ++  int register_offsets[59];	/* Must match MICROBLAZE_NUM_REGS.  */ ++  CORE_ADDR saved_sp; +  +   /* Table of saved registers.  */ +   struct trad_frame_saved_reg *saved_regs; +@@ -66,11 +81,11 @@ +   MICROBLAZE_R12_REGNUM, +   MICROBLAZE_R13_REGNUM, +   MICROBLAZE_R14_REGNUM, +-  MICROBLAZE_R15_REGNUM, ++  MICROBLAZE_R15_REGNUM, MICROBLAZE_PREV_PC_REGNUM = MICROBLAZE_R15_REGNUM, +   MICROBLAZE_R16_REGNUM, +   MICROBLAZE_R17_REGNUM, +   MICROBLAZE_R18_REGNUM, +-  MICROBLAZE_R19_REGNUM, ++  MICROBLAZE_R19_REGNUM, MICROBLAZE_FP_REGNUM = MICROBLAZE_R19_REGNUM, +   MICROBLAZE_R20_REGNUM, +   MICROBLAZE_R21_REGNUM, +   MICROBLAZE_R22_REGNUM, +@@ -107,7 +122,9 @@ +   MICROBLAZE_RTLBX_REGNUM, +   MICROBLAZE_RTLBSX_REGNUM, +   MICROBLAZE_RTLBLO_REGNUM, +-  MICROBLAZE_RTLBHI_REGNUM ++  MICROBLAZE_RTLBHI_REGNUM, ++  MICROBLAZE_SLR_REGNUM, ++  MICROBLAZE_SHR_REGNUM + }; +  + /* All registers are 32 bits.  */ +@@ -115,6 +132,21 @@ +  + /* MICROBLAZE_BREAKPOINT defines the breakpoint that should be used. +    Only used for native debugging.  */ +-#define MICROBLAZE_BREAKPOINT {0xb9, 0xcc, 0x00, 0x60} ++#define MICROBLAZE_BREAKPOINT {0xba, 0x0c, 0x00, 0x18} ++#define MICROBLAZE_BREAKPOINT_LE {0x18, 0x00, 0x0c, 0xba} ++ ++extern void microblaze_supply_gregset (const struct microblaze_gregset *gregset, ++                                    struct regcache *regcache, ++                                    int regnum, const void *gregs); ++extern void microblaze_collect_gregset (const struct microblaze_gregset *gregset, ++                                     const struct regcache *regcache, ++                                     int regnum, void *gregs); ++extern void microblaze_supply_fpregset (struct regcache *regcache, ++                                     int regnum, const void *fpregs); ++extern void microblaze_collect_fpregset (const struct regcache *regcache, ++                                      int regnum, void *fpregs); ++ ++extern const struct regset * microblaze_regset_from_core_section (struct gdbarch *gdbarch, ++                                     const char *sect_name, size_t sect_size); +  + #endif /* microblaze-tdep.h */ +diff -Nur gdb-7.7.orig/gdb/regformats/reg-microblaze.dat gdb-7.7/gdb/regformats/reg-microblaze.dat +--- gdb-7.7.orig/gdb/regformats/reg-microblaze.dat	1970-01-01 01:00:00.000000000 +0100 ++++ gdb-7.7/gdb/regformats/reg-microblaze.dat	2014-03-26 20:43:54.000000000 +0100 +@@ -0,0 +1,41 @@ ++name:microblaze ++expedite:r1,pc ++32:r0 ++32:r1 ++32:r2 ++32:r3 ++32:r4 ++32:r5 ++32:r6 ++32:r7 ++32:r8 ++32:r9 ++32:r10 ++32:r11 ++32:r12 ++32:r13 ++32:r14 ++32:r15 ++32:r16 ++32:r17 ++32:r18 ++32:r19 ++32:r20 ++32:r21 ++32:r22 ++32:r23 ++32:r24 ++32:r25 ++32:r26 ++32:r27 ++32:r28 ++32:r29 ++32:r30 ++32:r31 ++32:pc ++32:msr ++32:ear ++32:esr ++32:fsr ++32:slr ++32:shr +diff -Nur gdb-7.7.orig/include/elf/microblaze.h gdb-7.7/include/elf/microblaze.h +--- gdb-7.7.orig/include/elf/microblaze.h	2013-12-08 05:11:51.000000000 +0100 ++++ gdb-7.7/include/elf/microblaze.h	2014-03-26 20:44:34.000000000 +0100 +@@ -58,6 +58,7 @@ +   RELOC_NUMBER (R_MICROBLAZE_TLSDTPREL64, 27)   /* TLS Offset Within TLS Block */ +   RELOC_NUMBER (R_MICROBLAZE_TLSGOTTPREL32, 28) /* TLS Offset From Thread Pointer */ +   RELOC_NUMBER (R_MICROBLAZE_TLSTPREL32, 29)    /* TLS Offset From Thread Pointer */ ++  RELOC_NUMBER (R_MICROBLAZE_32_NONE, 30) +     + END_RELOC_NUMBERS (R_MICROBLAZE_max) +  +diff -Nur gdb-7.7.orig/opcodes/microblaze-opc.h gdb-7.7/opcodes/microblaze-opc.h +--- gdb-7.7.orig/opcodes/microblaze-opc.h	2013-12-08 05:11:52.000000000 +0100 ++++ gdb-7.7/opcodes/microblaze-opc.h	2014-03-26 20:45:46.000000000 +0100 +@@ -91,6 +91,7 @@ + #define OPCODE_MASK_H3  0xFC000600  /* High 6 bits and bits 21, 22.  */   + #define OPCODE_MASK_H32 0xFC00FC00  /* High 6 bits and bit 16-21.  */ + #define OPCODE_MASK_H34B 0xFC0000FF /* High 6 bits and low 8 bits.  */ ++#define OPCODE_MASK_H35B 0xFC0004FF /* High 6 bits and low 9 bits.  */ + #define OPCODE_MASK_H34C 0xFC0007E0 /* High 6 bits and bits 21-26.  */ +  + /* New Mask for msrset, msrclr insns.  */ +@@ -101,7 +102,7 @@ + #define DELAY_SLOT 1 + #define NO_DELAY_SLOT 0 +  +-#define MAX_OPCODES 289 ++#define MAX_OPCODES 291 +  + struct op_code_struct + { +@@ -174,7 +175,9 @@ +   {"wic",   INST_TYPE_R1_R2_SPECIAL, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x90000068, OPCODE_MASK_H34B, wic, special_inst }, +   {"wdc",   INST_TYPE_R1_R2_SPECIAL, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x90000064, OPCODE_MASK_H34B, wdc, special_inst }, +   {"wdc.clear", INST_TYPE_R1_R2_SPECIAL, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x90000066, OPCODE_MASK_H34B, wdcclear, special_inst }, ++  {"wdc.ext.clear", INST_TYPE_R1_R2_SPECIAL, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x90000466, OPCODE_MASK_H35B, wdcextclear, special_inst }, +   {"wdc.flush", INST_TYPE_R1_R2_SPECIAL, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x90000074, OPCODE_MASK_H34B, wdcflush, special_inst }, ++  {"wdc.ext.flush", INST_TYPE_R1_R2_SPECIAL, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x90000476, OPCODE_MASK_H35B, wdcextflush, special_inst }, +   {"mts",   INST_TYPE_SPECIAL_R1, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_MTS, 0x9400C000, OPCODE_MASK_H13S, mts, special_inst }, +   {"mfs",   INST_TYPE_RD_SPECIAL, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_MFS, 0x94008000, OPCODE_MASK_H23S, mfs, special_inst }, +   {"br",    INST_TYPE_R2, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x98000000, OPCODE_MASK_H124, br, branch_inst }, +diff -Nur gdb-7.7.orig/opcodes/microblaze-opcm.h gdb-7.7/opcodes/microblaze-opcm.h +--- gdb-7.7.orig/opcodes/microblaze-opcm.h	2013-12-08 05:11:52.000000000 +0100 ++++ gdb-7.7/opcodes/microblaze-opcm.h	2014-03-26 20:45:46.000000000 +0100 +@@ -31,9 +31,9 @@ +   idiv, idivu, bsll, bsra, bsrl, get, put, nget, nput, cget, cput, +   ncget, ncput, muli, bslli, bsrai, bsrli, mului, or, and, xor, +   andn, pcmpbf, pcmpbc, pcmpeq, pcmpne, sra, src, srl, sext8, sext16,  +-  wic, wdc, wdcclear, wdcflush, mts, mfs, mbar, br, brd, +-  brld, bra, brad, brald, microblaze_brk, beq, beqd, bne, bned, blt, +-  bltd, ble, bled, bgt, bgtd, bge, bged, ori, andi, xori, andni, ++  wic, wdc, wdcclear, wdcextclear, wdcflush, wdcextflush, mts, mfs, mbar, ++  br, brd, brld, bra, brad, brald, microblaze_brk, beq, beqd, bne, bned, ++  blt, bltd, ble, bled, bgt, bgtd, bge, bged, ori, andi, xori, andni, +   imm, rtsd, rtid, rtbd, rted, bri, brid, brlid, brai, braid, bralid, +   brki, beqi, beqid, bnei, bneid, blti, bltid, blei, bleid, bgti, +   bgtid, bgei, bgeid, lbu, lbur, lhu, lhur, lw, lwr, lwx, sb, sbr, sh,  | 
