aboutsummaryrefslogtreecommitdiffstats
path: root/recipes-microblaze
diff options
context:
space:
mode:
Diffstat (limited to 'recipes-microblaze')
-rw-r--r--recipes-microblaze/binutils/binutils-cross-canadian_2.24.bbappend1
-rw-r--r--recipes-microblaze/binutils/binutils-cross_2.24.bbappend1
-rw-r--r--recipes-microblaze/binutils/binutils-crosssdk_2.24.bbappend1
-rw-r--r--recipes-microblaze/binutils/binutils-microblaze-2.24.inc11
-rw-r--r--recipes-microblaze/binutils/binutils_2.24.bbappend1
-rw-r--r--recipes-microblaze/binutils/files/Add-mlittle-endian-and-mbig-endian.patch64
-rw-r--r--recipes-microblaze/binutils/files/Add-wdc.ext.clear-and-wdc.ext.flush.patch67
-rw-r--r--recipes-microblaze/binutils/files/Disable-the-warning-message-for-eh_frame_hdr.patch33
-rw-r--r--recipes-microblaze/binutils/files/Fix-relaxation-of-assembler-resolved-reference.patch75
-rw-r--r--recipes-microblaze/binutils/files/Fixup-debug_loc-sections-after-linker-relaxati.patch228
-rw-r--r--recipes-microblaze/binutils/files/upstream-change-to-garbage-collection-s.patch38
-rw-r--r--recipes-microblaze/gcc/files/0001-Patch-microblaze-Enable-DWARF-exception-handling-sup.patch158
-rw-r--r--recipes-microblaze/gcc/files/0002-Patch-microblaze-Add-4-byte-implementation-for-atomi.patch157
-rw-r--r--recipes-microblaze/gcc/files/0003-Patch-microblaze-Extend-jump-insn-to-accept-bri-to-S.patch35
-rw-r--r--recipes-microblaze/gcc/files/0005-Patch-microblaze-Add-fstack-usage-support.patch30
-rw-r--r--recipes-microblaze/gcc/files/0006-Patch-microblaze-Remove-SECONDARY_MEMORY_NEEDED.patch35
-rw-r--r--recipes-microblaze/gcc/files/0007-Patch-microblaze-Add-SIZE_TYPE-and-PTRDIFF_TYPE-to-m.patch39
-rw-r--r--recipes-microblaze/gcc/files/0008-Patch-microblaze-Add-branch_compare-instruction.patch224
-rw-r--r--recipes-microblaze/gcc/files/0462b5f-2014-02-23-David-Holsgrove-david.holsgrove.patch108
-rw-r--r--recipes-microblaze/gcc/files/Patch-microblaze-Fix-bswaphi2-implementation.patch44
-rw-r--r--recipes-microblaze/gcc/files/Patch-microblaze-cstoresf4-add-mode-and-ordered_comp.patch44
-rw-r--r--recipes-microblaze/gcc/files/gcc-Cherry-pick-mainline-patch-to-resolve-MB-k.patch110
-rw-r--r--recipes-microblaze/gcc/gcc-microblaze-4.8.inc16
-rw-r--r--recipes-microblaze/gcc/gcc-source_4.8.bbappend1
-rw-r--r--recipes-microblaze/gdb/files/0001-Patch-microblaze-Add-wdc.ext.clear-and-wdc.ext.flush.patch69
-rw-r--r--recipes-microblaze/gdb/files/0003-Patch-microblaze-Initial-port-of-microblaze-core-rea.patch384
-rw-r--r--recipes-microblaze/gdb/files/0004-Patch-microblaze-Communicate-in-larger-blocks-with-t.patch67
-rw-r--r--recipes-microblaze/gdb/files/0005-Patch-microblaze-Add-mb-singlestepping.patch200
-rw-r--r--recipes-microblaze/gdb/files/0006-Patch-microblaze-Add-initial-port-of-linux-gdbserver.patch553
-rw-r--r--recipes-microblaze/gdb/files/0007-Patch-microblaze-Add-slr-and-shr-regs-and-little-end.patch82
-rw-r--r--recipes-microblaze/gdb/files/0008-Patch-microblaze-Added-Backtrace-support-to-GDB.patch156
-rw-r--r--recipes-microblaze/gdb/files/0009-Patch-microblaze-Initial-support-for-native-gdb.patch495
-rw-r--r--recipes-microblaze/gdb/files/0010-Patch-gdb-Robustify-inline-function-support.patch43
-rw-r--r--recipes-microblaze/gdb/files/0011-Patch-gdb-Fix-debug-message-when-register-is-unavail.patch43
-rw-r--r--recipes-microblaze/gdb/files/0012-LOCAL-Disable-the-warning-message-for-eh_frame_hdr.patch34
-rw-r--r--recipes-microblaze/gdb/files/0013-LOCAL-Fix-relaxation-of-assembler-resolved-reference.patch64
-rw-r--r--recipes-microblaze/gdb/files/0014-LOCAL-Fixup-debug_loc-sections-after-linker-relaxati.patch192
-rw-r--r--recipes-microblaze/gdb/files/0015-LOCAL-upstream-change-to-garbage-collection-sweep-ca.patch40
-rw-r--r--recipes-microblaze/gdb/gdb-7.7.1.inc11
-rw-r--r--recipes-microblaze/gdb/gdb-cross-canadian_7.7.1.bb4
-rw-r--r--recipes-microblaze/gdb/gdb-cross_7.7.1.bb3
-rw-r--r--recipes-microblaze/gdb/gdb-microblaze-7.7.inc22
-rw-r--r--recipes-microblaze/gdb/gdb_7.7.1.bb29
-rw-r--r--recipes-microblaze/gnu-config/files/microblazeel.patch68
-rw-r--r--recipes-microblaze/gnu-config/gnu-config_20120814.bbappend6
-rw-r--r--recipes-microblaze/qemu/qemu_%.bbappend2
-rw-r--r--recipes-microblaze/shadow/shadow_%.bbappend14
47 files changed, 4102 insertions, 0 deletions
diff --git a/recipes-microblaze/binutils/binutils-cross-canadian_2.24.bbappend b/recipes-microblaze/binutils/binutils-cross-canadian_2.24.bbappend
new file mode 100644
index 00000000..e42e7a60
--- /dev/null
+++ b/recipes-microblaze/binutils/binutils-cross-canadian_2.24.bbappend
@@ -0,0 +1 @@
+require binutils-microblaze-${PV}.inc
diff --git a/recipes-microblaze/binutils/binutils-cross_2.24.bbappend b/recipes-microblaze/binutils/binutils-cross_2.24.bbappend
new file mode 100644
index 00000000..e42e7a60
--- /dev/null
+++ b/recipes-microblaze/binutils/binutils-cross_2.24.bbappend
@@ -0,0 +1 @@
+require binutils-microblaze-${PV}.inc
diff --git a/recipes-microblaze/binutils/binutils-crosssdk_2.24.bbappend b/recipes-microblaze/binutils/binutils-crosssdk_2.24.bbappend
new file mode 100644
index 00000000..e42e7a60
--- /dev/null
+++ b/recipes-microblaze/binutils/binutils-crosssdk_2.24.bbappend
@@ -0,0 +1 @@
+require binutils-microblaze-${PV}.inc
diff --git a/recipes-microblaze/binutils/binutils-microblaze-2.24.inc b/recipes-microblaze/binutils/binutils-microblaze-2.24.inc
new file mode 100644
index 00000000..71b50ee8
--- /dev/null
+++ b/recipes-microblaze/binutils/binutils-microblaze-2.24.inc
@@ -0,0 +1,11 @@
+
+# Add MicroBlaze Patches
+FILESEXTRAPATHS_append := "${THISDIR}/files:"
+SRC_URI_append += " \
+ file://Add-wdc.ext.clear-and-wdc.ext.flush.patch \
+ file://Add-mlittle-endian-and-mbig-endian.patch \
+ file://Disable-the-warning-message-for-eh_frame_hdr.patch \
+ file://Fix-relaxation-of-assembler-resolved-reference.patch \
+ file://Fixup-debug_loc-sections-after-linker-relaxati.patch \
+ file://upstream-change-to-garbage-collection-s.patch \
+ "
diff --git a/recipes-microblaze/binutils/binutils_2.24.bbappend b/recipes-microblaze/binutils/binutils_2.24.bbappend
new file mode 100644
index 00000000..e42e7a60
--- /dev/null
+++ b/recipes-microblaze/binutils/binutils_2.24.bbappend
@@ -0,0 +1 @@
+require binutils-microblaze-${PV}.inc
diff --git a/recipes-microblaze/binutils/files/Add-mlittle-endian-and-mbig-endian.patch b/recipes-microblaze/binutils/files/Add-mlittle-endian-and-mbig-endian.patch
new file mode 100644
index 00000000..984fda3f
--- /dev/null
+++ b/recipes-microblaze/binutils/files/Add-mlittle-endian-and-mbig-endian.patch
@@ -0,0 +1,64 @@
+From: nagaraju <nmekala@xilix.com>
+Date: Tue, 19 Mar 2013 17:18:23 +0530
+Subject: Add mlittle-endian and mbig-endian flags
+
+Added support in gas for mlittle-endian and mbig-endian flags
+as options.
+
+Updated show usage for MicroBlaze specific assembler options
+to include new entries.
+
+Signed-off-by:nagaraju <nmekala@xilix.com>
+Signed-off-by: David Holsgrove <david.holsgrove@xilinx.com>
+Upstream-Status: Pending
+---
+ gas/config/tc-microblaze.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/gas/config/tc-microblaze.c b/gas/config/tc-microblaze.c
+index 872737b..b241743 100644
+--- a/gas/config/tc-microblaze.c
++++ b/gas/config/tc-microblaze.c
+@@ -37,6 +37,8 @@
+
+ #define OPTION_EB (OPTION_MD_BASE + 0)
+ #define OPTION_EL (OPTION_MD_BASE + 1)
++#define OPTION_LITTLE (OPTION_MD_BASE + 2)
++#define OPTION_BIG (OPTION_MD_BASE + 3)
+
+ void microblaze_generate_symbol (char *sym);
+ static bfd_boolean check_spl_reg (unsigned *);
+@@ -1824,6 +1826,8 @@ struct option md_longopts[] =
+ {
+ {"EB", no_argument, NULL, OPTION_EB},
+ {"EL", no_argument, NULL, OPTION_EL},
++ {"mlittle-endian", no_argument, NULL, OPTION_LITTLE},
++ {"mbig-endian", no_argument, NULL, OPTION_BIG},
+ { NULL, no_argument, NULL, 0}
+ };
+
+@@ -2457,9 +2461,11 @@ md_parse_option (int c, char * arg ATTRIBUTE_UNUSED)
+ switch (c)
+ {
+ case OPTION_EB:
++ case OPTION_BIG:
+ target_big_endian = 1;
+ break;
+ case OPTION_EL:
++ case OPTION_LITTLE:
+ target_big_endian = 0;
+ break;
+ default:
+@@ -2474,6 +2480,9 @@ md_show_usage (FILE * stream ATTRIBUTE_UNUSED)
+ /* fprintf(stream, _("\
+ MicroBlaze options:\n\
+ -noSmall Data in the comm and data sections do not go into the small data section\n")); */
++ fprintf (stream, _(" MicroBlaze specific assembler options:\n"));
++ fprintf (stream, " -%-23s%s\n", "mbig-endian", N_("assemble for a big endian cpu"));
++ fprintf (stream, " -%-23s%s\n", "mlittle-endian", N_("assemble for a little endian cpu"));
+ }
+
+
+--
+1.7.9.5
+
diff --git a/recipes-microblaze/binutils/files/Add-wdc.ext.clear-and-wdc.ext.flush.patch b/recipes-microblaze/binutils/files/Add-wdc.ext.clear-and-wdc.ext.flush.patch
new file mode 100644
index 00000000..cb58f603
--- /dev/null
+++ b/recipes-microblaze/binutils/files/Add-wdc.ext.clear-and-wdc.ext.flush.patch
@@ -0,0 +1,67 @@
+From: David Holsgrove <david.holsgrove@xilinx.com>
+Date: Wed, 8 May 2013 11:03:36 +1000
+Subject: Add wdc.ext.clear and wdc.ext.flush insns
+
+Added two new instructions, wdc.ext.clear and wdc.ext.flush,
+to enable MicroBlaze to flush an external cache, which is
+used with the new coherency support for multiprocessing.
+
+Signed-off-by:nagaraju <nmekala@xilix.com>
+Signed-off-by: David Holsgrove <david.holsgrove@xilinx.com>
+Upstream-Status: Pending
+---
+ opcodes/microblaze-opc.h | 5 ++++-
+ opcodes/microblaze-opcm.h | 6 +++---
+ 2 files changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/opcodes/microblaze-opc.h b/opcodes/microblaze-opc.h
+index e9da12a..dd56ab5 100644
+--- a/opcodes/microblaze-opc.h
++++ b/opcodes/microblaze-opc.h
+@@ -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 @@ struct op_code_struct
+ {"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 --git a/opcodes/microblaze-opcm.h b/opcodes/microblaze-opcm.h
+index 124cdec..8e531f9 100644
+--- a/opcodes/microblaze-opcm.h
++++ b/opcodes/microblaze-opcm.h
+@@ -31,9 +31,9 @@ enum microblaze_instr
+ 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,
+--
+1.7.9.5
+
diff --git a/recipes-microblaze/binutils/files/Disable-the-warning-message-for-eh_frame_hdr.patch b/recipes-microblaze/binutils/files/Disable-the-warning-message-for-eh_frame_hdr.patch
new file mode 100644
index 00000000..f6616a1b
--- /dev/null
+++ b/recipes-microblaze/binutils/files/Disable-the-warning-message-for-eh_frame_hdr.patch
@@ -0,0 +1,33 @@
+From: "Edgar E. Iglesias" <edgar.iglesias@gmail.com>
+Date: Fri, 22 Jun 2012 01:20:20 +0200
+Subject: Disable the warning message for eh_frame_hdr
+
+Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
+Upstream-Status: Pending
+---
+ bfd/elf-eh-frame.c | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/bfd/elf-eh-frame.c b/bfd/elf-eh-frame.c
+index a75d806..de69cef 100644
+--- a/bfd/elf-eh-frame.c
++++ b/bfd/elf-eh-frame.c
+@@ -913,9 +913,12 @@ _bfd_elf_parse_eh_frame (bfd *abfd, struct bfd_link_info *info,
+ goto success;
+
+ free_no_table:
+- (*info->callbacks->einfo)
+- (_("%P: error in %B(%A); no .eh_frame_hdr table will be created.\n"),
+- abfd, sec);
++ /* FIXME: Remove the microblaze specifics when relaxing gets fixed. */
++ if (bfd_get_arch(abfd) != bfd_arch_microblaze) {
++ (*info->callbacks->einfo)
++ (_("%P: error in %B(%A); no .eh_frame_hdr table will be created.\n"),
++ abfd, sec);
++ }
+ hdr_info->table = FALSE;
+ if (sec_info)
+ free (sec_info);
+--
+1.7.9.5
+
diff --git a/recipes-microblaze/binutils/files/Fix-relaxation-of-assembler-resolved-reference.patch b/recipes-microblaze/binutils/files/Fix-relaxation-of-assembler-resolved-reference.patch
new file mode 100644
index 00000000..fb3ff355
--- /dev/null
+++ b/recipes-microblaze/binutils/files/Fix-relaxation-of-assembler-resolved-reference.patch
@@ -0,0 +1,75 @@
+From: "Edgar E. Iglesias" <edgar.iglesias@gmail.com>
+Date: Tue, 14 Feb 2012 01:00:22 +0100
+Subject: Fix relaxation of assembler resolved references
+
+Upstream-Status: Pending
+---
+ bfd/elf32-microblaze.c | 39 +++++++++++++++++++++++++++++++++++++++
+ gas/config/tc-microblaze.c | 1 +
+ 2 files changed, 40 insertions(+)
+
+diff --git a/bfd/elf32-microblaze.c b/bfd/elf32-microblaze.c
+index 502e3c9..9de2479 100644
+--- a/bfd/elf32-microblaze.c
++++ b/bfd/elf32-microblaze.c
+@@ -1906,6 +1906,45 @@ microblaze_elf_relax_section (bfd *abfd,
+ irelscanend = irelocs + o->reloc_count;
+ for (irelscan = irelocs; irelscan < irelscanend; irelscan++)
+ {
++ if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_NONE)
++ {
++ unsigned int val;
++
++ isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
++
++ /* 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;
++ }
++ }
++
++ irelscan->r_addend -= calc_fixup (irelscan->r_addend
++ + isym->st_value, sec);
++ val = bfd_get_32 (abfd, ocontents + irelscan->r_offset);
++ microblaze_bfd_write_imm_value_32 (abfd, ocontents + irelscan->r_offset,
++ irelscan->r_addend);
++ }
++ if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_64_NONE) {
++ fprintf(stderr, "Unhandled NONE 64\n");
++ }
+ if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32)
+ {
+ isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
+diff --git a/gas/config/tc-microblaze.c b/gas/config/tc-microblaze.c
+index b241743..7dd5895 100644
+--- a/gas/config/tc-microblaze.c
++++ b/gas/config/tc-microblaze.c
+@@ -2169,6 +2169,7 @@ md_apply_fix (fixS * fixP,
+ else
+ fixP->fx_r_type = BFD_RELOC_NONE;
+ fixP->fx_addsy = section_symbol (absolute_section);
++ fixP->fx_done = 0;
+ }
+ return;
+ }
+--
+1.7.9.5
+
diff --git a/recipes-microblaze/binutils/files/Fixup-debug_loc-sections-after-linker-relaxati.patch b/recipes-microblaze/binutils/files/Fixup-debug_loc-sections-after-linker-relaxati.patch
new file mode 100644
index 00000000..0623e945
--- /dev/null
+++ b/recipes-microblaze/binutils/files/Fixup-debug_loc-sections-after-linker-relaxati.patch
@@ -0,0 +1,228 @@
+From: David Holsgrove <david.holsgrove@xilinx.com>
+Date: Mon, 4 Feb 2013 12:15:22 +1000
+Subject: Fixup debug_loc sections after linker relaxation
+
+Adds a new reloctype R_MICROBLAZE_32_NONE, used for passing
+reloc info from the assembler to the linker when the linker
+manages to fully resolve a local symbol reference.
+
+This is a workaround for design flaws in the assembler to
+linker interface with regards to linker relaxation.
+
+Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
+Signed-off-by: David Holsgrove <david.holsgrove@xilinx.com>
+Upstream-Status: Pending
+---
+ bfd/bfd-in2.h | 5 +++++
+ bfd/elf32-microblaze.c | 45 +++++++++++++++++++++++++++++++++++++--------
+ bfd/libbfd.h | 1 +
+ bfd/reloc.c | 6 ++++++
+ binutils/readelf.c | 4 ++++
+ gas/config/tc-microblaze.c | 3 +++
+ include/elf/microblaze.h | 1 +
+ 7 files changed, 57 insertions(+), 8 deletions(-)
+
+diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
+index 8b7f2ee..de38907 100644
+--- a/bfd/bfd-in2.h
++++ b/bfd/bfd-in2.h
+@@ -5449,6 +5449,11 @@ value relative to the read-write small data area anchor */
+ 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 --git a/bfd/elf32-microblaze.c b/bfd/elf32-microblaze.c
+index f90df47..d440084 100644
+--- a/bfd/elf32-microblaze.c
++++ b/bfd/elf32-microblaze.c
+@@ -177,6 +177,20 @@ static reloc_howto_type microblaze_elf_howto_raw[] =
+ 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 @@ microblaze_elf_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
+ 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:
+@@ -1913,14 +1930,22 @@ microblaze_elf_relax_section (bfd *abfd,
+ }
+ 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, (unsigned long)irel->r_addend);
++ }
+ irel->r_addend -= (efix - sfix);
+ /* Should use HOWTO. */
+ microblaze_bfd_write_imm_value_32 (abfd, contents + irel->r_offset,
+@@ -1968,12 +1993,16 @@ microblaze_elf_relax_section (bfd *abfd,
+ irelscanend = irelocs + o->reloc_count;
+ for (irelscan = irelocs; irelscan < irelscanend; irelscan++)
+ {
+- if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_NONE)
++ 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)
+ {
+@@ -1998,15 +2027,15 @@ microblaze_elf_relax_section (bfd *abfd,
+ }
+ }
+
+- irelscan->r_addend -= calc_fixup (irelscan->r_addend
+- + isym->st_value, sec);
+ 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, (unsigned long)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_64_NONE) {
+- fprintf(stderr, "Unhandled NONE 64\n");
+- }
+ if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32)
+ {
+ isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
+@@ -2066,7 +2095,7 @@ microblaze_elf_relax_section (bfd *abfd,
+ 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);
+diff --git a/bfd/libbfd.h b/bfd/libbfd.h
+index 09f307f..840c662 100644
+--- a/bfd/libbfd.h
++++ b/bfd/libbfd.h
+@@ -2644,6 +2644,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
+ "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 --git a/bfd/reloc.c b/bfd/reloc.c
+index 7f46c58..5bcd52d 100644
+--- a/bfd/reloc.c
++++ b/bfd/reloc.c
+@@ -6396,6 +6396,12 @@ ENUMDOC
+ This is a 32 bit reloc for the microblaze to handle
+ expressions of the form "Symbol Op Symbol"
+ ENUM
++ BFD_RELOC_MICROBLAZE_32_NONE
++ENUMDOC
++ 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
++ENUM
+ BFD_RELOC_MICROBLAZE_64_NONE
+ ENUMDOC
+ This is a 64 bit reloc that stores the 32 bit pc relative
+diff --git a/binutils/readelf.c b/binutils/readelf.c
+index af6463e..343eb61 100644
+--- a/binutils/readelf.c
++++ b/binutils/readelf.c
+@@ -10821,6 +10821,10 @@ is_none_reloc (unsigned int reloc_type)
+ || reloc_type == 19 /* R_XTENSA_DIFF32. */);
+ case EM_METAG:
+ return reloc_type == 3; /* R_METAG_NONE. */
++ case EM_MICROBLAZE:
++ return reloc_type == 30 /* R_MICROBLAZE_32_NONE. */
++ || reloc_type == 0 /* R_MICROBLAZE_NONE. */
++ || reloc_type == 9; /* R_MICROBLAZE_64_NONE. */
+ }
+ return FALSE;
+ }
+diff --git a/gas/config/tc-microblaze.c b/gas/config/tc-microblaze.c
+index 12ad616..46d61db 100644
+--- a/gas/config/tc-microblaze.c
++++ b/gas/config/tc-microblaze.c
+@@ -2167,6 +2167,8 @@ md_apply_fix (fixS * fixP,
+ moves code around due to relaxing. */
+ if (fixP->fx_r_type == BFD_RELOC_64_PCREL)
+ fixP->fx_r_type = BFD_RELOC_MICROBLAZE_64_NONE;
++ else if (fixP->fx_r_type == BFD_RELOC_32)
++ fixP->fx_r_type = BFD_RELOC_MICROBLAZE_32_NONE;
+ else
+ fixP->fx_r_type = BFD_RELOC_NONE;
+ fixP->fx_addsy = section_symbol (absolute_section);
+@@ -2388,6 +2390,7 @@ tc_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
+ switch (fixp->fx_r_type)
+ {
+ case BFD_RELOC_NONE:
++ case BFD_RELOC_MICROBLAZE_32_NONE:
+ case BFD_RELOC_MICROBLAZE_64_NONE:
+ case BFD_RELOC_32:
+ case BFD_RELOC_MICROBLAZE_32_LO:
+diff --git a/include/elf/microblaze.h b/include/elf/microblaze.h
+index effca20..f8420dc 100644
+--- a/include/elf/microblaze.h
++++ b/include/elf/microblaze.h
+@@ -58,6 +58,7 @@ START_RELOC_NUMBERS (elf_microblaze_reloc_type)
+ 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)
+
+--
+1.9.0
+
diff --git a/recipes-microblaze/binutils/files/upstream-change-to-garbage-collection-s.patch b/recipes-microblaze/binutils/files/upstream-change-to-garbage-collection-s.patch
new file mode 100644
index 00000000..aa571d45
--- /dev/null
+++ b/recipes-microblaze/binutils/files/upstream-change-to-garbage-collection-s.patch
@@ -0,0 +1,38 @@
+From: David Holsgrove <david.holsgrove@xilinx.com>
+Date: Wed, 27 Feb 2013 13:56:11 +1000
+Subject: upstream change to garbage collection sweep causes mb regression
+
+Upstream change for PR13177 now clears the def_regular during gc_sweep of a
+section. (All other archs in binutils/bfd/elf32-*.c received an update
+to a warning about unresolvable relocations - this warning is not present
+in binutils/bfd/elf32-microblaze.c, but this warning check would not
+prevent the error being seen)
+
+The visible issue with this change is when running a c++ application
+in Petalinux which links libstdc++.so for exception handling it segfaults
+on execution.
+
+This does not occur if static linking libstdc++.a, so its during the
+relocations for a shared lib with garbage collection this occurs
+
+Signed-off-by: David Holsgrove <david.holsgrove@xilinx.com>
+Upstream-Status: Pending
+---
+ bfd/elflink.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/bfd/elflink.c b/bfd/elflink.c
+index 99b7ca1..415d714 100644
+--- a/bfd/elflink.c
++++ b/bfd/elflink.c
+@@ -11909,7 +11909,6 @@ elf_gc_sweep_symbol (struct elf_link_hash_entry *h, void *data)
+
+ inf = (struct elf_gc_sweep_symbol_info *) data;
+ (*inf->hide_symbol) (inf->info, h, TRUE);
+- h->def_regular = 0;
+ h->ref_regular = 0;
+ h->ref_regular_nonweak = 0;
+ }
+--
+1.8.5.1
+
diff --git a/recipes-microblaze/gcc/files/0001-Patch-microblaze-Enable-DWARF-exception-handling-sup.patch b/recipes-microblaze/gcc/files/0001-Patch-microblaze-Enable-DWARF-exception-handling-sup.patch
new file mode 100644
index 00000000..d6549cad
--- /dev/null
+++ b/recipes-microblaze/gcc/files/0001-Patch-microblaze-Enable-DWARF-exception-handling-sup.patch
@@ -0,0 +1,158 @@
+From: "Edgar E. Iglesias" <edgar.iglesias@gmail.com>
+Subject: [PATCH 1/8] [Patch, microblaze]: Enable DWARF exception handling
+ support.
+
+Changelog
+
+2013-03-18 Edgar E. Iglesias <edgar.iglesias@xilinx.com>
+ David Holsgrove <david.holsgrove@xilinx.com>
+
+ * common/config/microblaze/microblaze-common.c: Remove
+ TARGET_EXCEPT_UNWIND_INFO definition.
+ * config/microblaze/microblaze-protos.h: Add
+ microblaze_eh_return prototype.
+ * gcc/config/microblaze/microblaze.c: (microblaze_must_save_register,
+ microblaze_expand_epilogue, microblaze_return_addr): Handle
+ calls_eh_return
+ (microblaze_eh_return): New function.
+ * gcc/config/microblaze/microblaze.h: Define RETURN_ADDR_OFFSET,
+ EH_RETURN_DATA_REGNO, MB_EH_STACKADJ_REGNUM, EH_RETURN_STACKADJ_RTX,
+ ASM_PREFERRED_EH_DATA_FORMAT
+ * gcc/config/microblaze/microblaze.md: Define eh_return pattern.
+
+Signed-off-by: David Holsgrove <david.holsgrove@xilinx.com>
+Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
+Upstream-Status: Pending
+
+diff --git a/gcc/common/config/microblaze/microblaze-common.c b/gcc/common/config/microblaze/microblaze-common.c
+index 07a71fb..6c25a76 100644
+--- a/gcc/common/config/microblaze/microblaze-common.c
++++ b/gcc/common/config/microblaze/microblaze-common.c
+@@ -37,7 +37,4 @@ static const struct default_options microblaze_option_optimization_table[] =
+ #undef TARGET_OPTION_OPTIMIZATION_TABLE
+ #define TARGET_OPTION_OPTIMIZATION_TABLE microblaze_option_optimization_table
+
+-#undef TARGET_EXCEPT_UNWIND_INFO
+-#define TARGET_EXCEPT_UNWIND_INFO sjlj_except_unwind_info
+-
+ struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER;
+diff --git a/gcc/config/microblaze/microblaze-protos.h b/gcc/config/microblaze/microblaze-protos.h
+index 34be76f..201390b 100644
+--- a/gcc/config/microblaze/microblaze-protos.h
++++ b/gcc/config/microblaze/microblaze-protos.h
+@@ -54,6 +54,7 @@ extern bool microblaze_tls_referenced_p (rtx);
+ extern int symbol_mentioned_p (rtx);
+ extern int label_mentioned_p (rtx);
+ extern bool microblaze_cannot_force_const_mem (enum machine_mode, rtx);
++extern void microblaze_eh_return (rtx op0);
+ #endif /* RTX_CODE */
+
+ /* Declare functions in microblaze-c.c. */
+diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c
+index c121c2b..5f4bc60 100644
+--- a/gcc/config/microblaze/microblaze.c
++++ b/gcc/config/microblaze/microblaze.c
+@@ -1896,6 +1896,11 @@ microblaze_must_save_register (int regno)
+ if (frame_pointer_needed && (regno == HARD_FRAME_POINTER_REGNUM))
+ return 1;
+
++ if (crtl->calls_eh_return
++ && regno == MB_ABI_SUB_RETURN_ADDR_REGNUM) {
++ return 1;
++ }
++
+ if (!crtl->is_leaf)
+ {
+ if (regno == MB_ABI_SUB_RETURN_ADDR_REGNUM)
+@@ -1923,6 +1928,13 @@ microblaze_must_save_register (int regno)
+ return 1;
+ }
+
++ if (crtl->calls_eh_return
++ && (regno == EH_RETURN_DATA_REGNO (0)
++ || regno == EH_RETURN_DATA_REGNO (1)))
++ {
++ return 1;
++ }
++
+ return 0;
+ }
+
+@@ -2939,6 +2951,12 @@ microblaze_expand_epilogue (void)
+ emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, fsiz_rtx));
+ }
+
++ if (crtl->calls_eh_return)
++ emit_insn (gen_addsi3 (stack_pointer_rtx,
++ stack_pointer_rtx,
++ gen_rtx_raw_REG (SImode,
++ MB_EH_STACKADJ_REGNUM)));
++
+ emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, GP_REG_FIRST +
+ MB_ABI_SUB_RETURN_ADDR_REGNUM)));
+ }
+@@ -3166,10 +3184,13 @@ microblaze_return_addr (int count, rtx frame ATTRIBUTE_UNUSED)
+ if (count != 0)
+ return NULL_RTX;
+
+- return gen_rtx_PLUS (Pmode,
+- get_hard_reg_initial_val (Pmode,
+- MB_ABI_SUB_RETURN_ADDR_REGNUM),
+- GEN_INT (8));
++ return get_hard_reg_initial_val (Pmode,
++ MB_ABI_SUB_RETURN_ADDR_REGNUM);
++}
++
++void microblaze_eh_return (rtx op0)
++{
++ emit_insn (gen_movsi(gen_rtx_MEM(Pmode, stack_pointer_rtx), op0));
+ }
+
+ /* Queue an .ident string in the queue of top-level asm statements.
+diff --git a/gcc/config/microblaze/microblaze.h b/gcc/config/microblaze/microblaze.h
+index bc4d9a1..074b78e 100644
+--- a/gcc/config/microblaze/microblaze.h
++++ b/gcc/config/microblaze/microblaze.h
+@@ -184,6 +184,21 @@ extern enum pipeline_type microblaze_pipe;
+ #define INCOMING_RETURN_ADDR_RTX \
+ gen_rtx_REG (VOIDmode, GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM)
+
++/* Specifies the offset from INCOMING_RETURN_ADDR_RTX and the actual return PC. */
++#define RETURN_ADDR_OFFSET (8)
++
++/* Describe how we implement __builtin_eh_return. */
++#define EH_RETURN_DATA_REGNO(N) (((N) < 2) ? MB_ABI_FIRST_ARG_REGNUM + (N) : INVALID_REGNUM)
++
++#define MB_EH_STACKADJ_REGNUM MB_ABI_INT_RETURN_VAL2_REGNUM
++#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, MB_EH_STACKADJ_REGNUM)
++
++/* Select a format to encode pointers in exception handling data. CODE
++ is 0 for data, 1 for code labels, 2 for function pointers. GLOBAL is
++ true if the symbol may be affected by dynamic relocations. */
++#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) \
++ ((flag_pic || GLOBAL) ? DW_EH_PE_aligned : DW_EH_PE_absptr)
++
+ /* Use DWARF 2 debugging information by default. */
+ #define DWARF2_DEBUGGING_INFO
+ #define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
+diff --git a/gcc/config/microblaze/microblaze.md b/gcc/config/microblaze/microblaze.md
+index 3618cad..4e7fe3b 100644
+--- a/gcc/config/microblaze/microblaze.md
++++ b/gcc/config/microblaze/microblaze.md
+@@ -2221,3 +2221,13 @@
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")
+ (set_attr "length" "4")])
++
++; This is used in compiling the unwind routines.
++(define_expand "eh_return"
++ [(use (match_operand 0 "general_operand" ""))]
++ ""
++ "
++{
++ microblaze_eh_return(operands[0]);
++ DONE;
++}")
+--
+1.7.5.4
+
diff --git a/recipes-microblaze/gcc/files/0002-Patch-microblaze-Add-4-byte-implementation-for-atomi.patch b/recipes-microblaze/gcc/files/0002-Patch-microblaze-Add-4-byte-implementation-for-atomi.patch
new file mode 100644
index 00000000..aefa13b0
--- /dev/null
+++ b/recipes-microblaze/gcc/files/0002-Patch-microblaze-Add-4-byte-implementation-for-atomi.patch
@@ -0,0 +1,157 @@
+From: David Holsgrove <david.holsgrove@xilinx.com>
+Subject: [PATCH 2/8] [Patch, microblaze]: Add 4 byte implementation for
+ atomic builtin
+
+By providing this initial atomic implementation, gcc is able to generate the other atomic
+builtins by using a __sync_compare_and_swap loop
+
+Add __sync_lock_test_and_set 4 byte atomic builtin
+
+Changelog
+
+2013-03-18 David Holsgrove <david.holsgrove@xilinx.com>
+
+ * gcc/config/microblaze/sync.md: New file.
+ * gcc/config/microblaze/microblaze.md: Add UNSPEC_SYNC_CAS,
+ UNSPEC_SYNC_XCHG and include sync.md.
+ * gcc/config/microblaze/microblaze.c: Add print_operand 'y'.
+ * gcc/config/microblaze/constraints.md: Add memory_contraint
+ 'Q' which is a single register.
+
+Signed-off-by: David Holsgrove <david.holsgrove@xilinx.com>
+Upstream-Status: Pending
+
+diff --git a/gcc/config/microblaze/constraints.md b/gcc/config/microblaze/constraints.md
+index c6fbc98..c9c1649 100644
+--- a/gcc/config/microblaze/constraints.md
++++ b/gcc/config/microblaze/constraints.md
+@@ -70,3 +70,8 @@
+ "Double word operand."
+ (and (match_code "mem")
+ (match_test "double_memory_operand (op, GET_MODE (op))")))
++
++(define_memory_constraint "Q"
++ "Memory operand which is a single register."
++ (and (match_code "mem")
++ (match_test "GET_CODE ( XEXP (op, 0)) == REG")))
+diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c
+index 5f4bc60..1562e60 100644
+--- a/gcc/config/microblaze/microblaze.c
++++ b/gcc/config/microblaze/microblaze.c
+@@ -2130,6 +2130,7 @@ microblaze_initial_elimination_offset (int from, int to)
+ 't' print 't' for EQ, 'f' for NE
+ 'm' Print 1<<operand.
+ 'i' Print 'i' if MEM operand has immediate value
++ 'y' Print 'y' if MEM operand is single register
+ 'o' Print operand address+4
+ '?' Print 'd' if we use a branch with delay slot instead of normal branch.
+ 'h' Print high word of const_double (int or float) value as hex
+@@ -2300,6 +2301,15 @@ print_operand (FILE * file, rtx op, int letter)
+ rtx op4 = adjust_address (op, GET_MODE (op), 4);
+ output_address (XEXP (op4, 0));
+ }
++ else if (letter == 'y')
++ {
++ rtx mem_reg = XEXP (op, 0);
++ if (GET_CODE (mem_reg) == REG)
++ {
++ register int regnum = REGNO (mem_reg);
++ fprintf (file, "%s", reg_names[regnum]);
++ }
++ }
+ else
+ output_address (XEXP (op, 0));
+
+diff --git a/gcc/config/microblaze/microblaze.md b/gcc/config/microblaze/microblaze.md
+index 4e7fe3b..55cc730 100644
+--- a/gcc/config/microblaze/microblaze.md
++++ b/gcc/config/microblaze/microblaze.md
+@@ -41,6 +41,8 @@
+ (UNSPEC_CMP 104) ;; signed compare
+ (UNSPEC_CMPU 105) ;; unsigned compare
+ (UNSPEC_TLS 106) ;; jump table
++ (UNSPEC_SYNC_CAS 107) ;; Represent atomic compare swap.
++ (UNSPEC_SYNC_XCHG 108) ;; Represent atomic exchange.
+ ])
+
+
+@@ -2231,3 +2233,5 @@
+ microblaze_eh_return(operands[0]);
+ DONE;
+ }")
++
++(include "sync.md")
+diff --git a/gcc/config/microblaze/sync.md b/gcc/config/microblaze/sync.md
+new file mode 100644
+index 0000000..0923825
+--- /dev/null
++++ b/gcc/config/microblaze/sync.md
+@@ -0,0 +1,65 @@
++;; Machine description for Xilinx MicroBlaze synchronization instructions.
++;; Copyright (C) 2011, 2012
++;; Free Software Foundation, Inc.
++;;
++;; This file is part of GCC.
++;;
++;; GCC 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, or (at your option)
++;; any later version.
++;;
++;; GCC 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 GCC; see the file COPYING3. If not see
++;; <http://www.gnu.org/licenses/>.
++
++
++(define_insn "sync_compare_and_swapsi"
++ [(set (match_operand:SI 0 "register_operand" "=&d") ;; retval
++ (match_operand:SI 1 "nonimmediate_operand" "+Q")) ;; mem
++ (set (match_dup 1)
++ (unspec
++ [(match_operand:SI 2 "register_operand" "d") ;; oldval
++ (match_operand:SI 3 "register_operand" "d")] ;; newval
++ UNSPEC_SYNC_CAS))
++ (clobber (match_scratch:SI 4 "=&d"))] ;; scratch
++ ""
++ {
++ output_asm_insn ("addc \tr0,r0,r0", operands);
++ output_asm_insn ("lwx \t%0,%y1,r0", operands);
++ output_asm_insn ("addic\t%4,r0,0", operands);
++ output_asm_insn ("bnei \t%4,.-8", operands);
++ output_asm_insn ("cmp \t%4,%0,%2", operands);
++ output_asm_insn ("bnei \t%4,.+16", operands);
++ output_asm_insn ("swx \t%3,%y1,r0", operands);
++ output_asm_insn ("addic\t%4,r0,0", operands);
++ output_asm_insn ("bnei \t%4,.-28", operands);
++ return "";
++ }
++)
++
++(define_insn "sync_test_and_setsi"
++ [(set (match_operand:SI 0 "register_operand" "=&d") ;; retval
++ (match_operand:SI 1 "nonimmediate_operand" "+Q")) ;; mem
++ (set (match_dup 1)
++ (unspec
++ [(match_operand:SI 2 "register_operand" "d")] ;; value
++ UNSPEC_SYNC_XCHG))
++ (clobber (match_scratch:SI 3 "=&d"))] ;; scratch
++ ""
++ {
++ output_asm_insn ("addc \tr0,r0,r0", operands);
++ output_asm_insn ("lwx \t%0,%y1,r0", operands);
++ output_asm_insn ("addic\t%3,r0,0", operands);
++ output_asm_insn ("bnei \t%3,.-8", operands);
++ output_asm_insn ("swx \t%2,%y1,r0", operands);
++ output_asm_insn ("addic\t%3,r0,0", operands);
++ output_asm_insn ("bnei \t%3,.-20", operands);
++ return "";
++ }
++)
+--
+1.7.5.4
+
diff --git a/recipes-microblaze/gcc/files/0003-Patch-microblaze-Extend-jump-insn-to-accept-bri-to-S.patch b/recipes-microblaze/gcc/files/0003-Patch-microblaze-Extend-jump-insn-to-accept-bri-to-S.patch
new file mode 100644
index 00000000..998dfa03
--- /dev/null
+++ b/recipes-microblaze/gcc/files/0003-Patch-microblaze-Extend-jump-insn-to-accept-bri-to-S.patch
@@ -0,0 +1,35 @@
+From: David Holsgrove <david.holsgrove@xilinx.com>
+Subject: [PATCH 3/8] [Patch, microblaze]: Extend jump insn to accept bri to
+ SYMBOL_REFS
+
+Current insn checks if operand is a REG - if so, uses br
+else it bri to %l0 - using a label_ref print operand
+
+Check if operand is a SYMBOL_REF, and if so, use %0
+
+Changelog
+
+2013-03-18 David Holsgrove <david.holsgrove@xilinx.com>
+
+ * gcc/config/microblaze/microblaze.md (jump):
+ Account for jumps to SYMBOL_REFs.
+
+Signed-off-by: David Holsgrove <david.holsgrove@xilinx.com>
+Upstream-Status: Pending
+
+diff --git a/gcc/config/microblaze/microblaze.md b/gcc/config/microblaze/microblaze.md
+index 55cc730..49d8f01 100644
+--- a/gcc/config/microblaze/microblaze.md
++++ b/gcc/config/microblaze/microblaze.md
+@@ -1729,6 +1729,8 @@
+ {
+ if (GET_CODE (operands[0]) == REG)
+ return "br%?\t%0";
++ else if (GET_CODE (operands[0]) == SYMBOL_REF)
++ return "bri%?\t%0";
+ else
+ return "bri%?\t%l0";
+ }
+--
+1.7.5.4
+
diff --git a/recipes-microblaze/gcc/files/0005-Patch-microblaze-Add-fstack-usage-support.patch b/recipes-microblaze/gcc/files/0005-Patch-microblaze-Add-fstack-usage-support.patch
new file mode 100644
index 00000000..ee3cb9db
--- /dev/null
+++ b/recipes-microblaze/gcc/files/0005-Patch-microblaze-Add-fstack-usage-support.patch
@@ -0,0 +1,30 @@
+From: David Holsgrove <david.holsgrove@xilinx.com>
+Subject: [PATCH 5/8] [Patch, microblaze]: Add -fstack-usage support
+
+Changelog
+
+2013-03-18 David Holsgrove <david.holsgrove@xilinx.com>
+
+ * gcc/config/microblaze/microblaze.c (microblaze_expand_prologue):
+ Add check for flag_stack_usage to enable -fstack-usage support
+
+Signed-off-by: David Holsgrove <david.holsgrove@xilinx.com>
+Upstream-Status: Pending
+
+diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c
+index 7418e49..4417289 100644
+--- a/gcc/config/microblaze/microblaze.c
++++ b/gcc/config/microblaze/microblaze.c
+@@ -2790,6 +2790,9 @@ microblaze_expand_prologue (void)
+
+ fsiz = compute_frame_size (get_frame_size ());
+
++ if (flag_stack_usage)
++ current_function_static_stack_size = fsiz;
++
+ /* If this function is a varargs function, store any registers that
+ would normally hold arguments ($5 - $10) on the stack. */
+ if (((TYPE_ARG_TYPES (fntype) != 0
+--
+1.7.5.4
+
diff --git a/recipes-microblaze/gcc/files/0006-Patch-microblaze-Remove-SECONDARY_MEMORY_NEEDED.patch b/recipes-microblaze/gcc/files/0006-Patch-microblaze-Remove-SECONDARY_MEMORY_NEEDED.patch
new file mode 100644
index 00000000..923756a5
--- /dev/null
+++ b/recipes-microblaze/gcc/files/0006-Patch-microblaze-Remove-SECONDARY_MEMORY_NEEDED.patch
@@ -0,0 +1,35 @@
+From: "Edgar E. Iglesias" <edgar.iglesias@gmail.com>
+Subject: [PATCH 6/8] [Patch, microblaze]: Remove SECONDARY_MEMORY_NEEDED
+
+MicroBlaze doesn't have restrictions that would force us to
+reload regs via memory. Don't define SECONDARY_MEMORY_NEEDED.
+Fixes an ICE when compiling OpenSSL for linux.
+
+Changelog
+
+2013-03-18 Edgar E. Iglesias <edgar.iglesias@xilinx.com>
+
+ * gcc/config/microblaze/microblaze.h: Remove SECONDARY_MEMORY_NEEDED
+ definition.
+
+Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
+Signed-off-by: Peter A. G. Crosthwaite <peter.crosthwaite@xilinx.com>
+Upstream-Status: Pending
+
+diff --git a/gcc/config/microblaze/microblaze.h b/gcc/config/microblaze/microblaze.h
+index 074b78e..add69e8 100644
+--- a/gcc/config/microblaze/microblaze.h
++++ b/gcc/config/microblaze/microblaze.h
+@@ -422,9 +422,6 @@ extern enum reg_class microblaze_regno_to_class[];
+ || GET_MODE (X) == VOIDmode) \
+ ? (GR_REGS) : (CLASS))))
+
+-#define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \
+- (GET_MODE_CLASS (MODE) == MODE_INT)
+-
+ /* Stack layout; function entry, exit and calling. */
+
+ #define STACK_GROWS_DOWNWARD
+--
+1.7.5.4
+
diff --git a/recipes-microblaze/gcc/files/0007-Patch-microblaze-Add-SIZE_TYPE-and-PTRDIFF_TYPE-to-m.patch b/recipes-microblaze/gcc/files/0007-Patch-microblaze-Add-SIZE_TYPE-and-PTRDIFF_TYPE-to-m.patch
new file mode 100644
index 00000000..33aee3a7
--- /dev/null
+++ b/recipes-microblaze/gcc/files/0007-Patch-microblaze-Add-SIZE_TYPE-and-PTRDIFF_TYPE-to-m.patch
@@ -0,0 +1,39 @@
+From: David Holsgrove <david.holsgrove@xilinx.com>
+Subject: [PATCH 7/8] [Patch, microblaze]: Add SIZE_TYPE and PTRDIFF_TYPE to
+ microblaze.h
+
+Fixes warnings like;
+
+warning: format '%zX' expects argument of type 'size_t',
+but argument 3 has type 'unsigned int' [-Wformat]
+
+Changelog
+
+2013-03-18 David Holsgrove <david.holsgrove@xilinx.com>
+
+ * gcc/config/microblaze/microblaze.h: Define SIZE_TYPE
+ and PTRDIFF_TYPE.
+
+Signed-off-by: David Holsgrove <david.holsgrove@xilinx.com>
+Upstream-Status: Pending
+
+diff --git a/gcc/config/microblaze/microblaze.h b/gcc/config/microblaze/microblaze.h
+index add69e8..367e986 100644
+--- a/gcc/config/microblaze/microblaze.h
++++ b/gcc/config/microblaze/microblaze.h
+@@ -228,6 +228,12 @@ extern enum pipeline_type microblaze_pipe;
+ #define STRICT_ALIGNMENT 1
+ #define PCC_BITFIELD_TYPE_MATTERS 1
+
++#undef SIZE_TYPE
++#define SIZE_TYPE "unsigned int"
++
++#undef PTRDIFF_TYPE
++#define PTRDIFF_TYPE "int"
++
+ #define CONSTANT_ALIGNMENT(EXP, ALIGN) \
+ ((TREE_CODE (EXP) == STRING_CST || TREE_CODE (EXP) == CONSTRUCTOR) \
+ && (ALIGN) < BITS_PER_WORD \
+--
+1.7.5.4
+
diff --git a/recipes-microblaze/gcc/files/0008-Patch-microblaze-Add-branch_compare-instruction.patch b/recipes-microblaze/gcc/files/0008-Patch-microblaze-Add-branch_compare-instruction.patch
new file mode 100644
index 00000000..4da74f3f
--- /dev/null
+++ b/recipes-microblaze/gcc/files/0008-Patch-microblaze-Add-branch_compare-instruction.patch
@@ -0,0 +1,224 @@
+From: David Holsgrove <david.holsgrove@xilinx.com>
+Subject: [PATCH 8/8] [Patch, microblaze]: Add branch_compare instruction
+
+To facilitate optimization pass understanding of the conditional
+branch for microblaze, remove the UNSPEC'd signed_compare /
+unsigned_compare instructions, and replace with a complete
+branch_compare which will output_asm_insn the correct cmp/cmpu
+depending on comparison code and signed / unsigned.
+
+We then return the correct branch instruction.
+
+cbranchsi now calls an expanded microblaze_expand_conditional_branch
+function which will carry out compare against zero, compare EQ/NE,
+and all other compares appropriately.
+
+-funroll-loops optimization pass can now proceed
+
+Changelog
+
+2013-03-19 David Holsgrove <david.holsgrove@xilinx.com>
+
+ * gcc/config/microblaze/predicates.md: Add cmp_op predicate.
+ * gcc/config/microblaze/microblaze.md: Add branch_compare
+ instruction which uses cmp_op predicate and emits cmp insn
+ before branch.
+ * gcc/config/microblaze/microblaze.c
+ (microblaze_emit_compare): Rename to
+ microblaze_expand_conditional_branch and consolidate logic.
+ (microblaze_expand_conditional_branch): emit branch_compare
+ insn instead of handling cmp op separate from branch insn.
+
+Signed-off-by: David Holsgrove <david.holsgrove@xilinx.com>
+Upstream-Status: Pending
+
+diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c
+index 4417289..84b58bf 100644
+--- a/gcc/config/microblaze/microblaze.c
++++ b/gcc/config/microblaze/microblaze.c
+@@ -3336,65 +3336,45 @@ microblaze_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
+ emit_move_insn (mem, fnaddr);
+ }
+
+-/* Emit instruction to perform compare.
+- cmp is (compare_op op0 op1). */
+-static rtx
+-microblaze_emit_compare (enum machine_mode mode, rtx cmp, enum rtx_code *cmp_code)
++/* Generate conditional branch -- first, generate test condition,
++ second, generate correct branch instruction. */
++
++void
++microblaze_expand_conditional_branch (enum machine_mode mode, rtx operands[])
+ {
+- rtx cmp_op0 = XEXP (cmp, 0);
+- rtx cmp_op1 = XEXP (cmp, 1);
++ enum rtx_code code = GET_CODE (operands[0]);
++ rtx cmp_op0 = operands[1];
++ rtx cmp_op1 = operands[2];
++ rtx label1 = operands[3];
+ rtx comp_reg = gen_reg_rtx (SImode);
+- enum rtx_code code = *cmp_code;
+-
++ rtx condition;
++
+ gcc_assert ((GET_CODE (cmp_op0) == REG) || (GET_CODE (cmp_op0) == SUBREG));
+
+ /* If comparing against zero, just test source reg. */
+- if (cmp_op1 == const0_rtx)
+- return cmp_op0;
++ if (cmp_op1 == const0_rtx)
++ {
++ comp_reg = cmp_op0;
++ condition = gen_rtx_fmt_ee (signed_condition (code), SImode, comp_reg, const0_rtx);
++ emit_jump_insn (gen_condjump (condition, label1));
++ }
+
+- if (code == EQ || code == NE)
++ else if (code == EQ || code == NE)
+ {
+ /* Use xor for equal/not-equal comparison. */
+ emit_insn (gen_xorsi3 (comp_reg, cmp_op0, cmp_op1));
++ condition = gen_rtx_fmt_ee (signed_condition (code), SImode, comp_reg, const0_rtx);
++ emit_jump_insn (gen_condjump (condition, label1));
+ }
+- else if (code == GT || code == GTU || code == LE || code == LEU)
+- {
+- /* MicroBlaze compare is not symmetrical. */
+- /* Swap argument order. */
+- cmp_op1 = force_reg (mode, cmp_op1);
+- if (code == GT || code == LE)
+- emit_insn (gen_signed_compare (comp_reg, cmp_op0, cmp_op1));
+- else
+- emit_insn (gen_unsigned_compare (comp_reg, cmp_op0, cmp_op1));
+- /* Translate test condition. */
+- *cmp_code = swap_condition (code);
+- }
+- else /* if (code == GE || code == GEU || code == LT || code == LTU) */
++ else
+ {
++ /* Generate compare and branch in single instruction. */
+ cmp_op1 = force_reg (mode, cmp_op1);
+- if (code == GE || code == LT)
+- emit_insn (gen_signed_compare (comp_reg, cmp_op1, cmp_op0));
+- else
+- emit_insn (gen_unsigned_compare (comp_reg, cmp_op1, cmp_op0));
++ condition = gen_rtx_fmt_ee (code, mode, cmp_op0, cmp_op1);
++ emit_jump_insn (gen_branch_compare(condition, cmp_op0, cmp_op1, label1));
+ }
+-
+- return comp_reg;
+ }
+
+-/* Generate conditional branch -- first, generate test condition,
+- second, generate correct branch instruction. */
+-
+-void
+-microblaze_expand_conditional_branch (enum machine_mode mode, rtx operands[])
+-{
+- enum rtx_code code = GET_CODE (operands[0]);
+- rtx comp;
+- rtx condition;
+-
+- comp = microblaze_emit_compare (mode, operands[0], &code);
+- condition = gen_rtx_fmt_ee (signed_condition (code), SImode, comp, const0_rtx);
+- emit_jump_insn (gen_condjump (condition, operands[3]));
+-}
+
+ void
+ microblaze_expand_conditional_branch_sf (rtx operands[])
+diff --git a/gcc/config/microblaze/microblaze.md b/gcc/config/microblaze/microblaze.md
+index 49d8f01..9c1e1a3 100644
+--- a/gcc/config/microblaze/microblaze.md
++++ b/gcc/config/microblaze/microblaze.md
+@@ -1624,28 +1624,6 @@
+ (set_attr "length" "4")]
+ )
+
+-(define_insn "signed_compare"
+- [(set (match_operand:SI 0 "register_operand" "=d")
+- (unspec
+- [(match_operand:SI 1 "register_operand" "d")
+- (match_operand:SI 2 "register_operand" "d")] UNSPEC_CMP))]
+- ""
+- "cmp\t%0,%1,%2"
+- [(set_attr "type" "arith")
+- (set_attr "mode" "SI")
+- (set_attr "length" "4")])
+-
+-(define_insn "unsigned_compare"
+- [(set (match_operand:SI 0 "register_operand" "=d")
+- (unspec
+- [(match_operand:SI 1 "register_operand" "d")
+- (match_operand:SI 2 "register_operand" "d")] UNSPEC_CMPU))]
+- ""
+- "cmpu\t%0,%1,%2"
+- [(set_attr "type" "arith")
+- (set_attr "mode" "SI")
+- (set_attr "length" "4")])
+-
+ ;;----------------------------------------------------------------
+ ;; Setting a register from an floating point comparison.
+ ;;----------------------------------------------------------------
+@@ -1719,6 +1697,47 @@
+ (set_attr "length" "4")]
+ )
+
++(define_insn "branch_compare"
++ [(set (pc)
++ (if_then_else (match_operator:SI 0 "cmp_op"
++ [(match_operand:SI 1 "register_operand" "d")
++ (match_operand:SI 2 "register_operand" "d")
++ ])
++ (label_ref (match_operand 3))
++ (pc)))
++ (clobber(reg:SI R_TMP))]
++ ""
++ {
++ operands[4] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM);
++ enum rtx_code code = GET_CODE (operands[0]);
++
++ if (code == GT || code == LE)
++ {
++ output_asm_insn ("cmp\tr18,%z1,%z2", operands);
++ code = swap_condition (code);
++ }
++ else if (code == GTU || code == LEU)
++ {
++ output_asm_insn ("cmpu\tr18,%z1,%z2", operands);
++ code = swap_condition (code);
++ }
++ else if (code == GE || code == LT)
++ {
++ output_asm_insn ("cmp\tr18,%z2,%z1", operands);
++ }
++ else if (code == GEU || code == LTU)
++ {
++ output_asm_insn ("cmpu\tr18,%z2,%z1", operands);
++ }
++
++ operands[0] = gen_rtx_fmt_ee (signed_condition (code), SImode, operands[4], const0_rtx);
++ return "b%C0i%?\tr18,%3";
++ }
++ [(set_attr "type" "branch")
++ (set_attr "mode" "none")
++ (set_attr "length" "12")]
++)
++
+ ;;----------------------------------------------------------------
+ ;; Unconditional branches
+ ;;----------------------------------------------------------------
+diff --git a/gcc/config/microblaze/predicates.md b/gcc/config/microblaze/predicates.md
+index 5fd1bd4..2c23291 100644
+--- a/gcc/config/microblaze/predicates.md
++++ b/gcc/config/microblaze/predicates.md
+@@ -119,3 +119,7 @@
+ ;; Test for valid PIC call operand
+ (define_predicate "call_insn_plt_operand"
+ (match_test "PLT_ADDR_P (op)"))
++
++;; Return if the code of this rtx pattern is a comparison.
++(define_predicate "cmp_op"
++ (match_code "gt,ge,gtu,geu,lt,le,ltu,leu"))
+--
+1.7.5.4
+
diff --git a/recipes-microblaze/gcc/files/0462b5f-2014-02-23-David-Holsgrove-david.holsgrove.patch b/recipes-microblaze/gcc/files/0462b5f-2014-02-23-David-Holsgrove-david.holsgrove.patch
new file mode 100644
index 00000000..efd127de
--- /dev/null
+++ b/recipes-microblaze/gcc/files/0462b5f-2014-02-23-David-Holsgrove-david.holsgrove.patch
@@ -0,0 +1,108 @@
+From 0462b5fb1e91183c16e204e1a6cf436ef0d8d0f8 Mon Sep 17 00:00:00 2001
+From: eager <eager@138bc75d-0d04-0410-961f-82ee72b054a4>
+Date: Sun, 23 Feb 2014 18:44:27 +0000
+Subject: [PATCH] 2014-02-23 David Holsgrove <david.holsgrove@xilinx.com>
+
+ * /config/microblaze/microblaze.c: Add microblaze_asm_output_mi_thunk
+ and define TARGET_ASM_OUTPUT_MI_THUNK and
+ TARGET_ASM_CAN_OUTPUT_MI_THUNK.
+
+Upstream-Status: Backport
+---
+ gcc/config/microblaze/microblaze.c | 73 ++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 79 insertions(+)
+
+diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c
+index 985d26a..ba8109b 100644
+--- a/gcc/config/microblaze/microblaze.c
++++ b/gcc/config/microblaze/microblaze.c
+@@ -3087,6 +3087,73 @@ expand_pic_symbol_ref (enum machine_mode mode ATTRIBUTE_UNUSED, rtx op)
+ return result;
+ }
+
++static void
++microblaze_asm_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
++ HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
++ tree function)
++{
++ rtx this_rtx, insn, funexp;
++
++ reload_completed = 1;
++ epilogue_completed = 1;
++
++ /* Mark the end of the (empty) prologue. */
++ emit_note (NOTE_INSN_PROLOGUE_END);
++
++ /* Find the "this" pointer. If the function returns a structure,
++ the structure return pointer is in MB_ABI_FIRST_ARG_REGNUM. */
++ if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
++ this_rtx = gen_rtx_REG (Pmode, (MB_ABI_FIRST_ARG_REGNUM + 1));
++ else
++ this_rtx = gen_rtx_REG (Pmode, MB_ABI_FIRST_ARG_REGNUM);
++
++ /* Apply the constant offset, if required. */
++ if (delta)
++ emit_insn (gen_addsi3 (this_rtx, this_rtx, GEN_INT (delta)));
++
++ /* Apply the offset from the vtable, if required. */
++ if (vcall_offset)
++ {
++ rtx vcall_offset_rtx = GEN_INT (vcall_offset);
++ rtx temp1 = gen_rtx_REG (Pmode, MB_ABI_TEMP1_REGNUM);
++
++ emit_move_insn (temp1, gen_rtx_MEM (Pmode, this_rtx));
++
++ rtx loc = gen_rtx_PLUS (Pmode, temp1, vcall_offset_rtx);
++ emit_move_insn (temp1, gen_rtx_MEM (Pmode, loc));
++
++ emit_insn (gen_addsi3 (this_rtx, this_rtx, temp1));
++ }
++
++ /* Generate a tail call to the target function. */
++ if (!TREE_USED (function))
++ {
++ assemble_external (function);
++ TREE_USED (function) = 1;
++ }
++
++ funexp = XEXP (DECL_RTL (function), 0);
++ rtx temp2 = gen_rtx_REG (Pmode, MB_ABI_TEMP2_REGNUM);
++
++ if (flag_pic)
++ emit_move_insn (temp2, expand_pic_symbol_ref (Pmode, funexp));
++ else
++ emit_move_insn (temp2, funexp);
++
++ emit_insn (gen_indirect_jump (temp2));
++
++ /* Run just enough of rest_of_compilation. This sequence was
++ "borrowed" from rs6000.c. */
++ insn = get_insns ();
++ shorten_branches (insn);
++ final_start_function (insn, file, 1);
++ final (insn, file, 1);
++ final_end_function ();
++
++ reload_completed = 0;
++ epilogue_completed = 0;
++}
++
+ bool
+ microblaze_expand_move (enum machine_mode mode, rtx operands[])
+ {
+@@ -3504,6 +3571,12 @@ microblaze_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x
+ #undef TARGET_SECONDARY_RELOAD
+ #define TARGET_SECONDARY_RELOAD microblaze_secondary_reload
+
++#undef TARGET_ASM_OUTPUT_MI_THUNK
++#define TARGET_ASM_OUTPUT_MI_THUNK microblaze_asm_output_mi_thunk
++
++#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
++#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
++
+ #undef TARGET_SCHED_ADJUST_COST
+ #define TARGET_SCHED_ADJUST_COST microblaze_adjust_cost
+
+--
+1.9.0
+
diff --git a/recipes-microblaze/gcc/files/Patch-microblaze-Fix-bswaphi2-implementation.patch b/recipes-microblaze/gcc/files/Patch-microblaze-Fix-bswaphi2-implementation.patch
new file mode 100644
index 00000000..b39dc4db
--- /dev/null
+++ b/recipes-microblaze/gcc/files/Patch-microblaze-Fix-bswaphi2-implementation.patch
@@ -0,0 +1,44 @@
+From: David Holsgrove <david.holsgrove@xilinx.com>
+Subject: [PATCH] [Patch, microblaze]: Fix bswaphi2 implementation
+
+MicroBlaze insn swaph swaps the contents of register rA
+as two halfwords placing result in rD;
+
+(rD)[0:15] <- (rA)[16:31]
+(rD)[16:31] <- (rA)[0:15]
+
+gcc bswaphi2 is intended to reverse the order of the bytes
+in the half integer in rA
+
+(rD)[8:15] <- (rA)[0:7]
+(rD)[7:0] <- (rA)[8:15]
+(rD)[24:31] <- (rA)[16:23]
+(rD)[16:23] <- (rA)[24:31]
+
+Correct microblaze bswaphi2 insn pattern to be a
+swapb followed by swaph
+
+Reported-by: Nathan Rossi <nathan.rossi@xilinx.com>
+Signed-off-by: David Holsgrove <david.holsgrove@xilinx.com>
+Upstream-Status: Pending
+---
+ gcc/config/microblaze/microblaze.md | 3 ++-
+ 1 files changed, 2 insertions(+), 1 deletions(-)
+
+diff --git a/gcc/config/microblaze/microblaze.md b/gcc/config/microblaze/microblaze.md
+index ae4ade7..c7485fc 100644
+--- a/gcc/config/microblaze/microblaze.md
++++ b/gcc/config/microblaze/microblaze.md
+@@ -367,7 +367,8 @@
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (bswap:HI (match_operand:HI 1 "register_operand" "r")))]
+ "TARGET_REORDER"
+- "swaph %0, %1"
++ "swapb %0, %1
++ swaph %0, %0"
+ )
+
+ ;;----------------------------------------------------------------
+--
+1.7.1
+
diff --git a/recipes-microblaze/gcc/files/Patch-microblaze-cstoresf4-add-mode-and-ordered_comp.patch b/recipes-microblaze/gcc/files/Patch-microblaze-cstoresf4-add-mode-and-ordered_comp.patch
new file mode 100644
index 00000000..934e7fa9
--- /dev/null
+++ b/recipes-microblaze/gcc/files/Patch-microblaze-cstoresf4-add-mode-and-ordered_comp.patch
@@ -0,0 +1,44 @@
+From: David Holsgrove <david.holsgrove@xilinx.com>
+Subject: [PATCH] [Patch, microblaze]: cstoresf4, add mode and
+ ordered_comparison_operator
+
+Add SImode to comparison operator, prevents ICE during combine
+rtl pass with error message;
+
+internal compiler error: in simplify_subreg, at simplify-rtx.c:5725
+
+Use ordered_comparison_operator predicate to limit operators to
+those fcmp can handle, and letting compiler reorder insns to
+accomodate unordered as necessary
+
+Signed-off-by: David Holsgrove <david.holsgrove@xilinx.com>
+Upstream-Status: Pending
+---
+ gcc/config/microblaze/microblaze.md | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/config/microblaze/microblaze.md b/gcc/config/microblaze/microblaze.md
+index 786dabb..e9b032b 100644
+--- a/gcc/config/microblaze/microblaze.md
++++ b/gcc/config/microblaze/microblaze.md
+@@ -1650,7 +1650,7 @@
+ ;;----------------------------------------------------------------
+ (define_insn "cstoresf4"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+- (match_operator 1 "comparison_operator"
++ (match_operator:SI 1 "ordered_comparison_operator"
+ [(match_operand:SF 2 "register_operand" "r")
+ (match_operand:SF 3 "register_operand" "r")]))]
+ "TARGET_HARD_FLOAT"
+@@ -1679,7 +1679,7 @@
+
+ (define_expand "cbranchsf4"
+ [(set (pc)
+- (if_then_else (match_operator 0 "comparison_operator"
++ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(match_operand:SF 1 "register_operand")
+ (match_operand:SF 2 "register_operand")])
+ (label_ref (match_operand 3 ""))
+--
+1.7.9.5
+
diff --git a/recipes-microblaze/gcc/files/gcc-Cherry-pick-mainline-patch-to-resolve-MB-k.patch b/recipes-microblaze/gcc/files/gcc-Cherry-pick-mainline-patch-to-resolve-MB-k.patch
new file mode 100644
index 00000000..1cdc4029
--- /dev/null
+++ b/recipes-microblaze/gcc/files/gcc-Cherry-pick-mainline-patch-to-resolve-MB-k.patch
@@ -0,0 +1,110 @@
+Subject: Cherry-pick mainline patch to resolve MB kernel panic
+
+Cherry-pick backend optimization patch from gcc HEAD which 'resolves' a kernel
+panic for microblaze when compiled with -Os
+
+Upstream HEAD (soon to be gcc 4.9) does not exhibt this error any longer,
+and this patch when applied as a workaround on the 4.8 branch also hides the
+kernel panic resulting from incorrect branch-delay slot filling.
+
+ * tree-ssa-threadedge.c (thread_around_empty_block): Remove
+ checks for the number of predecessors and successors allowed.
+ * tree-ssa-threadupdate.c (mark_threaded_blocks): Ignore requests
+ which require copying a joiner block if there is a request which
+ is a subpath that requires no joiner block copying.
+
+Signed-off-by: David Holsgrove <david.holsgrove@xilinx.com>
+Upstream-Status: Backport
+---
+ gcc/tree-ssa-threadedge.c | 8 -------
+ gcc/tree-ssa-threadupdate.c | 49 ++++++++++++++++++++++++++++++++++++++-----
+ 2 files changed, 44 insertions(+), 13 deletions(-)
+
+diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c
+index b31e961..ab58ae8 100644
+--- a/gcc/tree-ssa-threadedge.c
++++ b/gcc/tree-ssa-threadedge.c
+@@ -761,14 +761,6 @@ thread_around_empty_block (edge taken_edge,
+ gimple stmt;
+ tree cond;
+
+- /* This block must have a single predecessor (E->dest). */
+- if (!single_pred_p (bb))
+- return NULL;
+-
+- /* This block must have more than one successor. */
+- if (single_succ_p (bb))
+- return NULL;
+-
+ /* This block can have no PHI nodes. This is overly conservative. */
+ if (!gsi_end_p (gsi_start_phis (bb)))
+ return NULL;
+diff --git a/gcc/tree-ssa-threadupdate.c b/gcc/tree-ssa-threadupdate.c
+index 0e4cbc9..cf8df8e 100644
+--- a/gcc/tree-ssa-threadupdate.c
++++ b/gcc/tree-ssa-threadupdate.c
+@@ -1146,17 +1146,56 @@ mark_threaded_blocks (bitmap threaded_blocks)
+ edge e;
+ edge_iterator ei;
+
++ /* It is possible to have jump threads in which one is a subpath
++ of the other. ie, (A, B), (B, C), (C, D) where B is a joiner
++ block and (B, C), (C, D) where no joiner block exists.
++
++ When this occurs ignore the jump thread request with the joiner
++ block. It's totally subsumed by the simpler jump thread request.
++
++ This results in less block copying, simpler CFGs. More improtantly,
++ when we duplicate the joiner block, B, in this case we will create
++ a new threading opportunity that we wouldn't be able to optimize
++ until the next jump threading iteration.
++
++ So first convert the jump thread requests which do not require a
++ joiner block. */
+ for (i = 0; i < threaded_edges.length (); i += 3)
+ {
+ edge e = threaded_edges[i];
+- edge *x = XNEWVEC (edge, 2);
+
+- e->aux = x;
+- THREAD_TARGET (e) = threaded_edges[i + 1];
+- THREAD_TARGET2 (e) = threaded_edges[i + 2];
+- bitmap_set_bit (tmp, e->dest->index);
++ if (threaded_edges[i + 2] == NULL)
++ {
++ edge *x = XNEWVEC (edge, 2);
++
++ e->aux = x;
++ THREAD_TARGET (e) = threaded_edges[i + 1];
++ THREAD_TARGET2 (e) = NULL;
++ bitmap_set_bit (tmp, e->dest->index);
++ }
+ }
+
++
++ /* Now iterate again, converting cases where we threaded through
++ a joiner block, but ignoring those where we have already
++ threaded through the joiner block. */
++ for (i = 0; i < threaded_edges.length (); i += 3)
++ {
++ edge e = threaded_edges[i];
++
++ if (threaded_edges[i + 2] != NULL
++ && threaded_edges[i + 1]->aux == NULL)
++ {
++ edge *x = XNEWVEC (edge, 2);
++
++ e->aux = x;
++ THREAD_TARGET (e) = threaded_edges[i + 1];
++ THREAD_TARGET2 (e) = threaded_edges[i + 2];
++ bitmap_set_bit (tmp, e->dest->index);
++ }
++ }
++
++
+ /* If optimizing for size, only thread through block if we don't have
+ to duplicate it or it's an otherwise empty redirection block. */
+ if (optimize_function_for_size_p (cfun))
+--
+1.7.9.5
+
diff --git a/recipes-microblaze/gcc/gcc-microblaze-4.8.inc b/recipes-microblaze/gcc/gcc-microblaze-4.8.inc
new file mode 100644
index 00000000..f0578dbd
--- /dev/null
+++ b/recipes-microblaze/gcc/gcc-microblaze-4.8.inc
@@ -0,0 +1,16 @@
+
+# Add MicroBlaze Patches
+FILESEXTRAPATHS_append := "${THISDIR}/files:"
+SRC_URI_append += " \
+ file://0001-Patch-microblaze-Enable-DWARF-exception-handling-sup.patch \
+ file://0002-Patch-microblaze-Add-4-byte-implementation-for-atomi.patch \
+ file://0003-Patch-microblaze-Extend-jump-insn-to-accept-bri-to-S.patch \
+ file://0462b5f-2014-02-23-David-Holsgrove-david.holsgrove.patch \
+ file://0005-Patch-microblaze-Add-fstack-usage-support.patch \
+ file://0006-Patch-microblaze-Remove-SECONDARY_MEMORY_NEEDED.patch \
+ file://0007-Patch-microblaze-Add-SIZE_TYPE-and-PTRDIFF_TYPE-to-m.patch \
+ file://0008-Patch-microblaze-Add-branch_compare-instruction.patch \
+ file://Patch-microblaze-Fix-bswaphi2-implementation.patch \
+ file://Patch-microblaze-cstoresf4-add-mode-and-ordered_comp.patch \
+ file://gcc-Cherry-pick-mainline-patch-to-resolve-MB-k.patch \
+ "
diff --git a/recipes-microblaze/gcc/gcc-source_4.8.bbappend b/recipes-microblaze/gcc/gcc-source_4.8.bbappend
new file mode 100644
index 00000000..e28b4dd0
--- /dev/null
+++ b/recipes-microblaze/gcc/gcc-source_4.8.bbappend
@@ -0,0 +1 @@
+require gcc-microblaze-4.8.inc
diff --git a/recipes-microblaze/gdb/files/0001-Patch-microblaze-Add-wdc.ext.clear-and-wdc.ext.flush.patch b/recipes-microblaze/gdb/files/0001-Patch-microblaze-Add-wdc.ext.clear-and-wdc.ext.flush.patch
new file mode 100644
index 00000000..3575cd7e
--- /dev/null
+++ b/recipes-microblaze/gdb/files/0001-Patch-microblaze-Add-wdc.ext.clear-and-wdc.ext.flush.patch
@@ -0,0 +1,69 @@
+From 8ab9a20c73acedbb636a41842a681872af8ae1d6 Mon Sep 17 00:00:00 2001
+From: David Holsgrove <david.holsgrove@xilinx.com>
+Date: Wed, 8 May 2013 11:03:36 +1000
+Subject: [PATCH 01/16] [Patch, microblaze]: Add wdc.ext.clear and
+ wdc.ext.flush insns
+
+Added two new instructions, wdc.ext.clear and wdc.ext.flush,
+to enable MicroBlaze to flush an external cache, which is
+used with the new coherency support for multiprocessing.
+
+Signed-off-by:nagaraju <nmekala@xilix.com>
+Signed-off-by: David Holsgrove <david.holsgrove@xilinx.com>
+Upstream-Status: Pending
+---
+ opcodes/microblaze-opc.h | 5 ++++-
+ opcodes/microblaze-opcm.h | 6 +++---
+ 2 files changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/opcodes/microblaze-opc.h b/opcodes/microblaze-opc.h
+index e3cc1d9..f453097 100644
+--- a/opcodes/microblaze-opc.h
++++ b/opcodes/microblaze-opc.h
+@@ -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 @@ struct op_code_struct
+ {"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 --git a/opcodes/microblaze-opcm.h b/opcodes/microblaze-opcm.h
+index 6868389..8f5c1cb 100644
+--- a/opcodes/microblaze-opcm.h
++++ b/opcodes/microblaze-opcm.h
+@@ -31,9 +31,9 @@ enum microblaze_instr
+ 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,
+--
+1.9.0
+
diff --git a/recipes-microblaze/gdb/files/0003-Patch-microblaze-Initial-port-of-microblaze-core-rea.patch b/recipes-microblaze/gdb/files/0003-Patch-microblaze-Initial-port-of-microblaze-core-rea.patch
new file mode 100644
index 00000000..5d856408
--- /dev/null
+++ b/recipes-microblaze/gdb/files/0003-Patch-microblaze-Initial-port-of-microblaze-core-rea.patch
@@ -0,0 +1,384 @@
+From da27c7161c676550f5fe8a4e0f7f395e5e0d4770 Mon Sep 17 00:00:00 2001
+From: David Holsgrove <david.holsgrove@petalogix.com>
+Date: Fri, 18 May 2012 11:49:50 +1000
+Subject: [PATCH 03/16] [Patch, microblaze]: Initial port of microblaze core
+ reading support
+
+Added support for reading notes in linux core dumps
+Support for reading of PRSTATUS and PSINFO information for rebuilding
+".reg" sections of core dumps at run time.
+
+Signed-off-by: David Holsgrove <david.holsgrove@xilinx.com>
+Signed-off-by: Nathan Rossi <nathan.rossi@xilinx.com>
+Upstream-Status: Pending
+---
+ bfd/elf32-microblaze.c | 64 ++++++++++++++++++++++++++++++++
+ gdb/configure.tgt | 2 +-
+ gdb/microblaze-linux-tdep.c | 61 +++++++++++++++++++++++++++++++
+ gdb/microblaze-tdep.c | 89 +++++++++++++++++++++++++++++++++++++++++++++
+ gdb/microblaze-tdep.h | 28 ++++++++++++++
+ 5 files changed, 243 insertions(+), 1 deletion(-)
+
+diff --git a/bfd/elf32-microblaze.c b/bfd/elf32-microblaze.c
+index 9837b18..cbd18f0 100644
+--- a/bfd/elf32-microblaze.c
++++ b/bfd/elf32-microblaze.c
+@@ -668,6 +668,67 @@ microblaze_elf_is_local_label_name (bfd *abfd, const char *name)
+ 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
+@@ -3506,4 +3567,7 @@ microblaze_elf_add_symbol_hook (bfd *abfd,
+ #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 --git a/gdb/configure.tgt b/gdb/configure.tgt
+index 01311b2..9297c56 100644
+--- a/gdb/configure.tgt
++++ b/gdb/configure.tgt
+@@ -340,7 +340,7 @@ mep-*-*)
+
+ 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
+ ;;
+diff --git a/gdb/microblaze-linux-tdep.c b/gdb/microblaze-linux-tdep.c
+index 8d360eb..7e6b61b 100644
+--- a/gdb/microblaze-linux-tdep.c
++++ b/gdb/microblaze-linux-tdep.c
+@@ -32,6 +32,7 @@
+ #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"
+@@ -116,6 +117,43 @@ static struct tramp_frame microblaze_linux_sighandler_tramp_frame =
+ 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 (&microblaze_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 (&microblaze_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 +161,10 @@ microblaze_linux_init_abi (struct gdbarch_info info,
+ {
+ 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 +177,25 @@ microblaze_linux_init_abi (struct gdbarch_info info,
+ /* Trampolines. */
+ tramp_frame_prepend_unwinder (gdbarch,
+ &microblaze_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 --git a/gdb/microblaze-tdep.c b/gdb/microblaze-tdep.c
+index 14c1b52..36cf1ca 100644
+--- a/gdb/microblaze-tdep.c
++++ b/gdb/microblaze-tdep.c
+@@ -145,6 +145,14 @@ microblaze_push_dummy_code (struct gdbarch *gdbarch, CORE_ADDR sp,
+ 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,
+@@ -536,6 +544,12 @@ microblaze_frame_base_address (struct frame_info *next_frame,
+ return cache->base;
+ }
+
++static const struct frame_unwind *
++microblaze_frame_sniffer (struct frame_info *next_frame)
++{
++ return &microblaze_frame_unwind;
++}
++
+ static const struct frame_base microblaze_frame_base =
+ {
+ &microblaze_frame_unwind,
+@@ -664,6 +678,70 @@ microblaze_dwarf2_reg_to_regnum (struct gdbarch *gdbarch, int reg)
+ 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 +757,11 @@ microblaze_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
+ tdep = XNEW (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);
+@@ -726,6 +809,12 @@ microblaze_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
+ frame_unwind_append_unwinder (gdbarch, &microblaze_frame_unwind);
+ frame_base_append_sniffer (gdbarch, dwarf2_frame_base_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 --git a/gdb/microblaze-tdep.h b/gdb/microblaze-tdep.h
+index a532092..fec24b9 100644
+--- a/gdb/microblaze-tdep.h
++++ b/gdb/microblaze-tdep.h
+@@ -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
+@@ -117,4 +131,18 @@ enum microblaze_regnum
+ Only used for native debugging. */
+ #define MICROBLAZE_BREAKPOINT {0xb9, 0xcc, 0x00, 0x60}
+
++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 */
+--
+1.9.0
+
diff --git a/recipes-microblaze/gdb/files/0004-Patch-microblaze-Communicate-in-larger-blocks-with-t.patch b/recipes-microblaze/gdb/files/0004-Patch-microblaze-Communicate-in-larger-blocks-with-t.patch
new file mode 100644
index 00000000..b14e4092
--- /dev/null
+++ b/recipes-microblaze/gdb/files/0004-Patch-microblaze-Communicate-in-larger-blocks-with-t.patch
@@ -0,0 +1,67 @@
+From 26e124f0d78233b1d976bd4b787f6a7866bcb7e7 Mon Sep 17 00:00:00 2001
+From: nagaraju <nmekala@xilix.com>
+Date: Wed, 4 Jan 2012 16:59:33 +0530
+Subject: [PATCH 04/16] [Patch, microblaze]: Communicate in larger blocks with
+ the target
+
+Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
+Upstream-Status: Pending
+---
+ gdb/microblaze-tdep.c | 25 ++++++++++++++++++++++---
+ 1 file changed, 22 insertions(+), 3 deletions(-)
+
+diff --git a/gdb/microblaze-tdep.c b/gdb/microblaze-tdep.c
+index 36cf1ca..76e87b3 100644
+--- a/gdb/microblaze-tdep.c
++++ b/gdb/microblaze-tdep.c
+@@ -242,6 +242,10 @@ microblaze_analyze_prologue (struct gdbarch *gdbarch, CORE_ADDR pc,
+ int flags = 0;
+ int save_hidden_pointer_found = 0;
+ int non_stack_instruction_found = 0;
++ int n_insns;
++ unsigned long *insn_block;
++ gdb_byte *buf_block;
++ int ti, tj;
+
+ /* Find the start of this function. */
+ find_pc_partial_function (pc, &name, &func_addr, &func_end);
+@@ -281,9 +285,23 @@ microblaze_analyze_prologue (struct gdbarch *gdbarch, CORE_ADDR pc,
+ 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 = (unsigned long *)calloc(n_insns, sizeof(unsigned long));
++ buf_block = (gdb_byte *)calloc(n_insns * INST_WORD_SIZE, sizeof(gdb_byte));
++
++ target_read_memory (func_addr, buf_block, n_insns * INST_WORD_SIZE );
++
++ for(ti = 0; ti < n_insns; ti++){
++ insn_block[ti] = 0;
++ for( tj = ti * INST_WORD_SIZE; tj < (ti + 1) * INST_WORD_SIZE; tj++ )
++ insn_block[ti] = (insn_block[ti] << 8) | buf_block[tj];
++ }
++
+ for (addr = func_addr; addr < stop; addr += INST_WORD_SIZE)
+ {
+- insn = microblaze_fetch_instruction (addr);
++ //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);
+
+@@ -409,8 +427,9 @@ microblaze_analyze_prologue (struct gdbarch *gdbarch, CORE_ADDR pc,
+ part of the prologue. */
+ if (save_hidden_pointer_found)
+ prologue_end_addr -= INST_WORD_SIZE;
+-
+- return prologue_end_addr;
++ free(insn_block);
++ free(buf_block);
++ return prologue_end_addr;
+ }
+
+ static CORE_ADDR
+--
+1.9.0
+
diff --git a/recipes-microblaze/gdb/files/0005-Patch-microblaze-Add-mb-singlestepping.patch b/recipes-microblaze/gdb/files/0005-Patch-microblaze-Add-mb-singlestepping.patch
new file mode 100644
index 00000000..e490f02a
--- /dev/null
+++ b/recipes-microblaze/gdb/files/0005-Patch-microblaze-Add-mb-singlestepping.patch
@@ -0,0 +1,200 @@
+From 5c3a08f407e1cbee5b0a4ca6092165b97acddda5 Mon Sep 17 00:00:00 2001
+From: "Edgar E. Iglesias" <edgar@axis.com>
+Date: Fri, 24 Feb 2012 11:52:30 +0100
+Subject: [PATCH 05/16] [Patch, microblaze]: Add mb singlestepping.
+
+Fix prologue analysis for little-endian.
+Always provide a frame base.
+
+Signed-off-by: Edgar E. Iglesias <edgar@axis.com>
+Upstream-Status: Pending
+---
+ gdb/microblaze-tdep.c | 123 ++++++++++++++++++++++++++++++++++++++++++++------
+ 1 file changed, 108 insertions(+), 15 deletions(-)
+
+diff --git a/gdb/microblaze-tdep.c b/gdb/microblaze-tdep.c
+index 76e87b3..50b68d2 100644
+--- a/gdb/microblaze-tdep.c
++++ b/gdb/microblaze-tdep.c
+@@ -243,9 +243,7 @@ microblaze_analyze_prologue (struct gdbarch *gdbarch, CORE_ADDR pc,
+ int save_hidden_pointer_found = 0;
+ int non_stack_instruction_found = 0;
+ int n_insns;
+- unsigned long *insn_block;
+- gdb_byte *buf_block;
+- int ti, tj;
++ unsigned int *insn_block;
+
+ /* Find the start of this function. */
+ find_pc_partial_function (pc, &name, &func_addr, &func_end);
+@@ -287,23 +285,16 @@ microblaze_analyze_prologue (struct gdbarch *gdbarch, CORE_ADDR pc,
+
+ /* 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 = (unsigned long *)calloc(n_insns, sizeof(unsigned long));
+- buf_block = (gdb_byte *)calloc(n_insns * INST_WORD_SIZE, sizeof(gdb_byte));
++ insn_block = calloc(n_insns, sizeof(unsigned long));
+
+- target_read_memory (func_addr, buf_block, n_insns * INST_WORD_SIZE );
+-
+- for(ti = 0; ti < n_insns; ti++){
+- insn_block[ti] = 0;
+- for( tj = ti * INST_WORD_SIZE; tj < (ti + 1) * INST_WORD_SIZE; tj++ )
+- insn_block[ti] = (insn_block[ti] << 8) | buf_block[tj];
+- }
++ 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
+@@ -428,7 +419,6 @@ microblaze_analyze_prologue (struct gdbarch *gdbarch, CORE_ADDR pc,
+ if (save_hidden_pointer_found)
+ prologue_end_addr -= INST_WORD_SIZE;
+ free(insn_block);
+- free(buf_block);
+ return prologue_end_addr;
+ }
+
+@@ -502,6 +492,7 @@ microblaze_frame_cache (struct frame_info *next_frame, void **this_cache)
+
+ func = get_frame_func (next_frame);
+
++ cache->base = get_frame_register_unsigned (next_frame, gdbarch_sp_regnum (gdbarch));
+ cache->pc = get_frame_address_in_block (next_frame);
+
+ return cache;
+@@ -518,7 +509,7 @@ microblaze_frame_this_id (struct frame_info *next_frame, void **this_cache,
+ if (cache->base == 0)
+ return;
+
+- (*this_id) = frame_id_build (cache->base, cache->pc);
++ (*this_id) = frame_id_build (cache->base, get_frame_pc (next_frame));
+ }
+
+ static struct value *
+@@ -661,6 +652,107 @@ microblaze_stabs_argument_has_addr (struct gdbarch *gdbarch, struct type *type)
+ 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)
+ {
+@@ -809,6 +901,7 @@ microblaze_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
+ set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
+
+ 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);
+
+--
+1.9.0
+
diff --git a/recipes-microblaze/gdb/files/0006-Patch-microblaze-Add-initial-port-of-linux-gdbserver.patch b/recipes-microblaze/gdb/files/0006-Patch-microblaze-Add-initial-port-of-linux-gdbserver.patch
new file mode 100644
index 00000000..cb2eec18
--- /dev/null
+++ b/recipes-microblaze/gdb/files/0006-Patch-microblaze-Add-initial-port-of-linux-gdbserver.patch
@@ -0,0 +1,553 @@
+From 2112c9ded01ddd08f0e31e5ce23eecac6c04e8c4 Mon Sep 17 00:00:00 2001
+From: David Holsgrove <david.holsgrove@petalogix.com>
+Date: Mon, 6 Feb 2012 10:28:29 +1000
+Subject: [PATCH 06/16] [Patch, microblaze]: Add initial port of linux
+ gdbserver
+
+add gdb_proc_service_h to gdbserver microblaze-linux
+
+gdbserver needs to initialise the microblaze registers
+
+other archs use this step to run a *_arch_setup() to carry out all
+architecture specific setup - may need to add in future
+
+ * add linux-ptrace.o to gdbserver configure
+ * gdb/configure.tgt: Set build_gdbserver=yes
+ * Update breakpoint opcode
+ * fix segfault on connecting gdbserver
+ * add microblaze_linux_memory_remove_breakpoint
+ * add set_solib_svr4_fetch_link_map_offsets
+ * add set_gdbarch_fetch_tls_load_module_address
+ * Force reading of r0 as 0, prevent stores
+
+Signed-off-by: David Holsgrove <david.holsgrove@petalogix.com>
+Signed-off-by: Nathan Rossi <nathan.rossi@petalogix.com>
+Upstream-Status: Pending
+---
+ gdb/configure.host | 3 +
+ gdb/configure.tgt | 1 +
+ gdb/gdbserver/Makefile.in | 4 +
+ gdb/gdbserver/configure.srv | 6 +
+ gdb/gdbserver/linux-microblaze-low.c | 228 +++++++++++++++++++++++++++++++++++
+ gdb/microblaze-linux-tdep.c | 25 +++-
+ gdb/microblaze-tdep.c | 45 ++++++-
+ gdb/microblaze-tdep.h | 3 +-
+ gdb/regformats/reg-microblaze.dat | 39 ++++++
+ 9 files changed, 348 insertions(+), 6 deletions(-)
+ create mode 100644 gdb/gdbserver/linux-microblaze-low.c
+ create mode 100644 gdb/regformats/reg-microblaze.dat
+
+diff --git a/gdb/configure.host b/gdb/configure.host
+index 15a8288..76cc5fe 100644
+--- a/gdb/configure.host
++++ b/gdb/configure.host
+@@ -59,6 +59,7 @@ i[34567]86*) gdb_host_cpu=i386 ;;
+ 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 @@ mips*-*-netbsd* | mips*-*-knetbsd*-gnu)
+ 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 --git a/gdb/configure.tgt b/gdb/configure.tgt
+index 9297c56..3a7951a 100644
+--- a/gdb/configure.tgt
++++ b/gdb/configure.tgt
+@@ -343,6 +343,7 @@ microblaze*-linux-*|microblaze*-*-linux*)
+ 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 --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
+index f773fa2..a11ace1 100644
+--- a/gdb/gdbserver/Makefile.in
++++ b/gdb/gdbserver/Makefile.in
+@@ -148,6 +148,7 @@ SFILES= $(srcdir)/gdbreplay.c $(srcdir)/inferiors.c $(srcdir)/dll.c \
+ $(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 \
+@@ -329,6 +330,7 @@ clean:
+ 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
+@@ -612,6 +614,8 @@ reg-m68k.c : $(srcdir)/../regformats/reg-m68k.dat $(regdat_sh)
+ $(SHELL) $(regdat_sh) $(srcdir)/../regformats/reg-m68k.dat reg-m68k.c
+ reg-cf.c : $(srcdir)/../regformats/reg-cf.dat $(regdat_sh)
+ $(SHELL) $(regdat_sh) $(srcdir)/../regformats/reg-cf.dat reg-cf.c
++microblaze-linux.c : $(srcdir)/../regformats/reg-microblaze.dat $(regdat_sh)
++ $(SHELL) $(regdat_sh) $(srcdir)/../regformats/reg-microblaze.dat microblaze-linux.c
+ mips-linux.c : $(srcdir)/../regformats/mips-linux.dat $(regdat_sh)
+ $(SHELL) $(regdat_sh) $(srcdir)/../regformats/mips-linux.dat mips-linux.c
+ mips-dsp-linux.c : $(srcdir)/../regformats/mips-dsp-linux.dat $(regdat_sh)
+diff --git a/gdb/gdbserver/configure.srv b/gdb/gdbserver/configure.srv
+index cc4f53d..359c756 100644
+--- a/gdb/gdbserver/configure.srv
++++ b/gdb/gdbserver/configure.srv
+@@ -198,6 +198,12 @@ case "${target}" in
+ 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 --git a/gdb/gdbserver/linux-microblaze-low.c b/gdb/gdbserver/linux-microblaze-low.c
+new file mode 100644
+index 0000000..279df9f
+--- /dev/null
++++ b/gdb/gdbserver/linux-microblaze-low.c
+@@ -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*)&regbuf_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 */
++ &microblaze_usrregs_info,
++ &microblaze_regsets_info
++ };
++
++static const struct regs_info *
++microblaze_regs_info (void)
++{
++ return &regs_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 *) &microblaze_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 (&microblaze_regsets_info);
++}
+\ No newline at end of file
+diff --git a/gdb/microblaze-linux-tdep.c b/gdb/microblaze-linux-tdep.c
+index 7e6b61b..cf58e21 100644
+--- a/gdb/microblaze-linux-tdep.c
++++ b/gdb/microblaze-linux-tdep.c
+@@ -38,6 +38,22 @@
+ #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)
+@@ -47,20 +63,27 @@ microblaze_linux_memory_remove_breakpoint (struct gdbarch *gdbarch,
+ 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;
+ }
+
+diff --git a/gdb/microblaze-tdep.c b/gdb/microblaze-tdep.c
+index 50b68d2..1c6dbfe 100644
+--- a/gdb/microblaze-tdep.c
++++ b/gdb/microblaze-tdep.c
+@@ -164,6 +164,39 @@ microblaze_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
+ 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)
+@@ -291,8 +324,8 @@ microblaze_analyze_prologue (struct gdbarch *gdbarch, CORE_ADDR pc,
+
+ for (addr = func_addr; addr < stop; addr += INST_WORD_SIZE)
+ {
+- //insn = microblaze_fetch_instruction (addr);
+- insn = insn_block[(addr - func_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 op=%x r%d r%d imm=%d\n", paddress (gdbarch, addr), insn, op, rd, ra, imm);
+
+@@ -724,13 +757,15 @@ microblaze_software_single_step (struct frame_info *frame)
+ 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);
++ 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].address != pc)) {
+ stepbreaks[1].valid = TRUE;
+ } else {
+ stepbreaks[1].valid = FALSE;
+@@ -900,6 +935,8 @@ microblaze_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
+ /* 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);
+
+diff --git a/gdb/microblaze-tdep.h b/gdb/microblaze-tdep.h
+index fec24b9..98aa0f5 100644
+--- a/gdb/microblaze-tdep.h
++++ b/gdb/microblaze-tdep.h
+@@ -129,7 +129,8 @@ enum microblaze_regnum
+
+ /* 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,
+diff --git a/gdb/regformats/reg-microblaze.dat b/gdb/regformats/reg-microblaze.dat
+new file mode 100644
+index 0000000..a5dd0a0
+--- /dev/null
++++ b/gdb/regformats/reg-microblaze.dat
+@@ -0,0 +1,39 @@
++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
+--
+1.9.0
+
diff --git a/recipes-microblaze/gdb/files/0007-Patch-microblaze-Add-slr-and-shr-regs-and-little-end.patch b/recipes-microblaze/gdb/files/0007-Patch-microblaze-Add-slr-and-shr-regs-and-little-end.patch
new file mode 100644
index 00000000..7cd11905
--- /dev/null
+++ b/recipes-microblaze/gdb/files/0007-Patch-microblaze-Add-slr-and-shr-regs-and-little-end.patch
@@ -0,0 +1,82 @@
+From fb2af2fffb673dbb14d743c8da94c4a83b71c792 Mon Sep 17 00:00:00 2001
+From: David Holsgrove <david.holsgrove@xilinx.com>
+Date: Mon, 26 Nov 2012 17:39:17 +1000
+Subject: [PATCH 07/16] [Patch, microblaze]: Add slr and shr regs and
+ little-endian breakpoint
+
+Signed-off-by: David Holsgrove <david.holsgrove@xilinx.com>
+Upstream-Status: Pending
+---
+ gdb/microblaze-tdep.c | 10 ++++++++--
+ gdb/microblaze-tdep.h | 6 ++++--
+ gdb/regformats/reg-microblaze.dat | 2 ++
+ 3 files changed, 14 insertions(+), 4 deletions(-)
+
+diff --git a/gdb/microblaze-tdep.c b/gdb/microblaze-tdep.c
+index 1c6dbfe..0ce4947 100644
+--- a/gdb/microblaze-tdep.c
++++ b/gdb/microblaze-tdep.c
+@@ -73,7 +73,8 @@ static const char *microblaze_register_names[] =
+ "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)
+@@ -201,10 +202,15 @@ 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. */
+diff --git a/gdb/microblaze-tdep.h b/gdb/microblaze-tdep.h
+index 98aa0f5..cd32e9f 100644
+--- a/gdb/microblaze-tdep.h
++++ b/gdb/microblaze-tdep.h
+@@ -56,7 +56,7 @@ struct microblaze_frame_cache
+ 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. */
+
+ /* Table of saved registers. */
+ struct trad_frame_saved_reg *saved_regs;
+@@ -121,7 +121,9 @@ enum microblaze_regnum
+ 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. */
+diff --git a/gdb/regformats/reg-microblaze.dat b/gdb/regformats/reg-microblaze.dat
+index a5dd0a0..bd8a438 100644
+--- a/gdb/regformats/reg-microblaze.dat
++++ b/gdb/regformats/reg-microblaze.dat
+@@ -37,3 +37,5 @@ expedite:r1,pc
+ 32:ear
+ 32:esr
+ 32:fsr
++32:slr
++32:shr
+--
+1.9.0
+
diff --git a/recipes-microblaze/gdb/files/0008-Patch-microblaze-Added-Backtrace-support-to-GDB.patch b/recipes-microblaze/gdb/files/0008-Patch-microblaze-Added-Backtrace-support-to-GDB.patch
new file mode 100644
index 00000000..7f075d55
--- /dev/null
+++ b/recipes-microblaze/gdb/files/0008-Patch-microblaze-Added-Backtrace-support-to-GDB.patch
@@ -0,0 +1,156 @@
+From 7944750e435100e72913f01aa0a43b7d7cffd421 Mon Sep 17 00:00:00 2001
+From: nagaraju <nmekala@xilix.com>
+Date: Tue, 3 Sep 2013 12:09:47 +0530
+Subject: [PATCH 08/16] [Patch, microblaze]: Added Backtrace support to GDB
+
+Added backtrace support without debugging information.
+
+Earlier backtrace used to work only when debug information is available.
+Previous pc & sp values are calculated incorrectly due to which backtrace
+was failing.
+
+In this patch, previous frame sp & pc values are calculated correctly
+in microblaze_frame_cache function and supplied them to
+microblaze_frame_prev_register function
+
+Signed-off-by:nagaraju <nmekala@xilix.com>
+Upstream-Status: Pending
+---
+ gdb/microblaze-tdep.c | 42 ++++++++++++++++++++++++++++++++++--------
+ gdb/microblaze-tdep.h | 5 +++--
+ 2 files changed, 37 insertions(+), 10 deletions(-)
+
+diff --git a/gdb/microblaze-tdep.c b/gdb/microblaze-tdep.c
+index 0ce4947..247740e 100644
+--- a/gdb/microblaze-tdep.c
++++ b/gdb/microblaze-tdep.c
+@@ -225,6 +225,7 @@ microblaze_alloc_frame_cache (void)
+ /* Base address. */
+ cache->base = 0;
+ cache->pc = 0;
++ cache->saved_sp = 0;
+
+ /* Frameless until proven otherwise. */
+ cache->frameless_p = 1;
+@@ -347,6 +348,7 @@ microblaze_analyze_prologue (struct gdbarch *gdbarch, CORE_ADDR pc,
+ 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))
+@@ -508,6 +510,7 @@ microblaze_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
+ return start_pc;
+ }
+
++enum { REG_UNAVAIL = (CORE_ADDR) -1 };
+ /* Normal frames. */
+
+ static struct microblaze_frame_cache *
+@@ -515,7 +518,7 @@ microblaze_frame_cache (struct frame_info *next_frame, void **this_cache)
+ {
+ 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)
+@@ -529,10 +532,18 @@ microblaze_frame_cache (struct frame_info *next_frame, void **this_cache)
+ 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->base = get_frame_register_unsigned (next_frame, gdbarch_sp_regnum (gdbarch));
+- cache->pc = get_frame_address_in_block (next_frame);
++ 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;
+ }
+@@ -548,7 +559,7 @@ microblaze_frame_this_id (struct frame_info *next_frame, void **this_cache,
+ if (cache->base == 0)
+ return;
+
+- (*this_id) = frame_id_build (cache->base, get_frame_pc (next_frame));
++ (*this_id) = frame_id_build (cache->base, cache->pc);
+ }
+
+ static struct value *
+@@ -558,6 +569,14 @@ microblaze_frame_prev_register (struct frame_info *this_frame,
+ 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)
+@@ -565,11 +584,18 @@ microblaze_frame_prev_register (struct frame_info *this_frame,
+ 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);
+
+ }
+
+diff --git a/gdb/microblaze-tdep.h b/gdb/microblaze-tdep.h
+index cd32e9f..14eb3ab 100644
+--- a/gdb/microblaze-tdep.h
++++ b/gdb/microblaze-tdep.h
+@@ -57,6 +57,7 @@ struct microblaze_frame_cache
+
+ /* Offsets to saved registers. */
+ int register_offsets[59]; /* Must match MICROBLAZE_NUM_REGS. */
++ CORE_ADDR saved_sp;
+
+ /* Table of saved registers. */
+ struct trad_frame_saved_reg *saved_regs;
+@@ -80,11 +81,11 @@ enum microblaze_regnum
+ 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,
+--
+1.9.0
+
diff --git a/recipes-microblaze/gdb/files/0009-Patch-microblaze-Initial-support-for-native-gdb.patch b/recipes-microblaze/gdb/files/0009-Patch-microblaze-Initial-support-for-native-gdb.patch
new file mode 100644
index 00000000..1ad6b89c
--- /dev/null
+++ b/recipes-microblaze/gdb/files/0009-Patch-microblaze-Initial-support-for-native-gdb.patch
@@ -0,0 +1,495 @@
+From c7b918283f2e438deef78aae84f6b748a7a1bb54 Mon Sep 17 00:00:00 2001
+From: David Holsgrove <david.holsgrove@petalogix.com>
+Date: Fri, 20 Jul 2012 15:18:35 +1000
+Subject: [PATCH 09/16] [Patch, microblaze]: Initial support for native gdb
+
+microblaze: Follow PPC method of getting setting registers
+using PTRACE PEEK/POKE
+
+Signed-off-by: David Holsgrove <david.holsgrove@petalogix.com>
+Upstream-Status: Pending
+---
+ gdb/Makefile.in | 4 +-
+ gdb/config/microblaze/linux.mh | 10 +
+ gdb/microblaze-linux-nat.c | 431 +++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 443 insertions(+), 2 deletions(-)
+ create mode 100644 gdb/config/microblaze/linux.mh
+ create mode 100644 gdb/microblaze-linux-nat.c
+
+diff --git a/gdb/Makefile.in b/gdb/Makefile.in
+index f2c16ec..12870a4 100644
+--- a/gdb/Makefile.in
++++ b/gdb/Makefile.in
+@@ -904,7 +904,7 @@ top.h bsd-kvm.h gdb-stabs.h reggroups.h \
+ 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 \
+@@ -1631,7 +1631,7 @@ ALLDEPFILES = \
+ 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 --git a/gdb/config/microblaze/linux.mh b/gdb/config/microblaze/linux.mh
+new file mode 100644
+index 0000000..547d103
+--- /dev/null
++++ b/gdb/config/microblaze/linux.mh
+@@ -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 --git a/gdb/microblaze-linux-nat.c b/gdb/microblaze-linux-nat.c
+new file mode 100644
+index 0000000..81f8346
+--- /dev/null
++++ b/gdb/microblaze-linux-nat.c
+@@ -0,0 +1,431 @@
++/* 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 <string.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, &microblaze_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);
++}
+--
+1.9.0
diff --git a/recipes-microblaze/gdb/files/0010-Patch-gdb-Robustify-inline-function-support.patch b/recipes-microblaze/gdb/files/0010-Patch-gdb-Robustify-inline-function-support.patch
new file mode 100644
index 00000000..3912ca57
--- /dev/null
+++ b/recipes-microblaze/gdb/files/0010-Patch-gdb-Robustify-inline-function-support.patch
@@ -0,0 +1,43 @@
+From a02963a97d7ce38b0af205f9e3e6dd7e0e06d9be Mon Sep 17 00:00:00 2001
+From: "Edgar E. Iglesias" <edgar@axis.com>
+Date: Mon, 27 Feb 2012 06:28:00 +0100
+Subject: [PATCH 10/16] [Patch, gdb]: Robustify inline function support
+
+Signed-off-by: Edgar E. Iglesias <edgar@axis.com>
+Upstream-Status: Pending
+---
+ gdb/blockframe.c | 3 ++-
+ gdb/inline-frame.c | 3 +++
+ 2 files changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/gdb/blockframe.c b/gdb/blockframe.c
+index 0a9381e..ba41d85 100644
+--- a/gdb/blockframe.c
++++ b/gdb/blockframe.c
+@@ -77,7 +77,8 @@ get_frame_block (struct frame_info *frame, CORE_ADDR *addr_in_block)
+ inline_count--;
+
+ bl = BLOCK_SUPERBLOCK (bl);
+- gdb_assert (bl != NULL);
++ if (!bl)
++ return NULL;
+ }
+
+ return bl;
+diff --git a/gdb/inline-frame.c b/gdb/inline-frame.c
+index eb82143..a793390 100644
+--- a/gdb/inline-frame.c
++++ b/gdb/inline-frame.c
+@@ -231,6 +231,9 @@ inline_frame_sniffer (const struct frame_unwind *self,
+ cur_block = BLOCK_SUPERBLOCK (cur_block);
+ }
+
++ if (depth == 0)
++ return 0;
++
+ /* Check how many inlined functions already have frames. */
+ for (next_frame = get_next_frame (this_frame);
+ next_frame && get_frame_type (next_frame) == INLINE_FRAME;
+--
+1.9.0
+
diff --git a/recipes-microblaze/gdb/files/0011-Patch-gdb-Fix-debug-message-when-register-is-unavail.patch b/recipes-microblaze/gdb/files/0011-Patch-gdb-Fix-debug-message-when-register-is-unavail.patch
new file mode 100644
index 00000000..bdec77c5
--- /dev/null
+++ b/recipes-microblaze/gdb/files/0011-Patch-gdb-Fix-debug-message-when-register-is-unavail.patch
@@ -0,0 +1,43 @@
+From a05fb34192727fc1b63c827ed006ddde846ce6b8 Mon Sep 17 00:00:00 2001
+From: Nathan Rossi <nathan.rossi@petalogix.com>
+Date: Tue, 8 May 2012 18:11:17 +1000
+Subject: [PATCH 11/16] [Patch, gdb]: Fix debug message when register is
+ unavailable
+
+Signed-off-by: Nathan Rossi <nathan.rossi@xilinx.com>
+Signed-off-by: David Holsgrove <david.holsgrove@xilinx.com>
+Upstream-Status: Pending
+---
+ gdb/frame.c | 13 ++++++++++---
+ 1 file changed, 10 insertions(+), 3 deletions(-)
+
+diff --git a/gdb/frame.c b/gdb/frame.c
+index 013d602..4d0766f 100644
+--- a/gdb/frame.c
++++ b/gdb/frame.c
+@@ -1134,12 +1134,19 @@ frame_unwind_register_value (struct frame_info *frame, int regnum)
+ else
+ {
+ int i;
+- const gdb_byte *buf = value_contents (value);
++ const gdb_byte *buf = NULL;
++ if (value_entirely_available(value)) {
++ buf = value_contents (value);
++ }
+
+ fprintf_unfiltered (gdb_stdlog, " bytes=");
+ fprintf_unfiltered (gdb_stdlog, "[");
+- for (i = 0; i < register_size (gdbarch, regnum); i++)
+- fprintf_unfiltered (gdb_stdlog, "%02x", buf[i]);
++ if (buf != NULL) {
++ for (i = 0; i < register_size (gdbarch, regnum); i++)
++ fprintf_unfiltered (gdb_stdlog, "%02x", buf[i]);
++ } else {
++ fprintf_unfiltered (gdb_stdlog, "unavailable");
++ }
+ fprintf_unfiltered (gdb_stdlog, "]");
+ }
+ }
+--
+1.9.0
+
diff --git a/recipes-microblaze/gdb/files/0012-LOCAL-Disable-the-warning-message-for-eh_frame_hdr.patch b/recipes-microblaze/gdb/files/0012-LOCAL-Disable-the-warning-message-for-eh_frame_hdr.patch
new file mode 100644
index 00000000..819cd179
--- /dev/null
+++ b/recipes-microblaze/gdb/files/0012-LOCAL-Disable-the-warning-message-for-eh_frame_hdr.patch
@@ -0,0 +1,34 @@
+From f54d5334afe799e15ca21c5d83097a4c81bbab7e Mon Sep 17 00:00:00 2001
+From: "Edgar E. Iglesias" <edgar.iglesias@gmail.com>
+Date: Fri, 22 Jun 2012 01:20:20 +0200
+Subject: [PATCH 12/16] [LOCAL]: Disable the warning message for eh_frame_hdr
+
+Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
+Upstream-Status: Pending
+---
+ bfd/elf-eh-frame.c | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/bfd/elf-eh-frame.c b/bfd/elf-eh-frame.c
+index 0f0a563..7d8e047 100644
+--- a/bfd/elf-eh-frame.c
++++ b/bfd/elf-eh-frame.c
+@@ -919,9 +919,12 @@ _bfd_elf_parse_eh_frame (bfd *abfd, struct bfd_link_info *info,
+ goto success;
+
+ free_no_table:
+- (*info->callbacks->einfo)
+- (_("%P: error in %B(%A); no .eh_frame_hdr table will be created.\n"),
+- abfd, sec);
++ /* FIXME: Remove the microblaze specifics when relaxing gets fixed. */
++ if (bfd_get_arch(abfd) != bfd_arch_microblaze) {
++ (*info->callbacks->einfo)
++ (_("%P: error in %B(%A); no .eh_frame_hdr table will be created.\n"),
++ abfd, sec);
++ }
+ hdr_info->table = FALSE;
+ if (sec_info)
+ free (sec_info);
+--
+1.9.0
+
diff --git a/recipes-microblaze/gdb/files/0013-LOCAL-Fix-relaxation-of-assembler-resolved-reference.patch b/recipes-microblaze/gdb/files/0013-LOCAL-Fix-relaxation-of-assembler-resolved-reference.patch
new file mode 100644
index 00000000..3a0eae83
--- /dev/null
+++ b/recipes-microblaze/gdb/files/0013-LOCAL-Fix-relaxation-of-assembler-resolved-reference.patch
@@ -0,0 +1,64 @@
+From c9f1f07e5b0756069e3d4b04eb9505027f09677f Mon Sep 17 00:00:00 2001
+From: "Edgar E. Iglesias" <edgar.iglesias@gmail.com>
+Date: Tue, 14 Feb 2012 01:00:22 +0100
+Subject: [PATCH 13/16] [LOCAL]: Fix relaxation of assembler resolved
+ references
+
+Upstream-Status: Pending
+---
+ bfd/elf32-microblaze.c | 39 +++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 39 insertions(+)
+
+diff --git a/bfd/elf32-microblaze.c b/bfd/elf32-microblaze.c
+index cbd18f0..f90df47 100644
+--- a/bfd/elf32-microblaze.c
++++ b/bfd/elf32-microblaze.c
+@@ -1968,6 +1968,45 @@ microblaze_elf_relax_section (bfd *abfd,
+ irelscanend = irelocs + o->reloc_count;
+ for (irelscan = irelocs; irelscan < irelscanend; irelscan++)
+ {
++ if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_NONE)
++ {
++ unsigned int val;
++
++ isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
++
++ /* 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;
++ }
++ }
++
++ irelscan->r_addend -= calc_fixup (irelscan->r_addend
++ + isym->st_value, sec);
++ val = bfd_get_32 (abfd, ocontents + irelscan->r_offset);
++ microblaze_bfd_write_imm_value_32 (abfd, ocontents + irelscan->r_offset,
++ irelscan->r_addend);
++ }
++ if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_64_NONE) {
++ fprintf(stderr, "Unhandled NONE 64\n");
++ }
+ if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32)
+ {
+ isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
+--
+1.9.0
+
diff --git a/recipes-microblaze/gdb/files/0014-LOCAL-Fixup-debug_loc-sections-after-linker-relaxati.patch b/recipes-microblaze/gdb/files/0014-LOCAL-Fixup-debug_loc-sections-after-linker-relaxati.patch
new file mode 100644
index 00000000..85cee9d5
--- /dev/null
+++ b/recipes-microblaze/gdb/files/0014-LOCAL-Fixup-debug_loc-sections-after-linker-relaxati.patch
@@ -0,0 +1,192 @@
+From aca2758cff1f8fdc5ad7b6076ef985ba9ec5f857 Mon Sep 17 00:00:00 2001
+From: David Holsgrove <david.holsgrove@xilinx.com>
+Date: Mon, 4 Feb 2013 12:15:22 +1000
+Subject: [PATCH 14/16] [LOCAL]: Fixup debug_loc sections after linker
+ relaxation
+
+Adds a new reloctype R_MICROBLAZE_32_NONE, used for passing
+reloc info from the assembler to the linker when the linker
+manages to fully resolve a local symbol reference.
+
+This is a workaround for design flaws in the assembler to
+linker interface with regards to linker relaxation.
+
+Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
+Signed-off-by: David Holsgrove <david.holsgrove@xilinx.com>
+Upstream-Status: Pending
+---
+ bfd/bfd-in2.h | 5 +++++
+ bfd/elf32-microblaze.c | 45 +++++++++++++++++++++++++++++++++++++--------
+ bfd/libbfd.h | 1 +
+ bfd/reloc.c | 6 ++++++
+ include/elf/microblaze.h | 1 +
+ 5 files changed, 50 insertions(+), 8 deletions(-)
+
+diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
+index 8b7f2ee..de38907 100644
+--- a/bfd/bfd-in2.h
++++ b/bfd/bfd-in2.h
+@@ -5449,6 +5449,11 @@ value relative to the read-write small data area anchor */
+ 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 --git a/bfd/elf32-microblaze.c b/bfd/elf32-microblaze.c
+index f90df47..a3f89b9 100644
+--- a/bfd/elf32-microblaze.c
++++ b/bfd/elf32-microblaze.c
+@@ -177,6 +177,20 @@ static reloc_howto_type microblaze_elf_howto_raw[] =
+ 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 @@ microblaze_elf_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
+ 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:
+@@ -1913,14 +1930,22 @@ microblaze_elf_relax_section (bfd *abfd,
+ }
+ 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,
+@@ -1968,12 +1993,16 @@ microblaze_elf_relax_section (bfd *abfd,
+ irelscanend = irelocs + o->reloc_count;
+ for (irelscan = irelocs; irelscan < irelscanend; irelscan++)
+ {
+- if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_NONE)
++ 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)
+ {
+@@ -1998,15 +2027,15 @@ microblaze_elf_relax_section (bfd *abfd,
+ }
+ }
+
+- irelscan->r_addend -= calc_fixup (irelscan->r_addend
+- + isym->st_value, sec);
+ 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_64_NONE) {
+- fprintf(stderr, "Unhandled NONE 64\n");
+- }
+ if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32)
+ {
+ isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
+@@ -2066,7 +2095,7 @@ microblaze_elf_relax_section (bfd *abfd,
+ 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);
+diff --git a/bfd/libbfd.h b/bfd/libbfd.h
+index 09f307f..840c662 100644
+--- a/bfd/libbfd.h
++++ b/bfd/libbfd.h
+@@ -2644,6 +2644,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
+ "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 --git a/bfd/reloc.c b/bfd/reloc.c
+index 7f46c58..5bcd52d 100644
+--- a/bfd/reloc.c
++++ b/bfd/reloc.c
+@@ -6396,6 +6396,12 @@ ENUMDOC
+ This is a 32 bit reloc for the microblaze to handle
+ expressions of the form "Symbol Op Symbol"
+ ENUM
++ BFD_RELOC_MICROBLAZE_32_NONE
++ENUMDOC
++ 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
++ENUM
+ BFD_RELOC_MICROBLAZE_64_NONE
+ ENUMDOC
+ This is a 64 bit reloc that stores the 32 bit pc relative
+diff --git a/include/elf/microblaze.h b/include/elf/microblaze.h
+index effca20..f8420dc 100644
+--- a/include/elf/microblaze.h
++++ b/include/elf/microblaze.h
+@@ -58,6 +58,7 @@ START_RELOC_NUMBERS (elf_microblaze_reloc_type)
+ 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)
+
+--
+1.9.0
+
diff --git a/recipes-microblaze/gdb/files/0015-LOCAL-upstream-change-to-garbage-collection-sweep-ca.patch b/recipes-microblaze/gdb/files/0015-LOCAL-upstream-change-to-garbage-collection-sweep-ca.patch
new file mode 100644
index 00000000..0bb66a94
--- /dev/null
+++ b/recipes-microblaze/gdb/files/0015-LOCAL-upstream-change-to-garbage-collection-sweep-ca.patch
@@ -0,0 +1,40 @@
+From 22c63d4d79ac488403340470c14c73bad4984fa3 Mon Sep 17 00:00:00 2001
+From: David Holsgrove <david.holsgrove@xilinx.com>
+Date: Wed, 27 Feb 2013 13:56:11 +1000
+Subject: [PATCH 15/16] [LOCAL]: upstream change to garbage collection sweep
+ causes mb regression
+
+Upstream change for PR13177 now clears the def_regular during gc_sweep of a
+section. (All other archs in binutils/bfd/elf32-*.c received an update
+to a warning about unresolvable relocations - this warning is not present
+in binutils/bfd/elf32-microblaze.c, but this warning check would not
+prevent the error being seen)
+
+The visible issue with this change is when running a c++ application
+in Petalinux which links libstdc++.so for exception handling it segfaults
+on execution.
+
+This does not occur if static linking libstdc++.a, so its during the
+relocations for a shared lib with garbage collection this occurs
+
+Signed-off-by: David Holsgrove <david.holsgrove@xilinx.com>
+Upstream-Status: Pending
+---
+ bfd/elflink.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/bfd/elflink.c b/bfd/elflink.c
+index 6756fb1..f21dc06 100644
+--- a/bfd/elflink.c
++++ b/bfd/elflink.c
+@@ -11932,7 +11932,6 @@ elf_gc_sweep_symbol (struct elf_link_hash_entry *h, void *data)
+
+ inf = (struct elf_gc_sweep_symbol_info *) data;
+ (*inf->hide_symbol) (inf->info, h, TRUE);
+- h->def_regular = 0;
+ h->ref_regular = 0;
+ h->ref_regular_nonweak = 0;
+ }
+--
+1.9.0
+
diff --git a/recipes-microblaze/gdb/gdb-7.7.1.inc b/recipes-microblaze/gdb/gdb-7.7.1.inc
new file mode 100644
index 00000000..04488e9e
--- /dev/null
+++ b/recipes-microblaze/gdb/gdb-7.7.1.inc
@@ -0,0 +1,11 @@
+LICENSE = "GPLv2 & GPLv3 & LGPLv2 & LGPLv3"
+LIC_FILES_CHKSUM = "file://COPYING;md5=59530bdf33659b29e73d4adb9f9f6552 \
+ file://COPYING3;md5=d32239bcb673463ab874e80d47fae504 \
+ file://COPYING3.LIB;md5=6a6a8e020838b23406c81b19c1d46df6 \
+ file://COPYING.LIB;md5=9f604d8a4f8e74f4f5140845a21b6674"
+
+S = "${WORKDIR}/${BPN}-${PV}"
+
+SRC_URI[md5sum] = "45b07b53d81832d32ccd4829465d4886"
+SRC_URI[sha256sum] = "eefadb9831e3695d1eaef34e98b8f1fb441df6fe5071317ea49c6bd6ba213eff"
+
diff --git a/recipes-microblaze/gdb/gdb-cross-canadian_7.7.1.bb b/recipes-microblaze/gdb/gdb-cross-canadian_7.7.1.bb
new file mode 100644
index 00000000..c349ebbb
--- /dev/null
+++ b/recipes-microblaze/gdb/gdb-cross-canadian_7.7.1.bb
@@ -0,0 +1,4 @@
+require recipes-devtools/gdb/gdb-common.inc
+require recipes-devtools/gdb/gdb-cross-canadian.inc
+require gdb-${PV}.inc
+require gdb-microblaze-7.7.inc
diff --git a/recipes-microblaze/gdb/gdb-cross_7.7.1.bb b/recipes-microblaze/gdb/gdb-cross_7.7.1.bb
new file mode 100644
index 00000000..98b3359c
--- /dev/null
+++ b/recipes-microblaze/gdb/gdb-cross_7.7.1.bb
@@ -0,0 +1,3 @@
+require recipes-devtools/gdb/gdb-cross.inc
+require gdb-${PV}.inc
+require gdb-microblaze-7.7.inc
diff --git a/recipes-microblaze/gdb/gdb-microblaze-7.7.inc b/recipes-microblaze/gdb/gdb-microblaze-7.7.inc
new file mode 100644
index 00000000..0b82bc67
--- /dev/null
+++ b/recipes-microblaze/gdb/gdb-microblaze-7.7.inc
@@ -0,0 +1,22 @@
+
+# MicroBlaze does not support LTTng UST
+LTTNGUST_microblaze = ""
+
+# Add MicroBlaze Patches
+FILESEXTRAPATHS_append := "${THISDIR}/files:"
+SRC_URI_append += " \
+ file://0001-Patch-microblaze-Add-wdc.ext.clear-and-wdc.ext.flush.patch \
+ file://0003-Patch-microblaze-Initial-port-of-microblaze-core-rea.patch \
+ file://0004-Patch-microblaze-Communicate-in-larger-blocks-with-t.patch \
+ file://0005-Patch-microblaze-Add-mb-singlestepping.patch \
+ file://0006-Patch-microblaze-Add-initial-port-of-linux-gdbserver.patch \
+ file://0007-Patch-microblaze-Add-slr-and-shr-regs-and-little-end.patch \
+ file://0008-Patch-microblaze-Added-Backtrace-support-to-GDB.patch \
+ file://0009-Patch-microblaze-Initial-support-for-native-gdb.patch \
+ file://0010-Patch-gdb-Robustify-inline-function-support.patch \
+ file://0011-Patch-gdb-Fix-debug-message-when-register-is-unavail.patch \
+ file://0012-LOCAL-Disable-the-warning-message-for-eh_frame_hdr.patch \
+ file://0013-LOCAL-Fix-relaxation-of-assembler-resolved-reference.patch \
+ file://0014-LOCAL-Fixup-debug_loc-sections-after-linker-relaxati.patch \
+ file://0015-LOCAL-upstream-change-to-garbage-collection-sweep-ca.patch \
+ "
diff --git a/recipes-microblaze/gdb/gdb_7.7.1.bb b/recipes-microblaze/gdb/gdb_7.7.1.bb
new file mode 100644
index 00000000..80b589a1
--- /dev/null
+++ b/recipes-microblaze/gdb/gdb_7.7.1.bb
@@ -0,0 +1,29 @@
+require recipes-devtools/gdb/gdb-common.inc
+require gdb-${PV}.inc
+require gdb-microblaze-7.7.inc
+
+inherit gettext
+inherit python-dir
+
+PACKAGECONFIG ??= ""
+PACKAGECONFIG[python] = "--with-python=${WORKDIR}/python,--without-python,python"
+PACKAGECONFIG[babeltrace] = "--with-babeltrace,--without-babeltrace,babeltrace"
+
+do_configure_prepend() {
+ if [ -n "${@bb.utils.contains('PACKAGECONFIG', 'python', 'python', '', d)}" ]; then
+ cat > ${WORKDIR}/python << EOF
+#!/bin/sh
+case "\$2" in
+ --includes) echo "-I${STAGING_INCDIR}/${PYTHON_DIR}/" ;;
+ --ldflags) echo "-Wl,-rpath-link,${STAGING_LIBDIR}/.. -Wl,-rpath,${libdir}/.. -lpthread -ldl -lutil -lm -lpython${PYTHON_BASEVERSION}" ;;
+ --exec-prefix) echo "${exec_prefix}" ;;
+ *) exit 1 ;;
+esac
+exit 0
+EOF
+ chmod +x ${WORKDIR}/python
+ fi
+}
+
+PACKAGES =+ "gdbserver"
+FILES_gdbserver = "${bindir}/gdbserver"
diff --git a/recipes-microblaze/gnu-config/files/microblazeel.patch b/recipes-microblaze/gnu-config/files/microblazeel.patch
new file mode 100644
index 00000000..2b8249d5
--- /dev/null
+++ b/recipes-microblaze/gnu-config/files/microblazeel.patch
@@ -0,0 +1,68 @@
+From fb456b34ef4aa02b95dc6be69aaa66fa94a844fb Mon Sep 17 00:00:00 2001
+From: David Holsgrove <david.holsgrove@xilinx.com>
+Date: Wed, 10 Oct 2012 04:33:17 +0000
+Subject: * config.sub (microblazeel): New.
+
+ * testsuite/config-sub.data: Add a test case.
+
+Signed-off-by: Ben Elliston <bje@gnu.org>
+Upstream-Status: Backport [Not part of 2012-08-14]
+---
+diff --git a/config.sub b/config.sub
+index bdda9e4..826e4c6 100755
+--- a/config.sub
++++ b/config.sub
+@@ -156,7 +156,7 @@ case $os in
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+- -apple | -axis | -knuth | -cray | -microblaze)
++ -apple | -axis | -knuth | -cray | -microblaze*)
+ os=
+ basic_machine=$1
+ ;;
+@@ -273,7 +273,7 @@ case $basic_machine in
+ | le32 | le64 \
+ | lm32 \
+ | m32c | m32r | m32rle | m68000 | m68k | m88k \
+- | maxq | mb | microblaze | mcore | mep | metag \
++ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \
+ | mips | mipsbe | mipseb | mipsel | mipsle \
+ | mips16 \
+ | mips64 | mips64el \
+@@ -389,7 +389,8 @@ case $basic_machine in
+ | lm32-* \
+ | m32c-* | m32r-* | m32rle-* \
+ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+- | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \
++ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
++ | microblaze-* | microblazeel-* \
+ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+ | mips16-* \
+ | mips64-* | mips64el-* \
+@@ -788,7 +789,7 @@ case $basic_machine in
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+- microblaze)
++ microblaze*)
+ basic_machine=microblaze-xilinx
+ ;;
+ mingw64)
+diff --git a/testsuite/config-sub.data b/testsuite/config-sub.data
+index fafbca1..9bd2cd5 100644
+--- a/testsuite/config-sub.data
++++ b/testsuite/config-sub.data
+@@ -99,8 +99,11 @@ mep mep-unknown-elf
+ metag-linux metag-unknown-linux-gnu
+ metag metag-unknown-none
+ microblaze-elf microblaze-unknown-elf
++microblazeel-elf microblazeel-unknown-elf
+ microblaze-linux microblaze-unknown-linux-gnu
++microblazeel-linux microblazeel-unknown-linux-gnu
+ microblaze microblaze-unknown-none
++microblazeel microblazeel-unknown-none
+ mingw32ce arm-unknown-mingw32ce
+ mingw64 x86_64-pc-mingw64
+ mips64octeonel-elf mips64octeonel-unknown-elf
+---
diff --git a/recipes-microblaze/gnu-config/gnu-config_20120814.bbappend b/recipes-microblaze/gnu-config/gnu-config_20120814.bbappend
new file mode 100644
index 00000000..0a9331cb
--- /dev/null
+++ b/recipes-microblaze/gnu-config/gnu-config_20120814.bbappend
@@ -0,0 +1,6 @@
+
+FILESEXTRAPATHS_prepend := "${THISDIR}/files:"
+
+# Apply patch to add "microblazeel" support to gnu-config
+SRC_URI += "file://microblazeel.patch"
+
diff --git a/recipes-microblaze/qemu/qemu_%.bbappend b/recipes-microblaze/qemu/qemu_%.bbappend
new file mode 100644
index 00000000..4c37b1e0
--- /dev/null
+++ b/recipes-microblaze/qemu/qemu_%.bbappend
@@ -0,0 +1,2 @@
+QEMU_TARGETS += "microblazeel"
+
diff --git a/recipes-microblaze/shadow/shadow_%.bbappend b/recipes-microblaze/shadow/shadow_%.bbappend
new file mode 100644
index 00000000..19b20da8
--- /dev/null
+++ b/recipes-microblaze/shadow/shadow_%.bbappend
@@ -0,0 +1,14 @@
+#
+# MicroBlaze Yocto Built Toolchain fails to compile shadow
+# --------------------------------------------------------
+# There is an issue with the GCC 4.8 toolchain built by Yocto which fails to
+# correctly built the 'shadow' package due to an assembler error.
+#
+# {standard input}: Assembler messages:
+# {standard input}:754: Error: operation combines symbols in different segments
+#
+# The current workaround for this issue is to build the entire repository
+# without debug symbols, or to disable debug symbols only for shadow.
+#
+
+DEBUG_FLAGS_microblaze = ""