This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: [PATCH] PowerPC VLE changes
- From: Alexander Fedotov <alfedotov at gmail dot com>
- To: Alan Modra <amodra at gmail dot com>, binutils at sourceware dot org
- Cc: Edmar Wienskoski <edmarwjr at gmail dot com>
- Date: Fri, 23 Jun 2017 23:51:57 +0300
- Subject: Re: [PATCH] PowerPC VLE changes
- Authentication-results: sourceware.org; auth=none
Hello Alan
We want to upstream our changes for VLE, LSP, SPE2 and other stuff.
All of them are based on 2.28 release.
Best regards,
Alexander
diff -ruN binutils-2.28/bfd/elf32-ppc.c binutils-2.28-vle/bfd/elf32-ppc.c
--- binutils-2.28/bfd/elf32-ppc.c 2017-03-02 11:23:53.000000000 +0300
+++ binutils-2.28-vle/bfd/elf32-ppc.c 2017-06-23 22:01:57.953766000 +0300
@@ -171,6 +171,9 @@
#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 @@
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 @@
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 @@
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. */
@@ -2511,6 +2552,8 @@
{
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;
}
@@ -4247,6 +4290,7 @@
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:
@@ -4294,6 +4338,7 @@
break;
case R_PPC_PLTREL24:
+ case R_PPC_VLE_PLTREL24:
if (h == NULL)
break;
/* Fall through */
@@ -4365,6 +4410,7 @@
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:
@@ -4965,6 +5011,23 @@
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. */
@@ -6907,6 +6970,13 @@
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 */
@@ -6915,6 +6985,15 @@
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;
@@ -6955,6 +7034,7 @@
bfd_size_type trampbase, trampoff, newsize, picfixup_size;
asection *got2;
bfd_boolean maybe_pasted;
+ ppc_target_stub_entry_type target_stub_type = 0;
*again = FALSE;
@@ -7035,21 +7115,43 @@
struct elf_link_hash_entry *h;
struct plt_entry **plist;
unsigned char sym_type;
+ reloc_howto_type *current_howto;
+ current_howto = NULL;
switch (r_type)
{
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;
+ current_howto = ppc_elf_howto_table[r_type];
+ break;
+
+ case R_PPC_VLE_REL15:
+ target_stub_type = stub_entry_type_vle;
+ max_branch_offset = 1 << 16;
+ current_howto = ppc_elf_howto_table[r_type];
+ break;
+
+ case R_PPC_VLE_REL8:
+ target_stub_type = stub_entry_type_vle;
+ max_branch_offset = 1 << 9;
+ current_howto = ppc_elf_howto_table[r_type];
+ break;
+
case R_PPC_ADDR16_HA:
if (htab->params->pic_fixup > 0)
break;
@@ -7297,9 +7399,25 @@
symaddr = tsec->output_section->vma + tsec->output_offset + toff;
reladdr = isec->output_section->vma + isec->output_offset + roff;
- if (symaddr - reladdr + max_branch_offset
- < 2 * max_branch_offset)
- continue;
+
+ /* I don't trust the relocation check using ' ... < (2 * max_branch_offset)'
+ * Check for overflow using the bfd API first.
+ */
+ if (current_howto) /* current_howto is not necessarily defined for
+ all reloc types above, but use it if it is defined */
+ {
+ if (bfd_check_overflow (current_howto->complain_on_overflow,
+ current_howto->bitsize,
+ current_howto->rightshift,
+ bfd_arch_bits_per_address(abfd),
+ (symaddr-reladdr)) == bfd_reloc_ok )
+ continue;
+ }
+ else
+ {
+ if (((symaddr - reladdr) + max_branch_offset) < (2 * max_branch_offset))
+ continue;
+ }
}
/* Look for an existing fixup to this address. */
@@ -7328,7 +7446,7 @@
size = 4 * ARRAY_SIZE (stub_entry);
insn_offset = 0;
}
- stub_rtype = R_PPC_RELAX;
+ stub_rtype = (target_stub_type == stub_entry_type_vle) ? R_PPC_VLE_RELAX : R_PPC_RELAX;
if (tsec == htab->elf.splt
|| tsec == htab->glink)
{
@@ -7385,10 +7503,21 @@
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:
@@ -7399,6 +7528,27 @@
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;
}
}
@@ -9043,6 +9193,7 @@
/* Fall through. */
case R_PPC_RELAX:
+ case R_PPC_VLE_RELAX:
{
const int *stub;
size_t size;
@@ -9063,8 +9214,8 @@
}
else
{
- stub = stub_entry;
- size = ARRAY_SIZE (stub_entry);
+ stub = (r_type == R_PPC_VLE_RELAX) ? stub_entry_vle : stub_entry;
+ size = ARRAY_SIZE (stub_entry); /* stub_entry and stub_entry_vle must be same size */
}
relocation += addend;
@@ -9072,10 +9223,23 @@
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;
@@ -9482,6 +9646,10 @@
}
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:
@@ -9759,8 +9927,15 @@
&& (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);
}
@@ -10949,6 +11124,7 @@
#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 -ruN binutils-2.28/binutils/objdump.c binutils-2.28-vle/binutils/objdump.c
--- binutils-2.28/binutils/objdump.c 2017-03-02 11:23:53.000000000 +0300
+++ binutils-2.28-vle/binutils/objdump.c 2017-06-23 17:25:21.641299056 +0300
@@ -481,6 +481,10 @@
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_TIC54X_BLOCK, "VLE"); /* hack, would have to include ppc.h */
+ }
if (bfd_get_arch (abfd) == bfd_arch_tic54x)
{
PF (SEC_TIC54X_BLOCK, "BLOCK");
diff -ruN binutils-2.28/binutils/readelf.c binutils-2.28-vle/binutils/readelf.c
--- binutils-2.28/binutils/readelf.c 2017-03-02 11:23:53.000000000 +0300
+++ binutils-2.28-vle/binutils/readelf.c 2017-06-23 21:51:24.753324000 +0300
@@ -5491,7 +5491,9 @@
/* ARM specific. */
/* 21 */ { STRING_COMMA_LEN ("ENTRYSECT") },
/* 22 */ { STRING_COMMA_LEN ("ARM_PURECODE") },
- /* 23 */ { STRING_COMMA_LEN ("COMDEF") }
+ /* 23 */ { STRING_COMMA_LEN ("COMDEF") },
+ /* VLE specific. */
+ /* 24 */ { STRING_COMMA_LEN ("VLE") }
};
if (do_section_details)
@@ -5524,6 +5526,7 @@
case SHF_TLS: sindex = 9; break;
case SHF_EXCLUDE: sindex = 18; break;
case SHF_COMPRESSED: sindex = 20; break;
+ case SHF_PPC_VLE: sindex = 24; break;
default:
sindex = -1;
@@ -5617,6 +5620,7 @@
case SHF_TLS: *p = 'T'; break;
case SHF_EXCLUDE: *p = 'E'; break;
case SHF_COMPRESSED: *p = 'C'; break;
+ case SHF_PPC_VLE: *p = 'V'; break;
default:
if ((elf_header.e_machine == EM_X86_64
@@ -6333,6 +6337,8 @@
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 -ruN binutils-2.28/gas/config/obj-elf.c binutils-2.28-vle/gas/config/obj-elf.c
--- binutils-2.28/gas/config/obj-elf.c 2017-03-02 11:23:53.000000000 +0300
+++ binutils-2.28-vle/gas/config/obj-elf.c 2017-06-23 17:26:08.784859055 +0300
@@ -677,6 +677,11 @@
/* 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 -ruN binutils-2.28/gas/config/tc-ppc.c binutils-2.28-vle/gas/config/tc-ppc.c
--- binutils-2.28/gas/config/tc-ppc.c 2017-03-02 11:23:53.000000000 +0300
+++ binutils-2.28-vle/gas/config/tc-ppc.c 2017-06-23 17:48:51.463401055 +0300
@@ -1153,6 +1153,16 @@
}
}
+ 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;
@@ -3562,13 +3572,26 @@
}
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 -ruN binutils-2.28/gas/config/tc-ppc.h binutils-2.28-vle/gas/config/tc-ppc.h
--- binutils-2.28/gas/config/tc-ppc.h 2017-03-02 11:23:53.000000000 +0300
+++ binutils-2.28-vle/gas/config/tc-ppc.h 2017-06-23 17:28:07.396135056 +0300
@@ -226,6 +226,9 @@
#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 -ruN binutils-2.28/gas/doc/as.texinfo binutils-2.28-vle/gas/doc/as.texinfo
--- binutils-2.28/gas/doc/as.texinfo 2017-03-02 11:23:53.000000000 +0300
+++ binutils-2.28-vle/gas/doc/as.texinfo 2017-06-23 17:29:31.519652342 +0300
@@ -6495,6 +6495,8 @@
section is allocatable
@item e
section is excluded from executable and shared library.
+@item v
+section contains PowerPC VLE code (sets the SHF_PPC_VLE flag bit)
@item w
section is writable
@item x
diff -ruN binutils-2.28/include/elf/ppc.h binutils-2.28-vle/include/elf/ppc.h
--- binutils-2.28/include/elf/ppc.h 2017-03-02 11:23:54.000000000 +0300
+++ binutils-2.28-vle/include/elf/ppc.h 2017-06-23 17:34:20.838930833 +0300
@@ -79,8 +79,10 @@
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 @@
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)
@@ -198,6 +201,9 @@
/* Processor specific section headers, sh_flags field. */
#define SHF_PPC_VLE 0x10000000 /* PowerPC VLE text section. */
+/* BFD section headers flag. */
+#define SEC_PPC_VLE SEC_TIC54X_BLOCK
+
/* Processor specific section headers, sh_type field. */
#define SHT_ORDERED SHT_HIPROC /* Link editor is to sort the \
diff -ruN binutils-2.28/opcodes/ppc-dis.c binutils-2.28-vle/opcodes/ppc-dis.c
--- binutils-2.28/opcodes/ppc-dis.c 2017-03-02 11:23:54.000000000 +0300
+++ binutils-2.28-vle/opcodes/ppc-dis.c 2017-06-23 17:16:54.219715056 +0300
@@ -108,8 +108,8 @@
{ "e200z4", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE| PPC_OPCODE_SPE
| PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
| PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
- | PPC_OPCODE_E500 | PPC_OPCODE_E200Z4),
- PPC_OPCODE_VLE },
+ | PPC_OPCODE_E500 | PPC_OPCODE_E200Z4 | PPC_OPCODE_VLE),
+ 0 },
{ "e300", PPC_OPCODE_PPC | PPC_OPCODE_E300,
0 },
{ "e500", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE
@@ -235,12 +235,13 @@
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;
}