From daa4f8fad1f39691b6e3338b1acb24b388c8450d Mon Sep 17 00:00:00 2001
From: Alexander Fedotov-B55613 <b55613@freescale.com>
Date: Sat, 26 Aug 2017 20:29:23 +0300
Subject: [PATCH] Update VLE to handle PLT, new relocations and flags.

---
 bfd/ChangeLog                     |  21 +++++
 bfd/bfd-in2.h                     |   3 +
 bfd/elf32-ppc.c                   | 189 +++++++++++++++++++++++++++++++++++---
 bfd/section.c                     |   3 +
 binutils/ChangeLog                |   8 ++
 binutils/objdump.c                |   5 +
 binutils/readelf.c                |  11 +++
 gas/ChangeLog                     |  12 +++
 gas/config/obj-elf.c              |   5 +
 gas/config/tc-ppc.c               |  25 ++++-
 gas/config/tc-ppc.h               |   3 +
 gas/testsuite/gas/elf/section10.d |   2 +-
 gas/testsuite/gas/ppc/ppc.exp     |   2 -
 include/ChangeLog                 |   8 ++
 include/elf/ppc.h                 |   5 +-
 opcodes/ChangeLog                 |   5 +
 opcodes/ppc-dis.c                 |   7 +-
 17 files changed, 295 insertions(+), 19 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index e785d0e..c6f6415 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,24 @@
+2017-08-26  Alexander Fedotov <alexander.fedotov@nxp.com>
+	    Edmar Wienskoski <edmar.wienskoski@nxp.com
+
+	* bfd-in2.h (SEC_PPC_VLE): New macro.
+	* elf32-ppc.c (E_B): New macro.
+	(R_PPC_VLE_PLTREL24): New relocation.
+	(R_PPC_VLE_ADDR20): Likewise.
+	(ppc_elf_section_flags): New function.
+	(ppc_elf_fake_sections): Add SHF_PPC_VLE.
+	(ppc_elf_check_relocs): Hnadle R_PPC_VLE_ADDR20, R_PPC_VLE_PLTREL24
+	and R_PPC_VLE_ADDR20 relocations.
+	(ppc_elf_vle_split20): New function.
+	(ppc_target_stub_entry_type): New.
+	(stub_entry_vle): New stub.
+	(ppc_elf_relax_section): Handle stub_entry_vle
+	and new relocations.
+	(ppc_elf_relocate_section): Handle stub_entry_vle
+	and new relocations. Use E_B instruiction when VLE for trampolines.
+	(elf_backend_section_flags): New macro.
+	* section.c (SEC_PPC_VLE): New macro.
+
 2017-08-26  Alan Modra  <amodra@gmail.com>
 
 	* elf32-ppc.c (must_be_dyn_reloc): Use bfd_link_dll.  Comment.
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index d126aed..17fafa0 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -1467,6 +1467,9 @@ typedef struct bfd_section
   /* Indicate that section has the purecode flag set.  */
 #define SEC_ELF_PURECODE 0x80000000
 
+  /* PowerPC VLE code.  */
+#define SEC_PPC_VLE 0x100000000
+
   /*  End of section flags.  */
 
   /* Some internal packed boolean fields.  */
diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c
index a5d8193..e3c9b8b 100644
--- a/bfd/elf32-ppc.c
+++ b/bfd/elf32-ppc.c
@@ -171,6 +171,9 @@ static const bfd_vma ppc_elf_vxworks_pic_plt0_entry
 #define NOP		0x60000000
 #define SUB_11_11_12	0x7d6c5850
 
+/* VLE some instructions */
+#define E_B		0x78000000
+
 /* Offset of tp and dtp pointers from start of TLS block.  */
 #define TP_OFFSET	0x7000
 #define DTP_OFFSET	0x8000
@@ -1444,6 +1447,21 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
 	 0x1fffffe,		/* dst_mask */
 	 TRUE),			/* pcrel_offset */
 
+  /* A relative 24 bit branch.  */
+  HOWTO (R_PPC_VLE_PLTREL24,	/* type */
+	 1,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 24,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 1,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 ppc_elf_unhandled_reloc, /* special_function */
+	 "R_PPC_VLE_PLTREL24",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x1fffffe,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
   /* The 16 LSBS in split16a format.  */
   HOWTO (R_PPC_VLE_LO16A,	/* type */
 	 0,			/* rightshift */
@@ -1656,6 +1674,21 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
 	 0x3e007ff,		/* dst_mask */
 	 FALSE),		/* pcrel_offset */
 
+  /* e_li split20 format.  */
+  HOWTO (R_PPC_VLE_ADDR20,	/* type */
+	 16,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 20,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_PPC_VLE_ADDR20",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x1f07ff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
   HOWTO (R_PPC_IRELATIVE,	/* type */
 	 0,			/* rightshift */
 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
@@ -2463,6 +2496,14 @@ ppc_elf_lookup_section_flags (char *flag_name)
   return 0;
 }
 
+static bfd_boolean
+ppc_elf_section_flags (flagword *flags, const Elf_Internal_Shdr * hdr)
+{
+  if (hdr->sh_flags & SHF_PPC_VLE)
+    *flags |= SEC_PPC_VLE;
+  return TRUE;
+}
+
 /* Return address for Ith PLT stub in section PLT, for relocation REL
    or (bfd_vma) -1 if it should not be included.  */
 
@@ -2512,6 +2553,9 @@ ppc_elf_fake_sections (bfd *abfd ATTRIBUTE_UNUSED,
   if ((asect->flags & SEC_SORT_ENTRIES) != 0)
     shdr->sh_type = SHT_ORDERED;
 
+  if ((asect->flags & SEC_PPC_VLE) != 0)
+    shdr->sh_flags |= SHF_PPC_VLE;
+
   return TRUE;
 }
 
@@ -4265,6 +4309,7 @@ ppc_elf_check_relocs (bfd *abfd,
 	case R_PPC_VLE_HI16D:
 	case R_PPC_VLE_HA16A:
 	case R_PPC_VLE_HA16D:
+	case R_PPC_VLE_ADDR20:
 	  break;
 
 	case R_PPC_EMB_SDA2REL:
@@ -4312,6 +4357,7 @@ ppc_elf_check_relocs (bfd *abfd,
 	  break;
 
 	case R_PPC_PLTREL24:
+	case R_PPC_VLE_PLTREL24:
 	  if (h == NULL)
 	    break;
 	  /* Fall through */
@@ -4383,6 +4429,7 @@ ppc_elf_check_relocs (bfd *abfd,
 	case R_PPC_NONE:
 	case R_PPC_max:
 	case R_PPC_RELAX:
+	case R_PPC_VLE_RELAX:
 	case R_PPC_RELAX_PLT:
 	case R_PPC_RELAX_PLTREL24:
 	case R_PPC_16DX_HA:
@@ -4983,6 +5030,23 @@ ppc_elf_vle_split16 (bfd *input_bfd,
   insn |= value & 0x7ff;
   bfd_put_32 (input_bfd, insn, loc);
 }
+
+static void
+ppc_elf_vle_split20 (bfd *output_bfd, bfd_byte *loc, bfd_vma value)
+{
+  unsigned int insn;
+
+  insn = bfd_get_32 (output_bfd, loc);
+  /* We have an li20 field, bits 17..20, 11..15, 21..31.  */
+  /* Top 4 bits of value to 17..20.  */
+  insn |= (value & 0xf0000) >> 5;
+  /* Next 5 bits of the value to 11..15.  */
+  insn |= (value & 0xf800) << 5;
+  /* And the final 11 bits of the value to bits 21 to 31.  */
+  insn |= value & 0x7ff;
+  bfd_put_32 (output_bfd, insn, loc);
+}
+
 
 /* Choose which PLT scheme to use, and set .plt flags appropriately.
    Returns -1 on error, 0 for old PLT, 1 for new PLT.  */
@@ -6893,6 +6957,13 @@ static const int shared_stub_entry[] =
     0x4e800420, /* bctr */
   };
 
+typedef enum ppc_target_stub_entry_type
+  {
+    stub_entry_type_ppc = 0,
+    stub_entry_type_vle
+  }
+ppc_target_stub_entry_type;
+
 static const int stub_entry[] =
   {
     0x3d800000, /* lis 12,xxx@ha */
@@ -6901,6 +6972,15 @@ static const int stub_entry[] =
     0x4e800420, /* bctr */
   };
 
+/* Keep the same size as stub_entry */
+static const int stub_entry_vle[] =
+  {
+    0x7180e000, /* e_lis 12,xxx@ha */
+    0x1d8c0000, /* e_add16i 12,12,xxx@l */
+    0x7d8903a6, /* mtctr 12 */
+    0x00064400, /* se_bctr, se_nop (size padding) */
+  };
+
 struct ppc_elf_relax_info
 {
   unsigned int workaround_size;
@@ -6941,6 +7021,7 @@ ppc_elf_relax_section (bfd *abfd,
   bfd_size_type trampbase, trampoff, newsize, picfixup_size;
   asection *got2;
   bfd_boolean maybe_pasted;
+  ppc_target_stub_entry_type target_stub_type = stub_entry_type_ppc;
 
   *again = FALSE;
 
@@ -7027,15 +7108,32 @@ ppc_elf_relax_section (bfd *abfd,
 	    case R_PPC_REL24:
 	    case R_PPC_LOCAL24PC:
 	    case R_PPC_PLTREL24:
+	      target_stub_type = stub_entry_type_ppc;
 	      max_branch_offset = 1 << 25;
 	      break;
 
 	    case R_PPC_REL14:
 	    case R_PPC_REL14_BRTAKEN:
 	    case R_PPC_REL14_BRNTAKEN:
+	      target_stub_type = stub_entry_type_ppc;
 	      max_branch_offset = 1 << 15;
 	      break;
 
+	    case R_PPC_VLE_REL24:
+	      target_stub_type = stub_entry_type_vle;
+	      max_branch_offset = 1 << 25;
+	      break;
+
+	    case R_PPC_VLE_REL15:
+	      target_stub_type = stub_entry_type_vle;
+	      max_branch_offset = 1 << 16;
+	      break;
+
+	    case R_PPC_VLE_REL8:
+	      target_stub_type = stub_entry_type_vle;
+	      max_branch_offset = 1 << 9;
+	      break;
+
 	    case R_PPC_ADDR16_HA:
 	      if (htab->params->pic_fixup > 0)
 		break;
@@ -7314,7 +7412,12 @@ ppc_elf_relax_section (bfd *abfd,
 		  size = 4 * ARRAY_SIZE (stub_entry);
 		  insn_offset = 0;
 		}
-	      stub_rtype = R_PPC_RELAX;
+
+	      if (target_stub_type == stub_entry_type_ppc)
+		stub_rtype = R_PPC_RELAX;
+	      else
+		stub_rtype = R_PPC_VLE_RELAX;
+
 	      if (tsec == htab->elf.splt
 		  || tsec == htab->glink)
 		{
@@ -7371,10 +7474,21 @@ ppc_elf_relax_section (bfd *abfd,
 	    case R_PPC_REL24:
 	    case R_PPC_LOCAL24PC:
 	    case R_PPC_PLTREL24:
-	      t0 = bfd_get_32 (abfd, hit_addr);
-	      t0 &= ~0x3fffffc;
-	      t0 |= val & 0x3fffffc;
-	      bfd_put_32 (abfd, t0, hit_addr);
+	      if (r_type == R_PPC_PLTREL24
+		  && (elf_section_flags (isec) & SHF_PPC_VLE) != 0)
+		{
+		  t0 = bfd_get_32 (abfd, hit_addr);
+		  t0 &= ~0x01fffffe;
+		  t0 |= val & 0x01fffffe;
+		  bfd_put_32 (abfd, t0, hit_addr);
+		}
+	      else
+		{
+		  t0 = bfd_get_32 (abfd, hit_addr);
+		  t0 &= ~0x3fffffc;
+		  t0 |= val & 0x3fffffc;
+		  bfd_put_32 (abfd, t0, hit_addr);
+		}
 	      break;
 
 	    case R_PPC_REL14:
@@ -7385,6 +7499,27 @@ ppc_elf_relax_section (bfd *abfd,
 	      t0 |= val & 0xfffc;
 	      bfd_put_32 (abfd, t0, hit_addr);
 	      break;
+
+	    case R_PPC_VLE_REL24:
+	      t0 = bfd_get_32 (abfd, hit_addr);
+	      t0 &= ~0x01fffffe;
+	      t0 |= val & 0x01fffffe;
+	      bfd_put_32 (abfd, t0, hit_addr);
+	      break;
+
+	    case R_PPC_VLE_REL15:
+	      t0 = bfd_get_32 (abfd, hit_addr);
+	      t0 &= ~0xfffe;
+	      t0 |= val & 0xfffe;
+	      bfd_put_32 (abfd, t0, hit_addr);
+	      break;
+
+	    case R_PPC_VLE_REL8:
+	      t0 = bfd_get_32 (abfd, hit_addr);
+	      t0 &= ~0xff;
+	      t0 |= val & 0xff;
+	      bfd_put_32 (abfd, t0, hit_addr);
+	      break;
 	    }
 	}
 
@@ -9035,6 +9170,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
 	  /* Fall through.  */
 
 	case R_PPC_RELAX:
+	case R_PPC_VLE_RELAX:
 	  {
 	    const int *stub;
 	    size_t size;
@@ -9055,7 +9191,13 @@ ppc_elf_relocate_section (bfd *output_bfd,
 	      }
 	    else
 	      {
-		stub = stub_entry;
+		if (r_type == R_PPC_VLE_RELAX)
+		  stub = stub_entry_vle;
+		else
+		  stub = stub_entry;
+
+		BFD_ASSERT(ARRAY_SIZE (stub_entry_vle) == ARRAY_SIZE (stub_entry));
+
 		size = ARRAY_SIZE (stub_entry);
 	      }
 
@@ -9064,10 +9206,23 @@ ppc_elf_relocate_section (bfd *output_bfd,
 	      relocation = 0;
 
 	    /* First insn is HA, second is LO.  */
-	    insn = *stub++;
-	    insn |= ((relocation + 0x8000) >> 16) & 0xffff;
-	    bfd_put_32 (input_bfd, insn, contents + insn_offset);
-	    insn_offset += 4;
+	    if (r_type == R_PPC_VLE_RELAX)
+	      {
+		/* Write e_lis insn is @ha type relocation */
+		unsigned ha_val;
+		insn = *stub++;
+		ha_val = ((relocation + 0x8000) >> 16) & 0xffff;
+		insn |= (((ha_val & 0xf800) << 5) | (ha_val&0x7ff));
+		bfd_put_32 (input_bfd, insn, contents + insn_offset);
+		insn_offset += 4;
+	      }
+	    else
+	      {
+		insn = *stub++;
+		insn |= ((relocation + 0x8000) >> 16) & 0xffff;
+		bfd_put_32 (input_bfd, insn, contents + insn_offset);
+		insn_offset += 4;
+	      }
 
 	    insn = *stub++;
 	    insn |= relocation & 0xffff;
@@ -9474,6 +9629,10 @@ ppc_elf_relocate_section (bfd *output_bfd,
 	  }
 	  goto copy_reloc;
 
+	case R_PPC_VLE_ADDR20:
+	  ppc_elf_vle_split20 (output_bfd, contents + rel->r_offset, relocation);
+	  continue;
+
 	  /* Relocate against the beginning of the section.  */
 	case R_PPC_SECTOFF:
 	case R_PPC_SECTOFF_LO:
@@ -9751,8 +9910,15 @@ ppc_elf_relocate_section (bfd *output_bfd,
       && (strcmp (input_section->output_section->name, ".init") == 0
 	  || strcmp (input_section->output_section->name, ".fini") == 0))
     {
+      unsigned int insn;
+
+      if ((elf_section_flags (input_section) & SHF_PPC_VLE) == 0)
+	insn = B;
+      else
+	insn = E_B;
+
       /* Branch around the trampolines.  */
-      unsigned int insn = B + input_section->size - input_section->rawsize;
+      insn += input_section->size - input_section->rawsize;
       bfd_put_32 (input_bfd, insn, contents + input_section->rawsize);
     }
 
@@ -10959,6 +11125,7 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
 #define elf_backend_action_discarded		ppc_elf_action_discarded
 #define elf_backend_init_index_section		_bfd_elf_init_1_index_section
 #define elf_backend_lookup_section_flags_hook	ppc_elf_lookup_section_flags
+#define elf_backend_section_flags	       ppc_elf_section_flags
 
 #include "elf32-target.h"
 
diff --git a/bfd/section.c b/bfd/section.c
index 811d42a..54698f4 100644
--- a/bfd/section.c
+++ b/bfd/section.c
@@ -364,6 +364,9 @@ CODE_FRAGMENT
 .  {* Indicate that section has the purecode flag set.  *}
 .#define SEC_ELF_PURECODE 0x80000000
 .
+.  {* PowerPC VLE code.  *}
+.#define SEC_PPC_VLE 0x100000000
+.
 .  {*  End of section flags.  *}
 .
 .  {* Some internal packed boolean fields.  *}
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index 6d6aeee..57185c9 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,3 +1,11 @@
+2017-08-26  Alexander Fedotov <alexander.fedotov@nxp.com>
+	    Edmar Wienskoski <edmar.wienskoski@nxp.com
+
+	* objdump.c (dump_section_header): Add SEC_PPC_VLE.
+	* readelf.c (get_elf_section_flags): Add VLE.
+	Handle SEC_PPC_VLE flag.
+	(process_section_headers): Add VLE key to details.
+
 2017-08-25  Alan Modra  <amodra@gmail.com>
 
 	PR 21994
diff --git a/binutils/objdump.c b/binutils/objdump.c
index 3c5defa..8782648 100644
--- a/binutils/objdump.c
+++ b/binutils/objdump.c
@@ -485,6 +485,11 @@ dump_section_header (bfd *abfd, asection *section, void *data)
   PF (SEC_NEVER_LOAD, "NEVER_LOAD");
   PF (SEC_EXCLUDE, "EXCLUDE");
   PF (SEC_SORT_ENTRIES, "SORT_ENTRIES");
+  if (bfd_get_arch(abfd) == bfd_arch_powerpc
+      || bfd_get_arch (abfd) == bfd_mach_ppc_vle)
+    {
+      PF (SEC_PPC_VLE, "VLE");
+    }
   if (bfd_get_arch (abfd) == bfd_arch_tic54x)
     {
       PF (SEC_TIC54X_BLOCK, "BLOCK");
diff --git a/binutils/readelf.c b/binutils/readelf.c
index db3fc03..571da2c 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -5587,6 +5587,8 @@ get_elf_section_flags (bfd_vma sh_flags)
       /* 23 */ { STRING_COMMA_LEN ("COMDEF") },
       /* GNU specific.  */
       /* 24 */ { STRING_COMMA_LEN ("GNU_MBIND") },
+      /* VLE specific.  */
+      /* 25 */ { STRING_COMMA_LEN ("VLE") },
     };
 
   if (do_section_details)
@@ -5667,6 +5669,10 @@ get_elf_section_flags (bfd_vma sh_flags)
 		    default: break;
 		    }
 		  break;
+		case EM_PPC:
+		  if (flag == SHF_PPC_VLE)
+		    sindex = 25;
+		  break;
 
 		default:
 		  break;
@@ -5724,6 +5730,9 @@ get_elf_section_flags (bfd_vma sh_flags)
 	      else if (elf_header.e_machine == EM_ARM
 		       && flag == SHF_ARM_PURECODE)
 		  *p = 'y';
+	      else if (elf_header.e_machine == EM_PPC
+		       && flag == SHF_PPC_VLE)
+		  *p = 'v';
 	      else if (flag & SHF_MASKOS)
 		{
 		  *p = 'o';
@@ -6460,6 +6469,8 @@ process_section_headers (FILE * file)
 	printf (_("l (large), "));
       else if (elf_header.e_machine == EM_ARM)
 	printf (_("y (purecode), "));
+      else if (elf_header.e_machine == EM_PPC)
+	printf (_("v (VLE), "));
       printf ("p (processor specific)\n");
     }
 
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 8bea1df..19abfb9 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,15 @@
+2017-08-26  Alexander Fedotov <alexander.fedotov@nxp.com>
+	    Edmar Wienskoski <edmar.wienskoski@nxp.com
+
+	* config/obj-elf.c (obj_elf_change_section): Override if
+	section have SHF_PPC_VLE.
+	* config/tc-ppc.c (md_parse_option): Handle "mno-vle" flag.
+	(ppc_section_flags): Handle SHF_PPC_VLE attribute.
+	(ppc_elf_section_letter): New function.
+	* config/tc-ppc.h (md_elf_section_letter): New.
+	* testsuite/gas/elf/section10.d: XFAIL for VLE
+	* testsuite/gas/ppc/ppc.exp: Mark LSP test as pass.
+
 2017-08-23  Alexander Fedotov <alexander.fedotov@nxp.com>
 	    Edmar Wienskoski <edmar.wienskoski@nxp.com
 
diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c
index 49d99a4..e79103b 100644
--- a/gas/config/obj-elf.c
+++ b/gas/config/obj-elf.c
@@ -696,6 +696,11 @@ obj_elf_change_section (const char *name,
 	    /* RX init/fini arrays can and should have the "awx" attributes set.  */
 	    ;
 #endif
+#ifdef TC_PPC
+	  /* A section on powerpc-vle may have SHF_PPC_VLE.  */
+	  else if ((attr & ~ssect->attr) == SHF_PPC_VLE)
+	    override = TRUE;
+#endif
 	  else
 	    {
 	      if (group_name == NULL)
diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c
index d20fac6..6b9f6c4 100644
--- a/gas/config/tc-ppc.c
+++ b/gas/config/tc-ppc.c
@@ -1206,6 +1206,16 @@ md_parse_option (int c, const char *arg)
 	    }
 	}
 
+      else if (strcmp (arg, "no-vle") == 0)
+	{
+	  sticky &= ~PPC_OPCODE_VLE;
+
+	  new_cpu = ppc_parse_cpu (ppc_cpu, &sticky, "booke");
+	  new_cpu &= ~PPC_OPCODE_VLE;
+
+	  ppc_cpu = new_cpu;
+	}
+
       else if (strcmp (arg, "regnames") == 0)
 	reg_names_p = TRUE;
 
@@ -3676,13 +3686,26 @@ ppc_section_type (char *str, size_t len)
 }
 
 int
-ppc_section_flags (flagword flags, bfd_vma attr ATTRIBUTE_UNUSED, int type)
+ppc_section_flags (flagword flags, bfd_vma attr, int type)
 {
   if (type == SHT_ORDERED)
     flags |= SEC_ALLOC | SEC_LOAD | SEC_SORT_ENTRIES;
 
+  if (attr == SHF_PPC_VLE)
+    flags |= SEC_PPC_VLE;
+
   return flags;
 }
+
+bfd_vma
+ppc_elf_section_letter (int letter, const char **ptrmsg)
+{
+  if (letter == 'v')
+    return SHF_PPC_VLE;
+
+  *ptrmsg = _("bad .section directive: want a,e,v,w,x,M,S,G,T in string");
+  return -1;
+}
 #endif /* OBJ_ELF */
 
 
diff --git a/gas/config/tc-ppc.h b/gas/config/tc-ppc.h
index 514c223..f71f2ea 100644
--- a/gas/config/tc-ppc.h
+++ b/gas/config/tc-ppc.h
@@ -226,6 +226,9 @@ extern int ppc_section_flags (flagword, bfd_vma, int);
 #define tc_comment_chars ppc_comment_chars
 extern const char *ppc_comment_chars;
 
+#define md_elf_section_letter		ppc_elf_section_letter
+extern bfd_vma ppc_elf_section_letter (int, const char **);
+
 /* Keep relocations relative to the GOT, or non-PC relative.  */
 #define tc_fix_adjustable(FIX) ppc_fix_adjustable (FIX)
 extern int ppc_fix_adjustable (struct fix *);
diff --git a/gas/testsuite/gas/elf/section10.d b/gas/testsuite/gas/elf/section10.d
index e187263..dc7446f 100644
--- a/gas/testsuite/gas/elf/section10.d
+++ b/gas/testsuite/gas/elf/section10.d
@@ -1,7 +1,7 @@
 #readelf: -N --wide
 #name: numeric section flags and types
 # The RX port annoyingly reorders the sections so that they do not match the sequence expected below.
-#skip: rx-*-*
+#skip: rx-*-* powerpc*-*-*vle
 
 #...
 [ 	]*\[.*\][ 	]+.text
diff --git a/gas/testsuite/gas/ppc/ppc.exp b/gas/testsuite/gas/ppc/ppc.exp
index cdcd8a1..593c703 100644
--- a/gas/testsuite/gas/ppc/ppc.exp
+++ b/gas/testsuite/gas/ppc/ppc.exp
@@ -61,8 +61,6 @@ if { [istarget powerpc*-*-*] } then {
 	    run_dump_test "vle-simple-5"
 	    run_dump_test "vle-simple-6"
 
-	    #fail expected until get_powerpc_dialect() patch not applied
-	    setup_xfail "*-*-*"
 	    run_dump_test "lsp"
 	    run_dump_test "lsp-checks"
 	    run_dump_test "efs"
diff --git a/include/ChangeLog b/include/ChangeLog
index d914f71..32e2faa 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,11 @@
+2017-08-26  Alexander Fedotov <alexander.fedotov@nxp.com>
+	    Edmar Wienskoski <edmar.wienskoski@nxp.com
+
+	* elf/ppc.h (R_PPC_VLE_RELAX): New relocation.
+	(R_PPC_16DX_HA): Modify number.
+	(R_PPC_VLE_PLTREL24): New relocation.
+	(R_PPC_VLE_ADDR20): Likewise.
+
 2017-08-23  Alexander Fedotov <alexander.fedotov@nxp.com>
 	    Edmar Wienskoski <edmar.wienskoski@nxp.com>
 
diff --git a/include/elf/ppc.h b/include/elf/ppc.h
index 6790cd7..d3a77f9 100644
--- a/include/elf/ppc.h
+++ b/include/elf/ppc.h
@@ -79,8 +79,10 @@ START_RELOC_NUMBERS (elf_ppc_reloc_type)
   RELOC_NUMBER (R_PPC_RELAX,		 48)
   RELOC_NUMBER (R_PPC_RELAX_PLT,	 49)
   RELOC_NUMBER (R_PPC_RELAX_PLTREL24,	 50)
+  RELOC_NUMBER (R_PPC_VLE_RELAX,	 51)
 /* Reloc only used internally by gas.  As above, value is unimportant.  */
-  RELOC_NUMBER (R_PPC_16DX_HA,		 51)
+  RELOC_NUMBER (R_PPC_16DX_HA,		 52)
+  RELOC_NUMBER (R_PPC_VLE_PLTREL24,	 53)
 #endif
 
   /* Relocs added to support TLS.  */
@@ -152,6 +154,7 @@ START_RELOC_NUMBERS (elf_ppc_reloc_type)
   RELOC_NUMBER (R_PPC_VLE_SDAREL_HI16D,	230)
   RELOC_NUMBER (R_PPC_VLE_SDAREL_HA16A,	231)
   RELOC_NUMBER (R_PPC_VLE_SDAREL_HA16D,	232)
+  RELOC_NUMBER (R_PPC_VLE_ADDR20,	233)
 
 /* Power9 split rel16 for addpcis.  */
   RELOC_NUMBER (R_PPC_REL16DX_HA,	246)
diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog
index e252089..63e8068 100644
--- a/opcodes/ChangeLog
+++ b/opcodes/ChangeLog
@@ -1,3 +1,8 @@
+2017-08-26  Alexander Fedotov <alexander.fedotov@nxp.com>
+	    Edmar Wienskoski <edmar.wienskoski@nxp.com
+
+	* ppc-dis.c (get_powerpc_dialect): Modify for VLE.
+
 2017-08-23  Alexander Fedotov <alexander.fedotov@nxp.com>
 	    Edmar Wienskoski <edmar.wienskoski@nxp.com>
 
diff --git a/opcodes/ppc-dis.c b/opcodes/ppc-dis.c
index 0e2e185..7b95f0a 100644
--- a/opcodes/ppc-dis.c
+++ b/opcodes/ppc-dis.c
@@ -253,12 +253,13 @@ get_powerpc_dialect (struct disassemble_info *info)
   dialect = POWERPC_DIALECT (info);
 
   /* Disassemble according to the section headers flags for VLE-mode.  */
-  if (dialect & PPC_OPCODE_VLE
-      && info->section != NULL && info->section->owner != NULL
+  if (dialect & PPC_OPCODE_VLE)
+    return dialect;
+  else if (info->section != NULL && info->section->owner != NULL
       && bfd_get_flavour (info->section->owner) == bfd_target_elf_flavour
       && elf_object_id (info->section->owner) == PPC32_ELF_DATA
       && (elf_section_flags (info->section) & SHF_PPC_VLE) != 0)
-    return dialect;
+    return PPC_OPCODE_VLE;
   else
     return dialect & ~ PPC_OPCODE_VLE;
 }
-- 
2.7.4

