diff --git a/bfd/Makefile.am b/bfd/Makefile.am index b81b040142..7358cf1e69 100644 --- a/bfd/Makefile.am +++ b/bfd/Makefile.am @@ -306,6 +306,7 @@ BFD32_BACKENDS = \ elf32-dlx.lo \ elf32-e2k.lo \ elf32-e2k-pm.lo \ + elf32-e2k-pm-uclibc.lo \ elf32-epiphany.lo \ elf32-fr30.lo \ elf32-frv.lo \ @@ -359,6 +360,8 @@ BFD32_BACKENDS = \ elf32.lo \ elflink.lo \ elfxx-e2k.lo \ + elfxx-e2k-pm.lo \ + elfxx-e2k-uclibc.lo \ elfxx-sparc.lo \ elfxx-tilegx.lo \ i386aout.lo \ @@ -444,6 +447,7 @@ BFD32_BACKENDS_CFILES = \ elf32-dlx.c \ elf32-e2k.c \ elf32-e2k-pm.c \ + elf32-e2k-pm-uclibc.c \ elf32-epiphany.c \ elf32-fr30.c \ elf32-frv.c \ @@ -497,6 +501,8 @@ BFD32_BACKENDS_CFILES = \ elf32.c \ elflink.c \ elfxx-e2k.c \ + elfxx-e2k-pm.c \ + elfxx-e2k-uclibc.c \ elfxx-sparc.c \ elfxx-tilegx.c \ i386aout.c \ @@ -556,6 +562,9 @@ BFD64_BACKENDS = \ elf32-score7.lo \ elf64-alpha.lo \ elf64-e2k.lo \ + elf64-e2k-kpda.lo \ + elf64-e2k-pm.lo \ + elf64-e2k-uclibc.lo \ elf64-gen.lo \ elf64-hppa.lo \ elf64-ia64.lo \ @@ -598,6 +607,9 @@ BFD64_BACKENDS_CFILES = \ elf32-score7.c \ elf64-alpha.c \ elf64-e2k.c \ + elf64-e2k-kpda.c \ + elf64-e2k-pm.c \ + elf64-e2k-uclibc.c \ elf64-gen.c \ elf64-hppa.c \ elf64-ia64-vms.c \ @@ -956,7 +968,7 @@ DISTCLEANFILES = $(BUILD_CFILES) $(BUILD_HFILES) libtool-soversion bfdver.h: $(srcdir)/version.h $(srcdir)/development.sh $(srcdir)/Makefile.in @echo "creating $@" @bfd_version=`echo "$(VERSION)" | $(SED) -e 's/\([^\.]*\)\.*\([^\.]*\)\.*\([^\.]*\)\.*\([^\.]*\)\.*\([^\.]*\).*/\1.00\2.00\3.00\4.00\5/' -e 's/\([^\.]*\)\..*\(..\)\..*\(..\)\..*\(..\)\..*\(..\)$$/\1\2\3\4\5/'` ;\ - bfd_version_string="\"$(VERSION)-23.008\"" ;\ + bfd_version_string="\"$(VERSION)-25.014\"" ;\ bfd_soversion="$(VERSION)" ;\ bfd_version_package="\"$(PKGVERSION)\"" ;\ report_bugs_to="\"$(REPORT_BUGS_TO)\"" ;\ diff --git a/bfd/Makefile.in b/bfd/Makefile.in index d0d14c6ab3..bb85d213f4 100644 --- a/bfd/Makefile.in +++ b/bfd/Makefile.in @@ -186,7 +186,7 @@ am__objects_1 = archive.lo archures.lo bfd.lo bfdio.lo bfdwin.lo \ format.lo hash.lo init.lo libbfd.lo linker.lo merge.lo \ opncls.lo reloc.lo section.lo simple.lo stab-syms.lo stabs.lo \ syms.lo targets.lo binary.lo ihex.lo srec.lo tekhex.lo \ - verilog.lo + verilog.lo eir.lo am_libbfd_la_OBJECTS = $(am__objects_1) libbfd_la_OBJECTS = $(am_libbfd_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) @@ -499,7 +499,7 @@ BFD32_LIBS = \ coff-bfd.lo compress.lo corefile.lo elf-properties.lo format.lo \ hash.lo init.lo libbfd.lo linker.lo merge.lo opncls.lo reloc.lo \ section.lo simple.lo stab-syms.lo stabs.lo syms.lo targets.lo \ - binary.lo ihex.lo srec.lo tekhex.lo verilog.lo + binary.lo ihex.lo srec.lo tekhex.lo verilog.lo eir.lo BFD64_LIBS = archive64.lo BFD32_LIBS_CFILES = \ @@ -507,7 +507,7 @@ BFD32_LIBS_CFILES = \ compress.c corefile.c elf-properties.c format.c hash.c \ init.c libbfd.c linker.c merge.c opncls.c reloc.c \ section.c simple.c stab-syms.c stabs.c syms.c targets.c \ - binary.c ihex.c srec.c tekhex.c verilog.c + binary.c ihex.c srec.c tekhex.c verilog.c eir.c BFD64_LIBS_CFILES = archive64.c @@ -528,6 +528,7 @@ ALL_MACHINES = \ cpu-d10v.lo \ cpu-d30v.lo \ cpu-dlx.lo \ + cpu-e2k.lo \ cpu-epiphany.lo \ cpu-fr30.lo \ cpu-frv.lo \ @@ -612,6 +613,7 @@ ALL_MACHINES_CFILES = \ cpu-d10v.c \ cpu-d30v.c \ cpu-dlx.c \ + cpu-e2k.c \ cpu-epiphany.c \ cpu-fr30.c \ cpu-frv.c \ @@ -727,6 +729,9 @@ BFD32_BACKENDS = \ elf32-d10v.lo \ elf32-d30v.lo \ elf32-dlx.lo \ + elf32-e2k.lo \ + elf32-e2k-pm.lo \ + elf32-e2k-pm-uclibc.lo \ elf32-epiphany.lo \ elf32-fr30.lo \ elf32-frv.lo \ @@ -779,6 +784,9 @@ BFD32_BACKENDS = \ elf32-z80.lo \ elf32.lo \ elflink.lo \ + elfxx-e2k.lo \ + elfxx-e2k-pm.lo \ + elfxx-e2k-uclibc.lo \ elfxx-sparc.lo \ elfxx-tilegx.lo \ i386aout.lo \ @@ -862,6 +870,9 @@ BFD32_BACKENDS_CFILES = \ elf32-d10v.c \ elf32-d30v.c \ elf32-dlx.c \ + elf32-e2k.c \ + elf32-e2k-pm.c \ + elf32-e2k-pm-uclibc.c \ elf32-epiphany.c \ elf32-fr30.c \ elf32-frv.c \ @@ -914,6 +925,9 @@ BFD32_BACKENDS_CFILES = \ elf32-z80.c \ elf32.c \ elflink.c \ + elfxx-e2k.c \ + elfxx-e2k-pm.c \ + elfxx-e2k-uclibc.c \ elfxx-sparc.c \ elfxx-tilegx.c \ i386aout.c \ @@ -973,6 +987,10 @@ BFD64_BACKENDS = \ elf32-score.lo \ elf32-score7.lo \ elf64-alpha.lo \ + elf64-e2k.lo \ + elf64-e2k-kpda.lo \ + elf64-e2k-pm.lo \ + elf64-e2k-uclibc.lo \ elf64-gen.lo \ elf64-hppa.lo \ elf64-ia64.lo \ @@ -1014,6 +1032,10 @@ BFD64_BACKENDS_CFILES = \ elf32-score.c \ elf32-score7.c \ elf64-alpha.c \ + elf64-e2k.c \ + elf64-e2k-kpda.c \ + elf64-e2k-pm.c \ + elf64-e2k-uclibc.c \ elf64-gen.c \ elf64-hppa.c \ elf64-ia64-vms.c \ @@ -1338,6 +1360,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-d10v.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-d30v.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-dlx.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-e2k.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-epiphany.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-fr30.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-frv.Plo@am__quote@ @@ -1410,6 +1433,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf2.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ecoff.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ecofflink.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eir.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf-attrs.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf-eh-frame.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf-ifunc.Plo@am__quote@ @@ -1433,6 +1457,9 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-d10v.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-d30v.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-dlx.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-e2k-pm-uclibc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-e2k-pm.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-e2k.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-epiphany.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-fr30.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-frv.Plo@am__quote@ @@ -1491,6 +1518,10 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-aarch64.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-alpha.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-bpf.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-e2k-kpda.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-e2k-pm.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-e2k-uclibc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-e2k.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-gen.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-hppa.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-ia64-vms.Plo@am__quote@ @@ -1508,6 +1539,9 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elflink.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfn32-mips.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-aarch64.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-e2k-pm.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-e2k-uclibc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-e2k.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-ia64.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-mips.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-riscv.Plo@am__quote@ @@ -2058,7 +2092,7 @@ stmp-lcoff-h: $(LIBCOFF_H_FILES) bfdver.h: $(srcdir)/version.h $(srcdir)/development.sh $(srcdir)/Makefile.in @echo "creating $@" @bfd_version=`echo "$(VERSION)" | $(SED) -e 's/\([^\.]*\)\.*\([^\.]*\)\.*\([^\.]*\)\.*\([^\.]*\)\.*\([^\.]*\).*/\1.00\2.00\3.00\4.00\5/' -e 's/\([^\.]*\)\..*\(..\)\..*\(..\)\..*\(..\)\..*\(..\)$$/\1\2\3\4\5/'` ;\ - bfd_version_string="\"$(VERSION)\"" ;\ + bfd_version_string="\"$(VERSION)-25.014\"" ;\ bfd_soversion="$(VERSION)" ;\ bfd_version_package="\"$(PKGVERSION)\"" ;\ report_bugs_to="\"$(REPORT_BUGS_TO)\"" ;\ diff --git a/bfd/archures.c b/bfd/archures.c index 551ec8732f..defbcc78d6 100644 --- a/bfd/archures.c +++ b/bfd/archures.c @@ -131,9 +131,15 @@ DESCRIPTION .#define bfd_mach_sparc_v9m 20 {* with OSA2015 and M7 add'ns. *} .#define bfd_mach_sparc_v8plusm8 21 {* with OSA2017 and M8 add'ns. *} .#define bfd_mach_sparc_v9m8 22 {* with OSA2017 and M8 add'ns. *} +.#define bfd_mach_sparc_v8plus_r1000 23 {* with r1000 add'ns. *} +.#define bfd_mach_sparc_v9_r1000 24 {* with r1000 add'ns. *} +.#define bfd_mach_sparc_v8plus_r2000 25 {* with r2000 add'ns. *} +.#define bfd_mach_sparc_v9_r2000 26 {* with r2000 add'ns. *} +.#define bfd_mach_sparc_v8plus_r2000_plus 27 {* with r2000+ add'ns. *} +.#define bfd_mach_sparc_v9_r2000_plus 28 {* with r2000+ add'ns. *} .{* Nonzero if MACH has the v9 instruction set. *} .#define bfd_mach_sparc_v9_p(mach) \ -. ((mach) >= bfd_mach_sparc_v8plus && (mach) <= bfd_mach_sparc_v9m8 \ +. ((mach) >= bfd_mach_sparc_v8plus && (mach) <= bfd_mach_sparc_v9_mcst \ . && (mach) != bfd_mach_sparc_sparclite_le) .{* Nonzero if MACH is a 64 bit sparc architecture. *} .#define bfd_mach_sparc_64bit_p(mach) \ @@ -144,7 +150,10 @@ DESCRIPTION . && (mach) != bfd_mach_sparc_v8pluse \ . && (mach) != bfd_mach_sparc_v8plusv \ . && (mach) != bfd_mach_sparc_v8plusm \ -. && (mach) != bfd_mach_sparc_v8plusm8) +. && (mach) != bfd_mach_sparc_v8plusm8 \ +. && (mach) != bfd_mach_sparc_v8plus_r1000 \ +. && (mach) != bfd_mach_sparc_v8plus_r2000 \ +. && (mach) != bfd_mach_sparc_v8plus_r2000_plus) . bfd_arch_spu, {* PowerPC SPU. *} .#define bfd_mach_spu 256 . bfd_arch_mips, {* MIPS Rxxxx. *} @@ -522,6 +531,27 @@ DESCRIPTION . bfd_arch_lm32, {* Lattice Mico32. *} .#define bfd_mach_lm32 1 . bfd_arch_microblaze,{* Xilinx MicroBlaze. *} +. bfd_arch_e2k, {* MCST E2K. *} +.{* It's crucial that the underlying `bfd_mach_e2k*' have the same values as *} +.{* the corresponding `E_E2K_MACH_*'s!!! *} +.#define bfd_mach_e2k_generic 0 +.#define bfd_mach_e2k_ev1 1 +.{* This is interpreted as the common subset of all Elbrus V2 iterations. +. Currently it is the same as the common subset of all elbrus-2c+. *} +.#define bfd_mach_e2k_ev2 2 +.#define bfd_mach_e2k_ev3 3 +.#define bfd_mach_e2k_ev4 4 +.#define bfd_mach_e2k_ev5 5 +.#define bfd_mach_e2k_ev6 6 +.{* Values 16, 17 and 18 used to be reserved for the first three iterations +. of `elbrus-v2'. See `include/elf/e2k.h' for why they can't be reused right +. now. *} +.#define bfd_mach_e2k_8c 19 +.#define bfd_mach_e2k_1cplus 20 +.#define bfd_mach_e2k_12c 21 +.#define bfd_mach_e2k_16c 22 +.#define bfd_mach_e2k_2c3 23 + . bfd_arch_tilepro, {* Tilera TILEPro. *} . bfd_arch_tilegx, {* Tilera TILE-Gx. *} .#define bfd_mach_tilepro 1 @@ -620,6 +650,7 @@ extern const bfd_arch_info_type bfd_d10v_arch; extern const bfd_arch_info_type bfd_d30v_arch; extern const bfd_arch_info_type bfd_dlx_arch; extern const bfd_arch_info_type bfd_bpf_arch; +extern const bfd_arch_info_type bfd_e2k_arch; extern const bfd_arch_info_type bfd_epiphany_arch; extern const bfd_arch_info_type bfd_fr30_arch; extern const bfd_arch_info_type bfd_frv_arch; @@ -709,6 +740,7 @@ static const bfd_arch_info_type * const bfd_archures_list[] = &bfd_d30v_arch, &bfd_dlx_arch, &bfd_bpf_arch, + &bfd_e2k_arch, &bfd_epiphany_arch, &bfd_fr30_arch, &bfd_frv_arch, diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 35ef4d755b..0f1039dc9f 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -1531,9 +1531,15 @@ enum bfd_architecture #define bfd_mach_sparc_v9m 20 /* with OSA2015 and M7 add'ns. */ #define bfd_mach_sparc_v8plusm8 21 /* with OSA2017 and M8 add'ns. */ #define bfd_mach_sparc_v9m8 22 /* with OSA2017 and M8 add'ns. */ +#define bfd_mach_sparc_v8plus_r1000 23 /* with r1000 add'ns. */ +#define bfd_mach_sparc_v9_r1000 24 /* with r1000 add'ns. */ +#define bfd_mach_sparc_v8plus_r2000 25 /* with r2000 add'ns. */ +#define bfd_mach_sparc_v9_r2000 26 /* with r2000 add'ns. */ +#define bfd_mach_sparc_v8plus_r2000_plus 27 /* with r2000+ add'ns. */ +#define bfd_mach_sparc_v9_r2000_plus 28 /* with r2000+ add'ns. */ /* Nonzero if MACH has the v9 instruction set. */ #define bfd_mach_sparc_v9_p(mach) \ - ((mach) >= bfd_mach_sparc_v8plus && (mach) <= bfd_mach_sparc_v9m8 \ + ((mach) >= bfd_mach_sparc_v8plus && (mach) <= bfd_mach_sparc_v9_mcst \ && (mach) != bfd_mach_sparc_sparclite_le) /* Nonzero if MACH is a 64 bit sparc architecture. */ #define bfd_mach_sparc_64bit_p(mach) \ @@ -1544,7 +1550,10 @@ enum bfd_architecture && (mach) != bfd_mach_sparc_v8pluse \ && (mach) != bfd_mach_sparc_v8plusv \ && (mach) != bfd_mach_sparc_v8plusm \ - && (mach) != bfd_mach_sparc_v8plusm8) + && (mach) != bfd_mach_sparc_v8plusm8 \ + && (mach) != bfd_mach_sparc_v8plus_r1000 \ + && (mach) != bfd_mach_sparc_v8plus_r2000 \ + && (mach) != bfd_mach_sparc_v8plus_r2000_plus) bfd_arch_spu, /* PowerPC SPU. */ #define bfd_mach_spu 256 bfd_arch_mips, /* MIPS Rxxxx. */ @@ -1922,6 +1931,26 @@ enum bfd_architecture bfd_arch_lm32, /* Lattice Mico32. */ #define bfd_mach_lm32 1 bfd_arch_microblaze,/* Xilinx MicroBlaze. */ + bfd_arch_e2k, /* MCST E2K. */ +/* It's crucial that the underlying `bfd_mach_e2k*' have the same values as */ +/* the corresponding `E_E2K_MACH_*'s!!! */ +#define bfd_mach_e2k_generic 0 +#define bfd_mach_e2k_ev1 1 +/* This is interpreted as the common subset of all Elbrus V2 iterations. + Currently it is the same as the common subset of all elbrus-2c+. */ +#define bfd_mach_e2k_ev2 2 +#define bfd_mach_e2k_ev3 3 +#define bfd_mach_e2k_ev4 4 +#define bfd_mach_e2k_ev5 5 +#define bfd_mach_e2k_ev6 6 +/* Values 16, 17 and 18 used to be reserved for the first three iterations + of `elbrus-v2'. See `include/elf/e2k.h' for why they can't be reused right + now. */ +#define bfd_mach_e2k_8c 19 +#define bfd_mach_e2k_1cplus 20 +#define bfd_mach_e2k_12c 21 +#define bfd_mach_e2k_16c 22 +#define bfd_mach_e2k_2c3 23 bfd_arch_tilepro, /* Tilera TILEPro. */ bfd_arch_tilegx, /* Tilera TILE-Gx. */ #define bfd_mach_tilepro 1 @@ -6268,6 +6297,89 @@ assembler and not (currently) written to any object files. */ /* S12Z relocations. */ BFD_RELOC_S12Z_OPR, + +/* This one corresponds to R_E2K_64_ABS_LIT. */ + BFD_RELOC_E2K_64_ABS_LIT, + +/* This one corresponds to R_E2K_DISP. */ + BFD_RELOC_E2K_DISP, + +/* This one corresponds to R_E2K_GOT. */ + BFD_RELOC_E2K_GOT, + +/* This one corresponds to R_E2K_TLS_GDMOD. */ + BFD_RELOC_E2K_TLS_GDMOD, + +/* This one corresponds to R_E2K_TLS_GDREL. */ + BFD_RELOC_E2K_TLS_GDREL, + +/* This one corresponds to R_E2K_TLS_IE. */ + BFD_RELOC_E2K_TLS_IE, + +/* This one corresponds to R_E2K_32_TLS_LE. */ + BFD_RELOC_E2K_32_TLS_LE, + +/* This one corresponds to R_E2K_64_TLS_LE. */ + BFD_RELOC_E2K_64_TLS_LE, + +/* This one corresponds to R_E2K_TLS_32_DTPREL. */ + BFD_RELOC_E2K_32_DTPREL, + +/* This one corresponds to R_E2K_TLS_64_DTPREL. */ + BFD_RELOC_E2K_64_DTPREL, + +/* This one corresponds to R_E2K_PLT. */ + BFD_RELOC_E2K_PLT, + +/* This one corresponds to R_E2K_GOTPLT. */ + BFD_RELOC_E2K_GOTPLT, + +/* This one corresponds to R_E2K_ISLOCAL. */ + BFD_RELOC_E2K_ISLOCAL, + +/* This one corresponds to R_E2K_AP_GOT. */ + BFD_RELOC_E2K_AP_GOT, + +/* This one corresponds to R_E2K_PL_GOT. */ + BFD_RELOC_E2K_PL_GOT, + +/* This one corresponds to R_E2K_PREF. */ + BFD_RELOC_E2K_PREF, + +/* This one corresponds to R_E2K_ISLOCAL32. */ + BFD_RELOC_E2K_ISLOCAL32, + +/* This one corresponds to R_E2K_GOTOFF64. */ + BFD_RELOC_E2K_GOTOFF64, + +/* This one corresponds to R_E2K_GOTOFF64_LIT. */ + BFD_RELOC_E2K_GOTOFF64_LIT, + +/* This one corresponds to R_E2K_AP. */ + BFD_RELOC_E2K_AP, + +/* This one corresponds to R_E2K_PL. */ + BFD_RELOC_E2K_PL, + +/* This one corresponds to R_E2K_32_DYNOPT. */ + BFD_RELOC_E2K_DYNOPT32, + +/* This one corresponds to R_E2K_64_DYNOPT. */ + BFD_RELOC_E2K_DYNOPT64, + +/* Elvees Elcore relocations. */ + BFD_RELOC_ELCORE32, + BFD_RELOC_ELCORE16NPC, + BFD_RELOC_ELCORE16PC, + BFD_RELOC_ELCORE16S, + BFD_RELOC_ELCORE16, + BFD_RELOC_ELCORE5, + BFD_RELOC_ELCORE32_FAKE, + BFD_RELOC_ELCORE16NPC_FAKE, + BFD_RELOC_ELCORE16PC_FAKE, + BFD_RELOC_ELCORE16S_FAKE, + BFD_RELOC_ELCORE16_FAKE, + BFD_RELOC_ELCORE5_FAKE, BFD_RELOC_UNUSED }; typedef enum bfd_reloc_code_real bfd_reloc_code_real_type; diff --git a/bfd/config.bfd b/bfd/config.bfd index 14523caf0c..66fc0a5b3d 100644 --- a/bfd/config.bfd +++ b/bfd/config.bfd @@ -176,6 +176,7 @@ crisv32) targ_archs=bfd_cris_arch ;; crx*) targ_archs=bfd_crx_arch ;; csky*) targ_archs=bfd_csky_arch ;; dlx*) targ_archs=bfd_dlx_arch ;; +e2k*) targ_archs=bfd_e2k_arch ;; fido*) targ_archs=bfd_m68k_arch ;; hppa*) targ_archs=bfd_hppa_arch ;; i[3-7]86) targ_archs=bfd_i386_arch ;; @@ -475,6 +476,24 @@ case "${targ}" in ;; #endif + e2k-*-linux-gnu) + targ_defvec=e2k_elf64_vec + targ_selvecs="e2k_elf32_vec e2k_pm_elf32_vec" + targ64_selvecs="e2k_pm_elf64_vec" + want64=true + ;; + + e2k-*-linux-uclibc) + targ_defvec=e2k_uclibc_elf64_vec + targ_selvecs="e2k_pm_uclibc_elf32_vec" + want64=true + ;; + + e2k-*-kpda) + targ_defvec=e2k_kpda_elf64_vec + want64=true + ;; + epiphany-*-*) targ_defvec=epiphany_elf32_vec targ_underscore=yes diff --git a/bfd/config.in b/bfd/config.in index be572969fc..1693fe67a7 100644 --- a/bfd/config.in +++ b/bfd/config.in @@ -302,6 +302,9 @@ */ #undef LT_OBJDIR +/* Define if we should enable new PM ABI */ +#undef NEW_PM_ABI + /* Name of package */ #undef PACKAGE diff --git a/bfd/configure b/bfd/configure index 0340ed541b..edfa598673 100755 --- a/bfd/configure +++ b/bfd/configure @@ -830,6 +830,7 @@ enable_targets enable_64_bit_archive with_mmap enable_secureplt +enable_new_pm_abi enable_separate_code enable_leading_mingw64_underscores with_separate_debug_dir @@ -1487,6 +1488,7 @@ Optional Features: --enable-targets alternative target configurations --enable-64-bit-archive force 64-bit archives --enable-secureplt Default to creating read-only plt entries + --enable-new-pm-abi Enable new PM ABI on E2K --enable-separate-code enable -z separate-code in ELF linker by default --enable-leading-mingw64-underscores Enable leading underscores on 64 bit mingw targets @@ -11728,7 +11730,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11731 "configure" +#line 11733 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -11834,7 +11836,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11837 "configure" +#line 11839 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -12493,6 +12495,22 @@ $as_echo "#define USE_SECUREPLT 1" >>confdefs.h fi +# Check whether --enable-new-pm-abi was given. +if test "${enable_new_pm_abi+set}" = set; then : + enableval=$enable_new_pm_abi; case "${enableval}" in + yes) new_pm_abi=true ;; + no) new_pm_abi=false ;; + *) as_fn_error $? "bad value ${enableval} for new-pm-abi option" "$LINENO" 5 ;; +esac +else + new_pm_abi=false +fi +if test $new_pm_abi = true; then + +$as_echo "#define NEW_PM_ABI 1" >>confdefs.h + +fi + # Decide if -z separate-code should be enabled in ELF linker by default. ac_default_ld_z_separate_code=unset # Check whether --enable-separate-code was given. @@ -14755,6 +14773,13 @@ do d10v_elf32_vec) tb="$tb elf32-d10v.lo elf32.lo $elf" ;; d30v_elf32_vec) tb="$tb elf32-d30v.lo elf32.lo $elf" ;; dlx_elf32_be_vec) tb="$tb elf32-dlx.lo elf32.lo $elf" ;; + e2k_elf32_vec) tb="$tb elf32-e2k.lo elfxx-e2k.lo elf-ifunc.lo $elf"; want64=true;; + e2k_pm_elf32_vec) tb="$tb elf32-e2k-pm.lo elfxx-e2k-pm.lo elfxx-e2k.lo elf-ifunc.lo $elf";; + e2k_pm_uclibc_elf32_vec) tb="$tb elf32-e2k-pm-uclibc.lo elfxx-e2k-pm.lo elfxx-e2k-uclibc.lo elfxx-e2k.lo elf-ifunc.lo $elf";; + e2k_elf64_vec) tb="$tb elf64-e2k.lo elfxx-e2k.lo elf-ifunc.lo $elf"; target_size=64;; + e2k_kpda_elf64_vec) tb="$tb elf64-e2k-kpda.lo elfxx-e2k.lo elf-ifunc.lo $elf"; target_size=64;; + e2k_pm_elf64_vec) tb="$tb elf64-e2k-pm.lo elfxx-e2k-pm.lo elfxx-e2k.lo elf-ifunc.lo $elf";; + e2k_uclibc_elf64_vec) tb="$tb elf64-e2k-uclibc.lo elfxx-e2k-uclibc.lo elfxx-e2k.lo elf-ifunc.lo $elf";; elf32_be_vec) tb="$tb elf32-gen.lo elf32.lo $elf" ;; elf32_le_vec) tb="$tb elf32-gen.lo elf32.lo $elf" ;; elf64_be_vec) tb="$tb elf64-gen.lo elf64.lo $elf"; target_size=64 ;; diff --git a/bfd/configure.ac b/bfd/configure.ac index 8e86f8399c..2a45c09a7b 100644 --- a/bfd/configure.ac +++ b/bfd/configure.ac @@ -116,6 +116,18 @@ if test $use_secureplt = true; then [Define if we should default to creating read-only plt entries]) fi +AC_ARG_ENABLE(new-pm-abi, +[ --enable-new-pm-abi Enable new PM ABI on E2K], +[case "${enableval}" in + yes) new_pm_abi=true ;; + no) new_pm_abi=false ;; + *) AC_MSG_ERROR(bad value ${enableval} for new-pm-abi option) ;; +esac],[new_pm_abi=false])dnl +if test $new_pm_abi = true; then + AC_DEFINE(NEW_PM_ABI, 1, + [Define if we should enable new PM ABI]) +fi + # Decide if -z separate-code should be enabled in ELF linker by default. ac_default_ld_z_separate_code=unset AC_ARG_ENABLE(separate-code, @@ -491,6 +503,13 @@ do d10v_elf32_vec) tb="$tb elf32-d10v.lo elf32.lo $elf" ;; d30v_elf32_vec) tb="$tb elf32-d30v.lo elf32.lo $elf" ;; dlx_elf32_be_vec) tb="$tb elf32-dlx.lo elf32.lo $elf" ;; + e2k_elf32_vec) tb="$tb elf32-e2k.lo elfxx-e2k.lo elf-ifunc.lo $elf"; want64=true;; + e2k_pm_elf32_vec) tb="$tb elf32-e2k-pm.lo elfxx-e2k-pm.lo elfxx-e2k.lo elf-ifunc.lo $elf";; + e2k_pm_uclibc_elf32_vec) tb="$tb elf32-e2k-pm-uclibc.lo elfxx-e2k-pm.lo elfxx-e2k-uclibc.lo elfxx-e2k.lo elf-ifunc.lo $elf";; + e2k_elf64_vec) tb="$tb elf64-e2k.lo elfxx-e2k.lo elf-ifunc.lo $elf"; target_size=64;; + e2k_kpda_elf64_vec) tb="$tb elf64-e2k-kpda.lo elfxx-e2k.lo elf-ifunc.lo $elf"; target_size=64;; + e2k_pm_elf64_vec) tb="$tb elf64-e2k-pm.lo elfxx-e2k-pm.lo elfxx-e2k.lo elf-ifunc.lo $elf";; + e2k_uclibc_elf64_vec) tb="$tb elf64-e2k-uclibc.lo elfxx-e2k-uclibc.lo elfxx-e2k.lo elf-ifunc.lo $elf";; elf32_be_vec) tb="$tb elf32-gen.lo elf32.lo $elf" ;; elf32_le_vec) tb="$tb elf32-gen.lo elf32.lo $elf" ;; elf64_be_vec) tb="$tb elf64-gen.lo elf64.lo $elf"; target_size=64 ;; diff --git a/bfd/cpu-e2k.c b/bfd/cpu-e2k.c index 5f03d7b30e..ad95692bca 100644 --- a/bfd/cpu-e2k.c +++ b/bfd/cpu-e2k.c @@ -38,10 +38,12 @@ canonicalize_arch_name (const char *name, int *pmode) if (pcolon != NULL) { - if (((pcolon[1] == '3' && pcolon[2] == '2' && (mode = 32)) - || (pcolon[1] == '6' && pcolon[2] == '4' && (mode = 64)) - || (pcolon[1] == 'p' && pcolon[2] == 'm' && (mode = 128))) - && pcolon[3] == '\0') + if ((((pcolon[1] == '3' && pcolon[2] == '2' && (mode = 32)) + || (pcolon[1] == '6' && pcolon[2] == '4' && (mode = 64)) + || (pcolon[1] == 'p' && pcolon[2] == 'm' && (mode = 128))) + && pcolon[3] == '\0') + || (pcolon[1] == 'a' && pcolon[2] == 'n' && pcolon[3] == 'y' + && pcolon[4] == '\0' && (mode = 256))) len = pcolon - name; else return NULL; @@ -56,18 +58,10 @@ canonicalize_arch_name (const char *name, int *pmode) #define STRNCMP(s1, s2, n) \ ((n == sizeof (s2) - 1 && strncmp (s1, s2, n) == 0) ? 0 : 1) - if (STRNCMP (name, "generic", len) == 0 - /* FIXME: `ARCH=e2k' is still used within the generated LD scripts for - E2K. Changing it to "generic" would result in a reference to some dummy - `bfd_arch_generic' which is definitely not the thing I need. */ - || STRNCMP (name, "e2k", len) == 0) - name = "generic"; - else if (STRNCMP (name, "elbrus-v1", len) == 0 - || STRNCMP (name, "elbrus", len) == 0) - name = "elbrus-v1"; - else if (STRNCMP (name, "elbrus-v2", len) == 0 - || STRNCMP (name, "elbrus-2c+", len) == 0 - || STRNCMP (name, "elbrus-2cm", len) == 0) + if (STRNCMP (name, "e2k", len) == 0 + || STRNCMP (name, "elbrus-v2", len) == 0 + || STRNCMP (name, "elbrus-2c+", len) == 0 + || STRNCMP (name, "elbrus-2cm", len) == 0) name = "elbrus-v2"; else if (STRNCMP (name, "elbrus-v3", len) == 0 || STRNCMP (name, "elbrus-4c", len) == 0) @@ -95,13 +89,13 @@ canonicalize_arch_name (const char *name, int *pmode) static bfd_boolean e2k_scan (const struct bfd_arch_info *info, const char *string) { - static const int modes[] = {64, 32, 128}; + static const int modes[] = {64, 32, 128, 256}; const char *canon; int mode; canon = canonicalize_arch_name (string, &mode); if (canon != NULL - && mode == modes[info->mach % 3] + && mode == modes[info->mach % 4] && strncmp (canon, info->printable_name, strlen (canon)) == 0) return TRUE; @@ -113,44 +107,120 @@ extern const bfd_arch_info_type bfd_e2k_arch; static const bfd_arch_info_type * bfd_e2k_compatible (const bfd_arch_info_type *i, const bfd_arch_info_type *o) { + /* FIXME: while reworking this function to make it return the "least common + denominator" of I and O a limited amount of code was copy/pasted from + `_bfd_e2k_elf_merge_private_bfd_data_1 ()'. Moreover, it was simplified + so as not to take EF_E2K_INCOMPAT case into account. The latter means + that GDB won't emit a warning (not an error?) on an attempt to execute a + forward-incompatible ELF for elbrus-vX on elbrus-v{Y > X} at it'll be the + Kernel that will prevent this. To make such a control possible here info + on the presence of EF_E2K_INCOMPAT should probably be encoded in `bfd_arch + _info_type.mach' along with 32-, 64-bit or PM ABIs. Once this is done, it + should be possible to delegate similar activities from `_bfd_e2k_elf_merge + _private_bfd_data_1 ()' to this function. */ + enum + { + ev1, + ev2, + ev3, + e8c, + e1cplus, + ev5, + e12c, + e16c, + e2c3, + /* The related bit in mask stands for "all future processor models". */ + ev7 + }; + +#define AT(p) (1L << p) +#define AT_ev6 (AT (e12c) | AT (e16c) | AT (e2c3)) + + + /* A reduced version of mask[] from `_bfd_e2k_elf_merge_private_bfd_data_1 ()' + without an "incompatible" column. */ + static const unsigned long mask[] = + { + [bfd_mach_e2k_generic] = (AT (ev1) | AT (ev2) | AT (ev3) | AT (e8c) + | AT (e1cplus) | AT (ev5) | AT_ev6 + | AT (ev7)), + + [bfd_mach_e2k_ev1] = AT (ev1), + + [bfd_mach_e2k_ev2] = (AT (ev2) | AT (ev3) | AT (e8c) | AT (e1cplus) + | AT (ev5) | AT_ev6 | AT (ev7)), + + [bfd_mach_e2k_ev3] = (AT (ev3) | AT (e8c) | AT (e1cplus) | AT (ev5) + | AT_ev6 | AT (ev7)), + + [bfd_mach_e2k_ev4] = (AT (e8c) | AT (e1cplus) | AT (ev5) | AT_ev6 + | AT (ev7)), + + [bfd_mach_e2k_ev5] = (AT (ev5) | AT_ev6 | AT (ev7)), + + [bfd_mach_e2k_ev6] = (AT_ev6 | AT (ev7)), + + [bfd_mach_e2k_8c] = AT (e8c), + + [bfd_mach_e2k_1cplus] = AT (e1cplus), + + [bfd_mach_e2k_12c] = AT (e12c), + + [bfd_mach_e2k_16c] = AT (e16c), + + [bfd_mach_e2k_2c3] = AT (e2c3), + }; + + unsigned long imach, omach, remind; + unsigned int j; + + if (i->arch != o->arch) return NULL; - /* Check whether input and output BFDs have the same ABI. */ - if (i->mach % 3 != o->mach % 3) + imach = i->mach; + omach = o->mach; + + /* Check whether input and output BFDs have the same ABI. 3 stands for + "any ABI will do" and is currently used when assigning bfd_arch_info + to TARGET_DESC in gdb as there is probably no way to determine which + mode the inferior is started in. */ + if (imach % 4 != 3 && omach % 4 != 3 && imach % 4 != omach % 4) return NULL; - /* Nowadays that we should be able to dynamically choose an output - machine without `-A' (see Bug #58358) any further checks here - are meaningless. They are moved to `_bfd_e2k_merge_private_bfd_data'. - Just return our "generic" arch info in order not to upset - `lang_check ()'. It turns out that a value returned by this function - is not actually used at all except for aforementioned formal(?) check and + remind = (imach % 4 != 3) ? imach % 4 : omach % 4; - . . . GDB's `can_run_code_for ()' which expects us to return the "more - featureful" of the two arches. For it to succeed the returned arch should - coincide with that of the executable, which is the `I' argument of this - function). I think that it's quite reasonable to return `I' for now, since - its arch can't certainly turn out to be "less featureful" than the minimal - arch of the GDB's handler, represented by `O'. But this may very well - change once GDB for E2K gets "non-minimal" handlers! + imach /= 4; + omach /= 4; - By the way, why don't they want to let GDB's handler have a more advanced - arch than that of the executable? As far as I remember, this is because a - more "featureful" handler may require registers which aren't provided by - the executable's primitive ABI. */ + imach = mask[imach]; + omach = mask[omach]; - return i; + omach = omach & imach; + if (omach != 0) + { + for (j = 0; j < sizeof (mask) / sizeof (mask[0]); j++) + { + if (omach == mask[j]) + return bfd_lookup_arch (o->arch, 4 * j + remind); + } + } + + return NULL; } #define BITS_ADDR_64 64 #define BITS_ADDR_32 32 #define BITS_ADDR_pm 32 +/* This is a formal definition as we are unaware of "BITS_ADDR" when "any" + bfd_arch_info_type is used. */ +#define BITS_ADDR_any 64 -#define MACH_64(mach) (3 * (mach)) -#define MACH_32(mach) (3 * (mach) + 1) -#define MACH_pm(mach) (3 * (mach) + 2) +#define MACH_64(mach) (4 * (mach)) +#define MACH_32(mach) (4 * (mach) + 1) +#define MACH_pm(mach) (4 * (mach) + 2) +#define MACH_any(mach) (4 * (mach) + 3) #define PRINT_PREFIX_64 "64-bit ABI for " #define PRINT_PREFIX_32 "32-bit ABI for " @@ -181,102 +251,144 @@ bfd_e2k_compatible (const bfd_arch_info_type *i, const bfd_arch_info_type *o) bfd_e2k_compatible, \ e2k_scan, \ bfd_arch_default_fill, \ - NEXT \ + NEXT, \ + 0 /* Maximum offset of a reloc from the start of an insn. */ \ } /* These indices are used to refer to the next arch_info entry. I_generic_64 is not needed here since the corresponding entry is defined apart. */ enum { + I_generic_64 = -1, I_generic_32, I_generic_pm, + I_generic_any, I_ev1_64, I_ev1_32, I_ev1_pm, + I_ev1_any, I_ev2_64, I_ev2_32, I_ev2_pm, + I_ev2_any, I_ev3_64, I_ev3_32, I_ev3_pm, + I_ev3_any, I_ev4_64, I_ev4_32, I_ev4_pm, + I_ev4_any, I_ev5_64, I_ev5_32, I_ev5_pm, + I_ev5_any, I_ev6_64, I_ev6_32, I_ev6_pm, + I_ev6_any, I_8c_64, I_8c_32, I_8c_pm, + I_8c_any, I_1cplus_64, I_1cplus_32, I_1cplus_pm, + I_1cplus_any, + + I_12c_64, + I_12c_32, + I_12c_pm, + I_12c_any, + + I_16c_64, + I_16c_32, + I_16c_pm, + I_16c_any, + + I_2c3_64, + I_2c3_32, + I_2c3_pm, + I_2c3_any }; #define NN(index) (&arch_info_struct[(index) + 1]) -static const bfd_arch_info_type arch_info_struct[] = +#define FIRST_TRIP(mach, name) \ + N (bfd_mach_e2k_##mach, 32, name, FALSE, NN (I_##mach##_32)), \ + N (bfd_mach_e2k_##mach, pm, name, FALSE, NN (I_##mach##_pm)), \ + N (bfd_mach_e2k_##mach, any, name, FALSE, NN (I_##mach##_any)) + +#define TRIP(mach, name) \ + N (bfd_mach_e2k_##mach, 64, name, FALSE, NN (I_##mach##_64)), \ + N (bfd_mach_e2k_##mach, 32, name, FALSE, NN (I_##mach##_32)), \ + N (bfd_mach_e2k_##mach, pm, name, FALSE, NN (I_##mach##_pm)) + +#define QUAD(mach, name) \ + TRIP (mach, name), \ + N (bfd_mach_e2k_##mach, any, name, FALSE, NN (I_##mach##_any)) + +#define LAST_QUAD(mach, name) \ + TRIP (mach, name), \ + N (bfd_mach_e2k_##mach, any, name, FALSE, NULL) + + + + +const bfd_arch_info_type arch_info_struct[] = { /* The two remaining generic entries. */ - N (bfd_mach_e2k_generic, 32, "generic", FALSE, NN (I_generic_32)), - N (bfd_mach_e2k_generic, pm, "generic", FALSE, NN (I_generic_pm)), + FIRST_TRIP (generic, "generic"), /* `elbrus-v1' entries. */ - N (bfd_mach_e2k_ev1, 64, "elbrus-v1", FALSE, NN (I_ev1_64)), - N (bfd_mach_e2k_ev1, 32, "elbrus-v1", FALSE, NN (I_ev1_32)), - N (bfd_mach_e2k_ev1, pm, "elbrus-v1", FALSE, NN (I_ev1_pm)), - + QUAD (ev1, "elbrus-v1"), + /* `elbrus-v2' entries. */ - N (bfd_mach_e2k_ev2, 64, "elbrus-v2", FALSE, NN (I_ev2_64)), - N (bfd_mach_e2k_ev2, 32, "elbrus-v2", FALSE, NN (I_ev2_32)), - N (bfd_mach_e2k_ev2, pm, "elbrus-v2", FALSE, NN (I_ev2_pm)), + QUAD (ev2, "elbrus-v2"), /* `elbrus-v3' entries. */ - N (bfd_mach_e2k_ev3, 64, "elbrus-v3", FALSE, NN (I_ev3_64)), - N (bfd_mach_e2k_ev3, 32, "elbrus-v3", FALSE, NN (I_ev3_32)), - N (bfd_mach_e2k_ev3, pm, "elbrus-v3", FALSE, NN (I_ev3_pm)), + QUAD (ev3, "elbrus-v3"), /* `elbrus-v4' entries. */ - N (bfd_mach_e2k_ev4, 64, "elbrus-v4", FALSE, NN (I_ev4_64)), - N (bfd_mach_e2k_ev4, 32, "elbrus-v4", FALSE, NN (I_ev4_32)), - N (bfd_mach_e2k_ev4, pm, "elbrus-v4", FALSE, NN (I_ev4_pm)), + QUAD (ev4, "elbrus-v4"), /* `elbrus-v5' entries. */ - N (bfd_mach_e2k_ev5, 64, "elbrus-v5", FALSE, NN (I_ev5_64)), - N (bfd_mach_e2k_ev5, 32, "elbrus-v5", FALSE, NN (I_ev5_32)), - N (bfd_mach_e2k_ev5, pm, "elbrus-v5", FALSE, NN (I_ev5_pm)), + QUAD (ev5, "elbrus-v5"), /* `elbrus-v6' entries. */ - N (bfd_mach_e2k_ev6, 64, "elbrus-v6", FALSE, NN (I_ev6_64)), - N (bfd_mach_e2k_ev6, 32, "elbrus-v6", FALSE, NN (I_ev6_32)), - N (bfd_mach_e2k_ev6, pm, "elbrus-v6", FALSE, NN (I_ev6_pm)), + QUAD (ev6, "elbrus-v6"), /* Entries, describing the specific `elbrus-8c' processor also known as Processor-1 (elbrus-v4). */ - N (bfd_mach_e2k_8c, 64, "elbrus-8c", FALSE, NN (I_8c_64)), - N (bfd_mach_e2k_8c, 32, "elbrus-8c", FALSE, NN (I_8c_32)), - N (bfd_mach_e2k_8c, pm, "elbrus-8c", FALSE, NN (I_8c_pm)), + QUAD (8c, "elbrus-8c"), /* Entries, describing the specific `elbrus-1c+' processor also known as Processor-2 (elbrus-v4). */ - N (bfd_mach_e2k_1cplus, 64, "elbrus-1c+", FALSE, NN (I_1cplus_64)), - N (bfd_mach_e2k_1cplus, 32, "elbrus-1c+", FALSE, NN (I_1cplus_32)), - N (bfd_mach_e2k_1cplus, pm, "elbrus-1c+", FALSE, NULL) + QUAD (1cplus, "elbrus-1c+"), + + /* Entries, describing the specific `elbrus-12c' processor of elbrus-v6 + series. */ + QUAD (12c, "elbrus-12c"), + + /* Entries, describing the specific `elbrus-16c' processor of elbrus-v6 + series. */ + QUAD (16c, "elbrus-16c"), + + /* Entries, describing the specific `elbrus-2c3' processor of elbrus-v6 + series. */ + LAST_QUAD (2c3, "elbrus-2c3") }; /* I don't remember for sure what DEFAULT actually means here. We should probably only one default arch, however. Let it be a 64-bit elbrus generic arch. */ const bfd_arch_info_type bfd_e2k_arch = - N (bfd_mach_e2k_generic, 64, "generic", TRUE, &arch_info_struct[0]); + N (bfd_mach_e2k_generic, 64, "generic", TRUE, NN (I_generic_64)); diff --git a/bfd/cpu-sparc.c b/bfd/cpu-sparc.c index b2528c5843..a0a9242b9c 100644 --- a/bfd/cpu-sparc.c +++ b/bfd/cpu-sparc.c @@ -62,7 +62,13 @@ static const bfd_arch_info_type arch_info_struct[] = N (32, bfd_mach_sparc_v8plusm, "sparc:v8plusm", FALSE, arch_info_struct + 18), N (64, bfd_mach_sparc_v9m, "sparc:v9m", FALSE, arch_info_struct + 19), N (32, bfd_mach_sparc_v8plusm8, "sparc:v8plusm8", FALSE, arch_info_struct + 20), - N (64, bfd_mach_sparc_v9m8, "sparc:v9m8", FALSE, NULL) + N (64, bfd_mach_sparc_v9m8, "sparc:v9m8", FALSE, arch_info_struct + 21), + N (32, bfd_mach_sparc_v8plus_r1000, "sparc:v8plus_r1000", FALSE, arch_info_struct + 22), + N (64, bfd_mach_sparc_v9_r1000, "sparc:r1000", FALSE, arch_info_struct + 23), + N (32, bfd_mach_sparc_v8plus_r2000, "sparc:v8plus_r2000", FALSE, arch_info_struct + 24), + N (64, bfd_mach_sparc_v9_r2000, "sparc:r2000", FALSE, arch_info_struct + 25), + N (32, bfd_mach_sparc_v8plus_r2000_plus, "sparc:v8plus_r2000_plus", FALSE, arch_info_struct + 26), + N (64, bfd_mach_sparc_v9_r2000_plus, "sparc:r2000_plus", FALSE, NULL), }; const bfd_arch_info_type bfd_sparc_arch = diff --git a/bfd/development.sh b/bfd/development.sh index 6bbed41d6d..32be4b9460 100644 --- a/bfd/development.sh +++ b/bfd/development.sh @@ -16,7 +16,7 @@ # along with this program. If not, see . # Controls whether to enable development-mode features by default. -development=true +development=false # Indicate whether this is a release branch. experimental=false diff --git a/bfd/eir.c b/bfd/eir.c index e02c5397a2..5cd04d1ac9 100644 --- a/bfd/eir.c +++ b/bfd/eir.c @@ -74,16 +74,16 @@ const bfd_target eir_vec = _bfd_dummy_target, }, { /* bfd_set_format */ - bfd_false, - bfd_true, - bfd_false, - bfd_false, + _bfd_bool_bfd_false_error, + _bfd_bool_bfd_true, + _bfd_bool_bfd_false_error, + _bfd_bool_bfd_false_error, }, { /* bfd_write_contents */ - bfd_false, - bfd_true, - bfd_false, - bfd_false, + _bfd_bool_bfd_false_error, + _bfd_bool_bfd_true, + _bfd_bool_bfd_false_error, + _bfd_bool_bfd_false_error, }, BFD_JUMP_TABLE_GENERIC (_bfd_generic), diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index 1576724511..9aea3fafdc 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -523,6 +523,7 @@ enum elf_target_id TILEGX_ELF_DATA, TILEPRO_ELF_DATA, RISCV_ELF_DATA, + E2K_ELF_DATA, GENERIC_ELF_DATA }; @@ -1664,6 +1665,8 @@ struct elf_backend_data /* True if the 64-bit Linux PRPSINFO structure's `pr_uid' and `pr_gid' members use a 16-bit data type. */ unsigned linux_prpsinfo64_ugid16 : 1; + + bfd_vma r_none_info; }; /* Information about reloc sections associated with a bfd_elf_section_data @@ -2887,6 +2890,12 @@ extern bfd_boolean _bfd_elf_allocate_ifunc_dyn_relocs struct elf_dyn_relocs **, unsigned int, unsigned int, unsigned int, bfd_boolean); +/* Leave it in place since E2K needs it. */ +extern long _bfd_elf_ifunc_get_synthetic_symtab + (bfd *, long, asymbol **, long, asymbol **, asymbol **, asection *, + int, void *, + bfd_vma *(*) (bfd *, asymbol **, asection *, asection *, int, void *)); + extern void elf_append_rela (bfd *, asection *, Elf_Internal_Rela *); extern void elf_append_rel (bfd *, asection *, Elf_Internal_Rela *); @@ -2917,6 +2926,15 @@ extern bfd_boolean _bfd_elf_maybe_set_textrel extern bfd_boolean _bfd_elf_add_dynamic_tags (bfd *, struct bfd_link_info *, bfd_boolean); +/* Stupidly ensure that this is NOT compiled for non-e2k targets. */ +#ifdef HAVE_e2k_elf64_vec +extern bfd_vma adjust_offset_in_cud_gd + (struct bfd_link_info *, bfd_vma); + +extern bfd_vma orig_offset_in_cud + (struct bfd_link_info *, bfd_vma); +#endif /* HAVE_e2k_elf64_vec */ + /* Large common section. */ extern asection _bfd_elf_large_com_section; diff --git a/bfd/elf-eh-frame.c b/bfd/elf-eh-frame.c index fa61cb0d0a..ce1bdce8c1 100644 --- a/bfd/elf-eh-frame.c +++ b/bfd/elf-eh-frame.c @@ -1002,6 +1002,15 @@ _bfd_elf_parse_eh_frame (bfd *abfd, struct bfd_link_info *info, CIE instructions. */ || (set_loc_count && this_inf->cie)) goto free_no_table; + + /* Prevent e2k-linux-ld from adjusting the size of entries (are only CIEs + adjusted this way?) and thus ensure that the 16 byte alignment of all + subsequent CIEs and FDEs is preserved in such a primitive way . . . */ + if (((elf_elfheader (abfd)->e_flags & 32 /* EF_E2K_PM */) + == 32 /* EF_E2K_PM */) + && strstr (abfd->xvec->name, "e2k-pm") != NULL) + insns_end = end; + this_inf->size -= end - insns_end; if (insns_end != end && this_inf->cie) { @@ -2164,9 +2173,28 @@ _bfd_elf_write_section_eh_frame (bfd *abfd, break; case DW_EH_PE_pcrel: value += (bfd_vma) ent->offset - ent->new_offset; - address += (sec->output_section->vma - + sec->output_offset - + ent->offset + 8); + address += +#ifdef HAVE_e2k_elf64_vec + /* Note "This is called with the relocated contents" above + meaning that "pc-relative deltas" read from the section + contain the differencies of PACKED addresses in e2k PM + written out by my backend. Therefore, evaluate the + absolute PACKED address and ... */ + adjust_offset_in_cud_gd (info, +#endif + (sec->output_section->vma + + sec->output_offset + + ent->offset + 8) +#ifdef HAVE_e2k_elf64_vec + ) +#endif + ; +#ifdef HAVE_e2k_elf64_vec + /* ... use it to restore the original absolute one. Later it + will be used to calculate another PACKED "pc-relative + delta" from another location. */ + address = orig_offset_in_cud (info, address); +#endif break; } if (ent->make_relative) @@ -2470,19 +2498,83 @@ write_dwarf_eh_frame_hdr (bfd *abfd, struct bfd_link_info *info) { bfd_vma val; - val = hdr_info->u.dwarf.array[i].initial_loc - - sec->output_section->vma; + val = + ( +#ifdef HAVE_e2k_elf64_vec + adjust_offset_in_cud_gd (info, +#endif + hdr_info->u.dwarf.array[i].initial_loc +#ifdef HAVE_e2k_elf64_vec + ) +#endif + - +#ifdef HAVE_e2k_elf64_vec + adjust_offset_in_cud_gd (info, +#endif + sec->output_section->vma +#ifdef HAVE_e2k_elf64_vec + ) +#endif + ); + val = ((val & 0xffffffff) ^ 0x80000000) - 0x80000000; if (elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS64 - && (hdr_info->u.dwarf.array[i].initial_loc - != sec->output_section->vma + val)) + && ( +#ifdef HAVE_e2k_elf64_vec + adjust_offset_in_cud_gd (info, +#endif + hdr_info->u.dwarf.array[i].initial_loc +#ifdef HAVE_e2k_elf64_vec + ) +#endif + != +#ifdef HAVE_e2k_elf64_vec + adjust_offset_in_cud_gd (info, +#endif + sec->output_section->vma +#ifdef HAVE_e2k_elf64_vec + ) +#endif + + val)) overflow = TRUE; bfd_put_32 (abfd, val, contents + EH_FRAME_HDR_SIZE + i * 8 + 4); - val = hdr_info->u.dwarf.array[i].fde - sec->output_section->vma; + val = ( +#ifdef HAVE_e2k_elf64_vec + adjust_offset_in_cud_gd (info, +#endif + hdr_info->u.dwarf.array[i].fde +#ifdef HAVE_e2k_elf64_vec + ) +#endif + - +#ifdef HAVE_e2k_elf64_vec + adjust_offset_in_cud_gd (info, +#endif + sec->output_section->vma +#ifdef HAVE_e2k_elf64_vec + ) +#endif + ); val = ((val & 0xffffffff) ^ 0x80000000) - 0x80000000; if (elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS64 - && (hdr_info->u.dwarf.array[i].fde - != sec->output_section->vma + val)) + && ( +#ifdef HAVE_e2k_elf64_vec + adjust_offset_in_cud_gd (info, +#endif + + hdr_info->u.dwarf.array[i].fde +#ifdef HAVE_e2k_elf64_vec + ) +#endif + != +#ifdef HAVE_e2k_elf64_vec + adjust_offset_in_cud_gd (info, +#endif + sec->output_section->vma +#ifdef HAVE_e2k_elf64_vec + ) +#endif + + val)) overflow = TRUE; bfd_put_32 (abfd, val, contents + EH_FRAME_HDR_SIZE + i * 8 + 8); if (i != 0 diff --git a/bfd/elf-ifunc.c b/bfd/elf-ifunc.c index 904950ccf4..8126d1e473 100644 --- a/bfd/elf-ifunc.c +++ b/bfd/elf-ifunc.c @@ -348,3 +348,173 @@ _bfd_elf_allocate_ifunc_dyn_relocs (struct bfd_link_info *info, return TRUE; } + +/* Leave the underlying function in place since E2K needs it. */ + +/* Similar to _bfd_elf_get_synthetic_symtab, optimized for unsorted PLT + entries. PLT is the PLT section. PLT_SYM_VAL is a function pointer + which returns an array of PLT entry symbol values. */ + +long +_bfd_elf_ifunc_get_synthetic_symtab + (bfd *abfd, long symcount ATTRIBUTE_UNUSED, + asymbol **syms ATTRIBUTE_UNUSED, long dynsymcount, asymbol **dynsyms, + asymbol **ret, asection *plt, + int kind, + void *dummy, + bfd_vma *(*get_plt_sym_val) (bfd *, asymbol **, asection *, asection *, + int, void *)) +{ + const struct elf_backend_data *bed = get_elf_backend_data (abfd); + asection *relplt; + asymbol *s; + const char *relplt_name; + bfd_boolean (*slurp_relocs) (bfd *, asection *, asymbol **, bfd_boolean); + arelent *p; + long count, i, n; + size_t size; + Elf_Internal_Shdr *hdr; + char *names; + bfd_vma *plt_sym_val; + const char *plt_sfx; + size_t plt_sfx_sz; + + switch (kind) + { + case 0: + plt_sfx = "@plt"; + plt_sfx_sz = sizeof ("@plt"); + break; + case 1: + plt_sfx = "@secondary_plt"; + plt_sfx_sz = sizeof ("@secondary_plt"); + break; + case 2: + plt_sfx = "@plt.got"; + plt_sfx_sz = sizeof ("@plt.got"); + break; + default: + return -1; + } + + *ret = NULL; + + if (plt == NULL) + return 0; + + if ((abfd->flags & (DYNAMIC | EXEC_P)) == 0) + return 0; + + if (dynsymcount <= 0) + return 0; + + /* When looking for primary and secondary PLT entries one should iterate + over `.rela.plt', whereas for `.plt.got' entries (recall that they are + created for functions a pointer to which should be resolved in a non-lazy + way (in a shared library?)) - over `.rela.dyn'. */ + if (kind == 0 || kind == 1) + { + relplt_name = bed->relplt_name; + if (relplt_name == NULL) + relplt_name = bed->rela_plts_and_copies_p ? ".rela.plt" : ".rel.plt"; + relplt = bfd_get_section_by_name (abfd, relplt_name); + } + else + { + /* FIXME: currently this function is called with `kind == 2' for E2K + only. How should I properly choose between `.rel{,a}.dyn' on other + platforms? */ + relplt_name = ".rela.dyn"; + + /* FIXME: is it worthwhile to iterate over a potentially huge `.rela.dyn' + for just a few relocations related to `.plt.got' entries? There are a + couple of such entries in libc.so . . . */ + relplt = bfd_get_section_by_name (abfd, relplt_name); + } + + if (relplt == NULL) + return 0; + + hdr = &elf_section_data (relplt)->this_hdr; + if (hdr->sh_link != elf_dynsymtab (abfd) + || (hdr->sh_type != SHT_REL && hdr->sh_type != SHT_RELA)) + return 0; + + slurp_relocs = get_elf_backend_data (abfd)->s->slurp_reloc_table; + if (! (*slurp_relocs) (abfd, relplt, dynsyms, TRUE)) + return -1; + + count = relplt->size / hdr->sh_entsize; + size = count * sizeof (asymbol); + p = relplt->relocation; + for (i = 0; i < count; i++, p += bed->s->int_rels_per_ext_rel) + { + size += strlen ((*p->sym_ptr_ptr)->name) + plt_sfx_sz; + if (p->addend != 0) + { +#ifdef BFD64 + size += sizeof ("+0x") - 1 + 8 + 8 * (bed->s->elfclass == ELFCLASS64); +#else + size += sizeof ("+0x") - 1 + 8; +#endif + } + } + + plt_sym_val = get_plt_sym_val (abfd, dynsyms, plt, relplt, kind, dummy); + if (plt_sym_val == NULL) + return -1; + + s = *ret = (asymbol *) bfd_malloc (size); + if (s == NULL) + { + free (plt_sym_val); + return -1; + } + + names = (char *) (s + count); + p = relplt->relocation; + n = 0; + for (i = 0; i < count; i++, p += bed->s->int_rels_per_ext_rel) + { + size_t len; + bfd_vma addr; + + addr = plt_sym_val[i]; + if (addr == (bfd_vma) -1) + continue; + + *s = **p->sym_ptr_ptr; + /* Undefined syms won't have BSF_LOCAL or BSF_GLOBAL set. Since + we are defining a symbol, ensure one of them is set. */ + if ((s->flags & BSF_LOCAL) == 0) + s->flags |= BSF_GLOBAL; + s->flags |= BSF_SYNTHETIC; + s->section = plt; + s->value = addr - plt->vma; + s->name = names; + s->udata.p = NULL; + len = strlen ((*p->sym_ptr_ptr)->name); + memcpy (names, (*p->sym_ptr_ptr)->name, len); + names += len; + if (p->addend != 0) + { + char buf[30], *a; + + memcpy (names, "+0x", sizeof ("+0x") - 1); + names += sizeof ("+0x") - 1; + bfd_sprintf_vma (abfd, buf, p->addend); + for (a = buf; *a == '0'; ++a) + ; + len = strlen (a); + memcpy (names, a, len); + names += len; + } + memcpy (names, plt_sfx, plt_sfx_sz); + names += plt_sfx_sz; + ++s, ++n; + } + + free (plt_sym_val); + + return n; +} diff --git a/bfd/elf32-e2k-pm-uclibc.c b/bfd/elf32-e2k-pm-uclibc.c new file mode 100644 index 0000000000..90f682b32f --- /dev/null +++ b/bfd/elf32-e2k-pm-uclibc.c @@ -0,0 +1,18 @@ +/* The only macro that should be defined prior to inclusion of + elf32-e2k.c so as to prevent it from including elf32-target.h + before we redefine all other macros of interest. */ +#define TARGET_LITTLE_NAME "elf32-e2k-pm-uclibc" +#include "elf32-e2k.c" + +#undef TARGET_LITTLE_SYM +#define TARGET_LITTLE_SYM e2k_pm_uclibc_elf32_vec + +#include "elfxx-e2k-pm.h" + +#include "elfxx-e2k-uclibc.h" + +#undef bfd_elf32_bfd_merge_private_bfd_data +#define bfd_elf32_bfd_merge_private_bfd_data \ + _bfd_e2k_uclibc_elf_merge_private_bfd_data + +#include "elf32-target.h" diff --git a/bfd/elf32-e2k-pm.c b/bfd/elf32-e2k-pm.c index 9bd39f12ed..6b273c4b44 100644 --- a/bfd/elf32-e2k-pm.c +++ b/bfd/elf32-e2k-pm.c @@ -1,130 +1,12 @@ -#include "sysdep.h" -#include "bfd.h" -#include "libbfd.h" -#include "elf-bfd.h" -#include "elf/e2k.h" -#include "elfxx-e2k.h" - -static bfd_boolean -segment_executable (struct elf_segment_map *seg) -{ - if (seg->p_flags_valid) - return (seg->p_flags & PF_X) != 0; - else - { - /* The p_flags value has not been computed yet, - so we have to look through the sections. */ - unsigned int i; - for (i = 0; i < seg->count; ++i) - if (seg->sections[i]->flags & SEC_CODE) - return TRUE; - } - return FALSE; -} - -/* Determine if this segment is eligible to receive the file and program - headers. It must be read-only and non-executable. - Its first section must start far enough past the page boundary to - allow space for the headers. */ -static bfd_boolean -segment_eligible_for_headers (struct elf_segment_map *seg, - bfd_vma minpagesize, bfd_vma sizeof_headers) -{ - unsigned int i; - if (seg->count == 0 || seg->sections[0]->lma % minpagesize < sizeof_headers) - return FALSE; - for (i = 0; i < seg->count; ++i) - { - if ((seg->sections[i]->flags & (SEC_CODE|SEC_READONLY)) != SEC_READONLY) - return FALSE; - } - return TRUE; -} - - -static bfd_boolean -_bfd_e2k_pm_elf_modify_segment_map (bfd *abfd, struct bfd_link_info *info) -{ - const struct elf_backend_data *const bed = get_elf_backend_data (abfd); - struct elf_segment_map **m = &elf_seg_map (abfd); - struct elf_segment_map **first_load = NULL; - struct elf_segment_map **last_load = NULL; - bfd_boolean moved_headers = FALSE; - int sizeof_headers; - - sizeof_headers = bfd_sizeof_headers (abfd, info); - - while (*m != NULL) - { - struct elf_segment_map *seg = *m; - - if (seg->p_type == PT_LOAD) - { - bfd_boolean executable = segment_executable (seg); - - /* First, we're just finding the earliest PT_LOAD. - By the normal rules, this will be the lowest-addressed one. - We only have anything interesting to do if it's executable. */ - last_load = m; - if (first_load == NULL) - { - if (!executable) - goto next; - first_load = m; - } - /* Now that we've noted the first PT_LOAD, we're looking for - the first non-executable PT_LOAD with a nonempty p_filesz. */ - else if (!moved_headers - && segment_eligible_for_headers (seg, bed->minpagesize, - sizeof_headers)) - { - /* This is the one we were looking for! - - First, clear the flags on previous segments that - say they include the file header and phdrs. */ - struct elf_segment_map *prevseg; - for (prevseg = *first_load; - prevseg != seg; - prevseg = prevseg->next) - if (prevseg->p_type == PT_LOAD) - { - prevseg->includes_filehdr = 0; - prevseg->includes_phdrs = 0; - } - - /* This segment will include those headers instead. */ - seg->includes_filehdr = 1; - seg->includes_phdrs = 1; - - moved_headers = TRUE; - } - } - - next: - m = &seg->next; - } - - if (first_load != last_load && moved_headers) - { - /* Now swap the first and last PT_LOAD segments' - positions in segment_map. */ - struct elf_segment_map *first = *first_load; - struct elf_segment_map *last = *last_load; - *first_load = first->next; - first->next = last->next; - last->next = first; - } - - return TRUE; -} - -#define elf_backend_modify_segment_map _bfd_e2k_pm_elf_modify_segment_map - -/* The first Elf32_Addr GOT entry containing link-time "address" of `_DYNAMIC' - is followed by two 16 bytes long appropriately aligned descriptors containing - `struct link_map *' and `&_dl_fixup ()'. */ -#define elf_backend_got_header_size 48 -#define TARGET_LITTLE_SYM e2k_pm_elf32_vec +/* The only macro that should be defined prior to inclusion of + elf32-e2k.c so as to prevent it from including elf32-target.h + before we redefine all other macros of interest. */ #define TARGET_LITTLE_NAME "elf32-e2k-pm" - #include "elf32-e2k.c" + +#undef TARGET_LITTLE_SYM +#define TARGET_LITTLE_SYM e2k_pm_elf32_vec + +#include "elfxx-e2k-pm.h" + +#include "elf32-target.h" diff --git a/bfd/elf32-e2k.c b/bfd/elf32-e2k.c index c95d58d2af..b47000d0a5 100644 --- a/bfd/elf32-e2k.c +++ b/bfd/elf32-e2k.c @@ -19,8 +19,6 @@ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ -#if ! defined TARGET_LITTLE_SYM - #include "sysdep.h" #include "bfd.h" #include "libbfd.h" @@ -28,9 +26,6 @@ #include "elf/e2k.h" #include "elfxx-e2k.h" -#endif - - static int elf32_e2k_write_out_phdrs (bfd *abfd, const Elf_Internal_Phdr *phdr, @@ -111,6 +106,7 @@ static const struct elf_size_info elf32_e2k_size_info = { #define bfd_elf32_bfd_reloc_type_lookup _bfd_e2k_elf_reloc_type_lookup #define bfd_elf32_bfd_reloc_name_lookup _bfd_e2k_elf_reloc_name_lookup #define bfd_elf32_bfd_merge_private_bfd_data _bfd_e2k_elf_merge_private_bfd_data + #define bfd_elf32_mkobject _bfd_e2k_elf_mkobject #define bfd_elf32_bfd_link_hash_table_create _bfd_e2k_elf_link_hash_table_create #define bfd_elf32_bfd_final_link _bfd_e2k_elf_final_link @@ -140,10 +136,11 @@ static const struct elf_size_info elf32_e2k_size_info = { #define elf_backend_finish_dynamic_symbol _bfd_e2k_elf_finish_dynamic_symbol #define elf_backend_reloc_type_class _bfd_e2k_elf_reloc_type_class #define elf_backend_finish_dynamic_sections _bfd_e2k_elf_finish_dynamic_sections -#define elf_backend_post_process_headers _bfd_e2k_elf_post_process_headers +#define elf_backend_init_file_header _bfd_e2k_elf_init_file_header #define elf_backend_ignore_discarded_relocs _bfd_e2k_elf_ignore_discarded_relocs #define elf_backend_hide_symbol _bfd_e2k_elf_hide_symbol -#define elf_backend_object_p _bfd_e2k_elf_object_p +#define elf_backend_object_p _bfd_e2k_elf_object_p + #define elf_backend_setup_gnu_properties _bfd_e2k_elf_link_setup_gnu_properties /* Make tests employing `gc-sections' option PASS. I wonder if any backend- @@ -170,6 +167,10 @@ static const struct elf_size_info elf32_e2k_size_info = { #define elf_backend_r_none_info R_E2K_NONE +/* Let `bfd_elf_size_dynamic_sections ()' treat a missing PT_GNU_STACK as an + unexecutable one to be in line with the Kernel and glibc. */ +#define elf_backend_default_execstack 0 + #define ELF_ARCH bfd_arch_e2k @@ -180,19 +181,13 @@ static const struct elf_size_info elf32_e2k_size_info = { #define ELF_MAXPAGESIZE 0x1000 -#ifndef elf_backend_got_header_size /* The first entry in `.got' is reserved for the `_DYNAMIC' link-time address. */ -# define elf_backend_got_header_size 12 -#endif +#define elf_backend_got_header_size 12 -#ifndef TARGET_LITTLE_SYM -#define TARGET_LITTLE_SYM e2k_elf32_vec -#endif +#define TARGET_LITTLE_SYM e2k_elf32_vec #ifndef TARGET_LITTLE_NAME -#define TARGET_LITTLE_NAME "elf32-e2k" +# define TARGET_LITTLE_NAME "elf32-e2k" +# include "elf32-target.h" #endif - - -#include "elf32-target.h" diff --git a/bfd/elf32-sparc.c b/bfd/elf32-sparc.c index 4be618cc55..f55dbf10e7 100644 --- a/bfd/elf32-sparc.c +++ b/bfd/elf32-sparc.c @@ -75,6 +75,13 @@ elf32_sparc_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) /* FIXME: This should not be static. */ static unsigned long previous_ibfd_e_flags = (unsigned long) -1; + /* No matter whether the output BFD is ELF or not, check magic in the input + one provided that it is. */ + if (bfd_get_flavour (ibfd) == bfd_target_elf_flavour + && ! _bfd_sparc_elf_check_magic (ibfd)) + return FALSE; + + if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour || bfd_get_flavour (obfd) != bfd_target_elf_flavour) return TRUE; @@ -147,6 +154,17 @@ sparc_final_write_processing (bfd *abfd) elf_elfheader (abfd)->e_flags |= EF_SPARC_32PLUS | EF_SPARC_SUN_US1 | EF_SPARC_SUN_US3; break; + /* I cannot understand why in 32-bit mode the same functionality as in + (sparc_elf_final_processing (), tc-sparc.c) is DUPLICATED here. In fact + we set the same value of `e_flags' both there and here. */ + case bfd_mach_sparc_v8plus_r1000: + case bfd_mach_sparc_v8plus_r2000: + case bfd_mach_sparc_v8plus_r2000_plus: + elf_elfheader (abfd)->e_machine = EM_SPARC32PLUS; + elf_elfheader (abfd)->e_flags &=~ EF_SPARC_32PLUS_MASK; + elf_elfheader (abfd)->e_flags |= (EF_SPARC_32PLUS | EF_SPARC_SUN_US1 + | EF_SPARC_SUN_US3 | EF_SPARC_MCST); + break; case bfd_mach_sparc_sparclite_le: elf_elfheader (abfd)->e_flags |= EF_SPARC_LEDATA; break; @@ -273,6 +291,18 @@ elf32_sparc_reloc_type_class (const struct bfd_link_info *info, #define elf_backend_linux_prpsinfo32_ugid16 TRUE +/* EIR-specific hacks. */ +#define bfd_elf32_bfd_link_add_symbols _bfd_sparc_elf_link_add_symbols +#define bfd_elf32_bfd_final_link _bfd_sparc_elf_final_link +#define elf_backend_ignore_discarded_relocs _bfd_sparc_elf_ignore_discarded_relocs +#define elf_backend_hide_symbol _bfd_sparc_elf_hide_symbol +#define bfd_elf32_write_object_contents _bfd_sparc_elf_write_object_contents + +/* Let `.magic' section be `SHT_NOTE'. */ +#define elf_backend_special_sections _bfd_sparc_elf_special_sections + +#define elf_backend_extern_protected_data 1 + #include "elf32-target.h" /* Solaris 2. */ diff --git a/bfd/elf64-e2k-kpda.c b/bfd/elf64-e2k-kpda.c index 25d6a4d299..51d6ebdda2 100644 --- a/bfd/elf64-e2k-kpda.c +++ b/bfd/elf64-e2k-kpda.c @@ -1,8 +1,8 @@ -/* Signalize that elf64-e2k.c shouldn't set up bfd target vector for us. - We'll do it ourselves after redefining a few macros. */ -#define TARGET_KPDA +/* The only macro that should be defined prior to inclusion of + elf64-e2k.c so as to prevent it from including elf64-target.h + before we redefine all other macros of interest. */ +#define TARGET_LITTLE_NAME "elf64-e2k-kpda" #include "elf64-e2k.c" -#undef TARGET_KPDA #if 0 static void @@ -25,9 +25,6 @@ _bfd_e2k_kpda_elf64_post_process_headers (bfd *abfd, #undef TARGET_LITTLE_SYM #define TARGET_LITTLE_SYM e2k_kpda_elf64_vec -#undef TARGET_LITTLE_NAME -#define TARGET_LITTLE_NAME "elf64-e2k-kpda" - #define ELF_OSABI ELFOSABI_KPDA /* Now set up the target vector. */ diff --git a/bfd/elf64-e2k-pm.c b/bfd/elf64-e2k-pm.c new file mode 100644 index 0000000000..69e2946582 --- /dev/null +++ b/bfd/elf64-e2k-pm.c @@ -0,0 +1,12 @@ +/* The only macro that should be defined prior to inclusion of + elf64-e2k.c so as to prevent it from including elf64-target.h + before we redefine all other macros of interest. */ +#define TARGET_LITTLE_NAME "elf64-e2k-pm" +#include "elf64-e2k.c" + +#undef TARGET_LITTLE_SYM +#define TARGET_LITTLE_SYM e2k_pm_elf64_vec + +#include "elfxx-e2k-pm.h" + +#include "elf64-target.h" diff --git a/bfd/elf64-e2k-uclibc.c b/bfd/elf64-e2k-uclibc.c new file mode 100644 index 0000000000..eb0b0af3ab --- /dev/null +++ b/bfd/elf64-e2k-uclibc.c @@ -0,0 +1,16 @@ +/* The only macro that should be defined prior to inclusion of + elf64-e2k.c so as to prevent it from including elf64-target.h + before we redefine all other macros of interest. */ +#define TARGET_LITTLE_NAME "elf64-e2k-uclibc" +#include "elf64-e2k.c" + +#undef TARGET_LITTLE_SYM +#define TARGET_LITTLE_SYM e2k_uclibc_elf64_vec + +#include "elfxx-e2k-uclibc.h" + +#undef bfd_elf64_bfd_merge_private_bfd_data +#define bfd_elf64_bfd_merge_private_bfd_data \ + _bfd_e2k_uclibc_elf_merge_private_bfd_data + +#include "elf64-target.h" diff --git a/bfd/elf64-e2k.c b/bfd/elf64-e2k.c index 5e340f6a3f..545c60807b 100644 --- a/bfd/elf64-e2k.c +++ b/bfd/elf64-e2k.c @@ -100,6 +100,7 @@ static const struct elf_size_info elf64_e2k_size_info = { #define bfd_elf64_bfd_reloc_type_lookup _bfd_e2k_elf_reloc_type_lookup #define bfd_elf64_bfd_reloc_name_lookup _bfd_e2k_elf_reloc_name_lookup #define bfd_elf64_bfd_merge_private_bfd_data _bfd_e2k_elf_merge_private_bfd_data + #define bfd_elf64_mkobject _bfd_e2k_elf_mkobject #define bfd_elf64_bfd_link_hash_table_create _bfd_e2k_elf_link_hash_table_create #define bfd_elf64_bfd_final_link _bfd_e2k_elf_final_link @@ -134,10 +135,11 @@ static const struct elf_size_info elf64_e2k_size_info = { #define elf_backend_finish_dynamic_symbol _bfd_e2k_elf_finish_dynamic_symbol #define elf_backend_reloc_type_class _bfd_e2k_elf_reloc_type_class #define elf_backend_finish_dynamic_sections _bfd_e2k_elf_finish_dynamic_sections -#define elf_backend_post_process_headers _bfd_e2k_elf_post_process_headers +#define elf_backend_init_file_header _bfd_e2k_elf_init_file_header #define elf_backend_ignore_discarded_relocs _bfd_e2k_elf_ignore_discarded_relocs #define elf_backend_hide_symbol _bfd_e2k_elf_hide_symbol -#define elf_backend_object_p _bfd_e2k_elf_object_p +#define elf_backend_object_p _bfd_e2k_elf_object_p + #define elf_backend_setup_gnu_properties _bfd_e2k_elf_link_setup_gnu_properties /* Make tests employing `gc-sections' option PASS. I wonder if any backend- @@ -168,9 +170,12 @@ static const struct elf_size_info elf64_e2k_size_info = { #define elf_backend_r_none_info R_E2K_NONE +/* Let `bfd_elf_size_dynamic_sections ()' treat a missing PT_GNU_STACK as an + unexecutable one to be in line with the Kernel and glibc. */ +#define elf_backend_default_execstack 0 #define TARGET_LITTLE_SYM e2k_elf64_vec -#define TARGET_LITTLE_NAME "elf64-e2k" + #define ELF_ARCH bfd_arch_e2k #define ELF_MACHINE_CODE EM_MCST_ELBRUS @@ -180,8 +185,7 @@ static const struct elf_size_info elf64_e2k_size_info = { #define ELF_MAXPAGESIZE 0x1000 -/* Don't rush to set up BFD target vector if we are included on behalf of KPDA - target: some of the above definitions are going to be altered by it. */ -#ifndef TARGET_KPDA -#include "elf64-target.h" -#endif /* ! TARGET_KPDA */ +#ifndef TARGET_LITTLE_NAME +# define TARGET_LITTLE_NAME "elf64-e2k" +# include "elf64-target.h" +#endif diff --git a/bfd/elf64-sparc.c b/bfd/elf64-sparc.c index 8d352252b6..70f1d83e4d 100644 --- a/bfd/elf64-sparc.c +++ b/bfd/elf64-sparc.c @@ -657,6 +657,12 @@ elf64_sparc_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) flagword new_flags, old_flags; int new_mm, old_mm; + /* No matter whether the output BFD is ELF or not, check magic in the input + one provided that it is. */ + if (bfd_get_flavour (ibfd) == bfd_target_elf_flavour + && ! _bfd_sparc_elf_check_magic (ibfd)) + return FALSE; + if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour || bfd_get_flavour (obfd) != bfd_target_elf_flavour) return TRUE; @@ -677,8 +683,10 @@ elf64_sparc_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) { error = FALSE; + /* MCST extensions should be considered Sun- rather than HAL-compatible. + See the code below. */ #define EF_SPARC_ISA_EXTENSIONS \ - (EF_SPARC_SUN_US1 | EF_SPARC_SUN_US3 | EF_SPARC_HAL_R1) + (EF_SPARC_SUN_US1 | EF_SPARC_SUN_US3 | EF_SPARC_MCST | EF_SPARC_HAL_R1) if ((ibfd->flags & DYNAMIC) != 0) { @@ -694,12 +702,14 @@ elf64_sparc_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) /* Choose the highest architecture requirements. */ old_flags |= (new_flags & EF_SPARC_ISA_EXTENSIONS); new_flags |= (old_flags & EF_SPARC_ISA_EXTENSIONS); - if ((old_flags & (EF_SPARC_SUN_US1 | EF_SPARC_SUN_US3)) + if ((old_flags & (EF_SPARC_SUN_US1 | EF_SPARC_SUN_US3 + | EF_SPARC_MCST)) && (old_flags & EF_SPARC_HAL_R1)) { error = TRUE; _bfd_error_handler - (_("%pB: linking UltraSPARC specific with HAL specific code"), + (_("%pB: linking either UltraSPARC or MCST specific " + "with HAL specific code"), ibfd); } /* Choose the most restrictive memory ordering. */ @@ -970,6 +980,18 @@ const struct elf_size_info elf64_sparc_size_info = /* Section 5.2.4 of the ABI specifies a 256-byte boundary for the table. */ #define elf_backend_plt_alignment 8 +/* EIR-specific hacks. */ +#define bfd_elf64_bfd_link_add_symbols _bfd_sparc_elf_link_add_symbols +#define bfd_elf64_bfd_final_link _bfd_sparc_elf_final_link +#define elf_backend_ignore_discarded_relocs _bfd_sparc_elf_ignore_discarded_relocs +#define elf_backend_hide_symbol _bfd_sparc_elf_hide_symbol +#define bfd_elf64_write_object_contents _bfd_sparc_elf_write_object_contents + +/* Let `.magic' section be `SHT_NOTE'. */ +#define elf_backend_special_sections _bfd_sparc_elf_special_sections + +#define elf_backend_extern_protected_data 1 + #include "elf64-target.h" /* FreeBSD support */ diff --git a/bfd/elflink.c b/bfd/elflink.c index 998b72f228..c0b88119e8 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -1906,26 +1906,23 @@ _bfd_elf_add_default_symbol (bfd *abfd, if (hi->def_regular || ELF_COMMON_DEF_P (hi)) { + struct bfd_elf_version_tree *vertree = hi->verinfo.vertree; + /* If the undecorated symbol will have a version added by a script different to H, then don't indirect to/from the undecorated symbol. This isn't ideal because we may not yet have seen symbol versions, if given by a script on the command line rather than via --version-script. */ - if (hi->verinfo.vertree == NULL && info->version_info != NULL) + if (vertree == NULL && info->version_info != NULL) { bfd_boolean hide; - hi->verinfo.vertree + vertree = bfd_find_version_for_sym (info->version_info, hi->root.root.string, &hide); - if (hi->verinfo.vertree != NULL && hide) - { - (*bed->elf_backend_hide_symbol) (info, hi, TRUE); - goto nondefault; - } } - if (hi->verinfo.vertree != NULL - && strcmp (p + 1 + (p[1] == '@'), hi->verinfo.vertree->name) != 0) + if (vertree != NULL + && strcmp (p + 1 + (p[1] == '@'), vertree->name) != 0) goto nondefault; } @@ -9506,6 +9503,12 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec) free (sort); return 0; } + + /* FIXME: currently there's an unresolved issue on Sparc making me + occasionally allocate excessive space in `.rela.got', which is why + '>=' is temporarely used here instead of '=='. */ + BFD_ASSERT (o->size >= o->reloc_count * ext_size); + erel = o->contents; erelend = o->contents + o->size; p = sort + o->output_offset * opb / ext_size * sort_elt; @@ -10934,7 +10937,16 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd) /* We need to reverse-copy input .ctors/.dtors sections if they are placed in .init_array/.finit_array for output. */ - if (o->size > address_size + if ( +#if 1 + /* However, there's no point in doing so in E2K Protected + Mode. */ + (((elf_elfheader (input_bfd)->e_flags & 32 /* EF_E2K_PM */) + != 32 /* EF_E2K_PM */) + || (strstr (input_bfd->xvec->name, "e2k-pm") == NULL)) + && +#endif /* 0 */ + o->size > address_size && ((strncmp (o->name, ".ctors", 6) == 0 && strcmp (o->output_section->name, ".init_array") == 0) @@ -11197,7 +11209,14 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd) bfd_elf_discard_info rely on reloc offsets being ordered. */ irela->r_offset = last_offset; - irela->r_info = 0; + /* FIXME: I suppose that the original code setting + `r_info' to 0 is sure to lead for an invalid result not + only for E2K but for all targets with `R_xxx_NONE + != 0'. Moreover, it discards my attempts to setup + R_E2K_NONE instead of an original relocation against a + symbol coming from a discarded section in `_bfd_e2k_elf + _relocate_section ()'. */ + irela->r_info = bed->r_none_info; irela->r_addend = 0; continue; } @@ -14783,9 +14802,13 @@ _bfd_elf_copy_link_hash_symbol_type (bfd *abfd, void elf_append_rela (bfd *abfd, asection *s, Elf_Internal_Rela *rel) { + static const char zero_rel[sizeof (Elf_Internal_Rela)]; const struct elf_backend_data *bed = get_elf_backend_data (abfd); bfd_byte *loc = s->contents + (s->reloc_count++ * bed->s->sizeof_rela); BFD_ASSERT (loc + bed->s->sizeof_rela <= s->contents + s->size); + + BFD_ASSERT (memcmp (rel, zero_rel, sizeof (zero_rel)) != 0); + bed->s->swap_reloca_out (abfd, rel, loc); } diff --git a/bfd/elfxx-e2k-pm.c b/bfd/elfxx-e2k-pm.c new file mode 100644 index 0000000000..fafaf36d92 --- /dev/null +++ b/bfd/elfxx-e2k-pm.c @@ -0,0 +1,135 @@ +#include "sysdep.h" +#include "bfd.h" +#include "elf-bfd.h" +#include "elfxx-e2k.h" +#include "elfxx-e2k-pm.h" + +static bfd_boolean +segment_executable (struct elf_segment_map *seg) +{ + if (seg->p_flags_valid) + return (seg->p_flags & PF_X) != 0; + else + { + /* The p_flags value has not been computed yet, + so we have to look through the sections. */ + unsigned int i; + for (i = 0; i < seg->count; ++i) + if (seg->sections[i]->flags & SEC_CODE) + return TRUE; + } + return FALSE; +} + +/* Determine if this segment is eligible to receive the file and program + headers. It must be read-only and non-executable. + Its first section must start far enough past the page boundary to + allow space for the headers. */ +static bfd_boolean +segment_eligible_for_headers (struct elf_segment_map *seg, + bfd_vma minpagesize, bfd_vma sizeof_headers) +{ + unsigned int i; + if (seg->count == 0 || seg->sections[0]->lma % minpagesize < sizeof_headers) + return FALSE; + for (i = 0; i < seg->count; ++i) + { + if ((seg->sections[i]->flags & (SEC_CODE|SEC_READONLY)) != SEC_READONLY) + return FALSE; + } + return TRUE; +} + + +bfd_boolean +_bfd_e2k_pm_elf_modify_segment_map (bfd *abfd, struct bfd_link_info *info) +{ + const struct elf_backend_data *const bed = get_elf_backend_data (abfd); + struct elf_segment_map **m = &elf_seg_map (abfd); + struct elf_segment_map **first_load = NULL; + struct elf_segment_map **last_load = NULL; + bfd_boolean moved_headers = FALSE; + int sizeof_headers; + + if (info != NULL) + /* We're doing linking, so evalute SIZEOF_HEADERS as in a linker script. */ + sizeof_headers = bfd_sizeof_headers (abfd, info); + else + { + /* We're not doing linking, so this is objcopy or suchlike. + We just need to collect the size of the existing headers. */ + struct elf_segment_map *seg; + sizeof_headers = bed->s->sizeof_ehdr; + for (seg = *m; seg != NULL; seg = seg->next) + sizeof_headers += bed->s->sizeof_phdr; + } + + while (*m != NULL) + { + struct elf_segment_map *seg = *m; + + if (seg->p_type == PT_LOAD) + { + bfd_boolean executable = segment_executable (seg); + + /* First, we're just finding the earliest PT_LOAD. + By the normal rules, this will be the lowest-addressed one. + We only have anything interesting to do if it's executable. */ + last_load = m; + if (first_load == NULL) + { + if (!executable) + goto next; + first_load = m; + } + /* Now that we've noted the first PT_LOAD, we're looking for + the first non-executable PT_LOAD with a nonempty p_filesz. */ + else if (!moved_headers + && segment_eligible_for_headers (seg, bed->minpagesize, + sizeof_headers)) + { + /* This is the one we were looking for! + + First, clear the flags on previous segments that + say they include the file header and phdrs. */ + struct elf_segment_map *prevseg; + for (prevseg = *first_load; + prevseg != seg; + prevseg = prevseg->next) + if (prevseg->p_type == PT_LOAD) + { + prevseg->includes_filehdr = 0; + prevseg->includes_phdrs = 0; + } + + /* This segment will include those headers instead. */ + seg->includes_filehdr = 1; + seg->includes_phdrs = 1; + + moved_headers = TRUE; + } + } + + next: + m = &seg->next; + } + + if (first_load != last_load && moved_headers) + { + /* Now swap the first and last PT_LOAD segments' + positions in segment_map. */ + struct elf_segment_map *first = *first_load; + struct elf_segment_map *last = *last_load; + *first_load = first->next; + first->next = last->next; + last->next = first; + } + + return TRUE; +} + +bfd_boolean +_bfd_e2k_pm_elf_object_p (bfd *abfd) +{ + return _bfd_e2k_elf_object_p_1 (abfd, TRUE); +} diff --git a/bfd/elfxx-e2k-pm.h b/bfd/elfxx-e2k-pm.h new file mode 100644 index 0000000000..7d26a44fbd --- /dev/null +++ b/bfd/elfxx-e2k-pm.h @@ -0,0 +1,17 @@ +extern bfd_boolean _bfd_e2k_pm_elf_modify_segment_map + (bfd *, struct bfd_link_info *); + +extern bfd_boolean _bfd_e2k_pm_elf_object_p + (bfd *); + +#undef elf_backend_modify_segment_map +#define elf_backend_modify_segment_map _bfd_e2k_pm_elf_modify_segment_map + +#undef elf_backend_object_p +#define elf_backend_object_p _bfd_e2k_pm_elf_object_p + +/* The first Elf32_Addr GOT entry containing link-time "address" of `_DYNAMIC' + is followed by two 16 bytes long appropriately aligned descriptors containing + `struct link_map *' and `&_dl_fixup ()'. */ +#undef elf_backend_got_header_size +#define elf_backend_got_header_size 48 diff --git a/bfd/elfxx-e2k-uclibc.c b/bfd/elfxx-e2k-uclibc.c new file mode 100644 index 0000000000..98b1145318 --- /dev/null +++ b/bfd/elfxx-e2k-uclibc.c @@ -0,0 +1,12 @@ +#include "sysdep.h" +#include "bfd.h" +#include "elf-bfd.h" +#include "elfxx-e2k.h" +#include "elfxx-e2k-uclibc.h" + +bfd_boolean +_bfd_e2k_uclibc_elf_merge_private_bfd_data (bfd *ibfd, + struct bfd_link_info *info) +{ + return _bfd_e2k_elf_merge_private_bfd_data_1 (ibfd, info->output_bfd, TRUE); +} diff --git a/bfd/elfxx-e2k-uclibc.h b/bfd/elfxx-e2k-uclibc.h new file mode 100644 index 0000000000..48e442497a --- /dev/null +++ b/bfd/elfxx-e2k-uclibc.h @@ -0,0 +1,2 @@ +extern bfd_boolean _bfd_e2k_uclibc_elf_merge_private_bfd_data + (bfd *ibfd, struct bfd_link_info *info); diff --git a/bfd/elfxx-e2k.c b/bfd/elfxx-e2k.c index 31db08474a..0c56143ec8 100644 --- a/bfd/elfxx-e2k.c +++ b/bfd/elfxx-e2k.c @@ -30,19 +30,18 @@ /* In case we're on a 32-bit machine, construct a 64-bit "-1" value. */ #define MINUS_ONE (0xffffffffffffffffULL) - - -#define ABI_64_P(abfd) \ - (get_elf_backend_data (abfd)->s->elfclass == ELFCLASS64) +#define ELF64_P(abfd) (get_elf_backend_data (abfd)->s->elfclass == ELFCLASS64) #define ABI_PM_P(abfd) \ ((elf_elfheader (abfd)->e_flags & EF_E2K_PM) == EF_E2K_PM) +#define ABI_64_P(abfd) (ELF64_P (abfd) && ! ABI_PM_P (abfd)) + #define ELF_R_TYPE(abfd, i) \ - (ABI_64_P (abfd) ? ELF64_R_TYPE (i) : ELF32_R_TYPE (i)) + (ELF64_P (abfd) ? ELF64_R_TYPE (i) : ELF32_R_TYPE (i)) #define ELF_R_SYM(abfd, i) \ - (ABI_64_P (abfd) ? ELF64_R_SYM (i) : ELF32_R_SYM (i)) + (ELF64_P (abfd) ? ELF64_R_SYM (i) : ELF32_R_SYM (i)) /* REMINDER: this function has been originally implemented in commit @@ -189,6 +188,11 @@ static reloc_howto_type _bfd_e2k_elf_howto_table[] = bfd_elf_generic_reloc, "R_E2K_32_ABS", FALSE, 0x00000000, 0xffffffff, FALSE), + [R_E2K_32_DYNOPT] = + HOWTO (R_E2K_32_DYNOPT, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, + bfd_elf_generic_reloc, "R_E2K_32_DYNOPT", FALSE, + 0x00000000, 0xffffffff, FALSE), + [R_E2K_32_PC] = HOWTO (R_E2K_32_PC, 0, 2, 32, TRUE, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_E2K_32_PC", FALSE, @@ -204,11 +208,16 @@ static reloc_howto_type _bfd_e2k_elf_howto_table[] = bfd_elf_generic_reloc, "R_E2K_PL_GOT", FALSE, 0x00000000, 0xffffffff, FALSE), - [R_E2K_64_ABS] = + [R_E2K_64_ABS] = HOWTO (R_E2K_64_ABS, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_E2K_64_ABS", FALSE, 0x0000000000000000ULL, MINUS_ONE, FALSE), + [R_E2K_64_DYNOPT] = + HOWTO (R_E2K_64_DYNOPT, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, + bfd_elf_generic_reloc, "R_E2K_64_DYNOPT", FALSE, + 0x0000000000000000ULL, MINUS_ONE, FALSE), + [R_E2K_64_ABS_LIT] = HOWTO (R_E2K_64_ABS_LIT, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, _bfd_e2k_elf_64_abs_lit_reloc, "R_E2K_64_ABS_LIT", FALSE, @@ -224,6 +233,51 @@ static reloc_howto_type _bfd_e2k_elf_howto_table[] = _bfd_e2k_elf_64_pc_lit_reloc, "R_E2K_64_PC_LIT", FALSE, 0x0000000000000000ULL, MINUS_ONE, FALSE), + [R_E2K_32_JMP_SLOT] = + HOWTO (R_E2K_32_JMP_SLOT, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, + bfd_elf_generic_reloc, "R_E2K_32_JMP_SLOT", FALSE, + 0x00000000, 0xffffffff, FALSE), + + [R_E2K_32_COPY] = + HOWTO (R_E2K_32_COPY, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, + bfd_elf_generic_reloc, "R_E2K_32_COPY", FALSE, + 0x00000000, 0xffffffff, FALSE), + + [R_E2K_32_RELATIVE] = + HOWTO (R_E2K_32_RELATIVE, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, + bfd_elf_generic_reloc, "R_E2K_32_RELATIVE", FALSE, + 0x00000000, 0xffffffff, FALSE), + + [R_E2K_32_IRELATIVE] = + HOWTO (R_E2K_32_IRELATIVE, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, + bfd_elf_generic_reloc, "R_E2K_32_IRELATIVE", FALSE, + 0x00000000, 0xffffffff, FALSE), + + [R_E2K_64_JMP_SLOT] = + HOWTO (R_E2K_64_JMP_SLOT, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, + bfd_elf_generic_reloc, "R_E2K_64_JMP_SLOT", FALSE, + 0x0000000000000000ULL, MINUS_ONE, FALSE), + + [R_E2K_64_COPY] = + HOWTO (R_E2K_64_COPY, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, + bfd_elf_generic_reloc, "R_E2K_64_COPY", FALSE, + 0x0000000000000000ULL, MINUS_ONE, FALSE), + + [R_E2K_64_RELATIVE] = + HOWTO (R_E2K_64_RELATIVE, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, + bfd_elf_generic_reloc, "R_E2K_64_RELATIVE", FALSE, + 0x0000000000000000ULL, MINUS_ONE, FALSE), + + [R_E2K_64_RELATIVE_LIT] = + HOWTO (R_E2K_64_RELATIVE_LIT, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, + bfd_elf_generic_reloc, "R_E2K_64_RELATIVE_LIT", FALSE, + 0x0000000000000000ULL, MINUS_ONE, FALSE), + + [R_E2K_64_IRELATIVE] = + HOWTO (R_E2K_64_IRELATIVE, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, + bfd_elf_generic_reloc, "R_E2K_64_IRELATIVE", FALSE, + 0x0000000000000000ULL, MINUS_ONE, FALSE), + [R_E2K_TLS_GDMOD] = HOWTO (R_E2K_TLS_GDMOD, 0, 2, 32, FALSE, 0, complain_overflow_unsigned, bfd_elf_generic_reloc, "R_E2K_TLS_GDMOD", FALSE, 0, @@ -258,23 +312,50 @@ static reloc_howto_type _bfd_e2k_elf_howto_table[] = bfd_elf_generic_reloc, "R_E2K_TLS_32_DTPREL", FALSE, 0x00000000, 0xffffffff, FALSE), - [R_E2K_TLS_64_DTPREL] = + [R_E2K_TLS_64_DTPREL] = HOWTO (R_E2K_TLS_64_DTPREL, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_E2K_TLS_64_DTPREL", FALSE, 0x0000000000000000ULL, MINUS_ONE, FALSE), + /* These ones are not emitted by GAS but HOWTOs for them are required to + prevent GDB from barfing on them. */ + [R_E2K_TLS_32_DTPMOD] = + HOWTO (R_E2K_TLS_32_DTPMOD, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, + bfd_elf_generic_reloc, "R_E2K_TLS_32_DTPMOD", FALSE, + 0x00000000, 0xffffffff, FALSE), + + [R_E2K_TLS_64_DTPMOD] = + HOWTO (R_E2K_TLS_64_DTPMOD, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, + bfd_elf_generic_reloc, "R_E2K_TLS_64_DTPMOD", FALSE, + 0x0000000000000000ULL, MINUS_ONE, FALSE), + + [R_E2K_TLS_TPOFF32] = + HOWTO (R_E2K_TLS_TPOFF32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, + bfd_elf_generic_reloc, "R_E2K_TLS_TPOFF32", FALSE, + 0x00000000, 0xffffffff, FALSE), + + [R_E2K_TLS_TPOFF64] = + HOWTO (R_E2K_TLS_TPOFF64, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, + bfd_elf_generic_reloc, "R_E2K_TLS_TPOFF64", FALSE, + 0x0000000000000000ULL, MINUS_ONE, FALSE), + /* The next two howtos aren't used by BFD in fact, except for producing relocation dumps. Therefore, the fields are initialized in a rather random manner. I wonder, how `{src,dst}_mask' fields can be expressed for 128-bit items using the 64-bit `bfd_vma' type . . . */ - - [R_E2K_AP] = - HOWTO (R_E2K_AP, 0, 8, 128, FALSE, 0, complain_overflow_bitfield, + + /* Now that `struct reloc_howto_struct' has been packed and `size == 8' + (this value used to match `bfd_get_reloc_size () == 16') and `bitsize == + 128' can be no longer encoded, stupidly set these fileds to 0 for `R_E2K_ + {AP,PL}' and get ready to process these relocations specially wherever + needed. */ + [R_E2K_AP] = + HOWTO (R_E2K_AP, 0, 0, 0, FALSE, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_E2K_AP", FALSE, 0x0000000000000000ULL, MINUS_ONE, FALSE), - [R_E2K_PL] = - HOWTO (R_E2K_PL, 0, 8, 128, FALSE, 0, complain_overflow_bitfield, + [R_E2K_PL] = + HOWTO (R_E2K_PL, 0, 0, 0, FALSE, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_E2K_PL", FALSE, 0x0000000000000000ULL, MINUS_ONE, FALSE), @@ -422,6 +503,10 @@ _bfd_e2k_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, return &_bfd_e2k_elf_howto_table[R_E2K_AP]; case BFD_RELOC_E2K_PL: return &_bfd_e2k_elf_howto_table[R_E2K_PL]; + case BFD_RELOC_E2K_DYNOPT64: + return &_bfd_e2k_elf_howto_table[R_E2K_64_DYNOPT]; + case BFD_RELOC_E2K_DYNOPT32: + return &_bfd_e2k_elf_howto_table[R_E2K_32_DYNOPT]; default: break; } @@ -448,14 +533,258 @@ _bfd_e2k_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, return NULL; } + +/* These ones are set to values of the respective options. See my comments + in `elfxx-e2k.h' on why they are not placed into e2k link hash table. */ +static int e2k_ipd; +static int e2k_is_x86app; +static int e2k_is_4mpages; +static bfd_boolean arch_set_via_cmdline; +static bfd_boolean restrict_to_arch; +static bfd_boolean relaxed_e2k_machine_check; +static bfd_boolean output_new_e_machine = TRUE; +bfd_boolean simulating_mode; +static bfd_boolean pack_cud_gd; + +static int link_mixed_eir_phase; + +bfd_boolean e2k_dsp_linux_mode; + + +struct cud_gd_range +{ + bfd_vma min; + bfd_vma max; + bfd_vma align; + bfd_signed_vma delta; + /* This field should be of no use except for during the initialization + of htab->ranges[]. Consider eliminating it. */ + bfd_boolean in_cud; +}; + +static int +compare_cud_gd_ranges (const void *a, const void *b) +{ + const struct cud_gd_range *first = (const struct cud_gd_range *) a; + const struct cud_gd_range *second = (const struct cud_gd_range *) b; + + /* Taking into account that the ranges are not allowed to overlap (at least + at present) which is going to be checked during the initialization of + htab->ranges[] below, just use MIN field to order them. */ + + return first->min < second->min ? -1 : (first->min > second->min ? 1 : 0); +} + +#ifdef HAVE_e2k_elf64_vec +bfd_vma +orig_offset_in_cud (struct bfd_link_info *info, bfd_vma offset) +{ + struct _bfd_e2k_elf_link_hash_table *htab = _bfd_e2k_elf_hash_table (info); + + if (! ABI_PM_P (htab->elf.dynobj) + || htab->ranges == NULL) + return offset; + + int i; + struct cud_gd_range *ranges = htab->ranges; + for (i = 0; i < htab->ranges_num; i++) + { + if (! ranges[i].in_cud) + continue; + + bfd_vma orig_off = offset - ranges[i].delta; + if (orig_off >= ranges[i].min && orig_off < ranges[i].max) + return orig_off; + } + + return offset; +} +#endif + +#ifndef HAVE_e2k_elf64_vec +static +#endif +bfd_vma +adjust_offset_in_cud_gd (struct bfd_link_info *info, bfd_vma offset) +{ + int i; + struct _bfd_e2k_elf_link_hash_table *htab; + struct cud_gd_range *ranges; + + /* Zero offset corresponds to NULL both in CUD and GD. It's probably the + only valid offset not belonging to any of PT_LOAD segments. */ + if (offset == 0) + return 0; + + if (! pack_cud_gd) + return offset; + + htab = _bfd_e2k_elf_hash_table (info); + + if (! ABI_PM_P (htab->elf.dynobj)) + return offset; + + if (htab->ranges == NULL) + { + struct elf_segment_map *m; + Elf_Internal_Phdr *phdrs = elf_tdata (info->output_bfd)->phdr; + Elf_Internal_Phdr *p; + int num = 0; + bfd_vma max_page_aligned; + bfd_vma cud_size, gd_size; + + for (m = elf_seg_map (info->output_bfd), p = phdrs; m != NULL; + m = m->next, p++) + { + if (p->p_type == PT_LOAD) + num++; + } + + ranges = (struct cud_gd_range *) bfd_alloc (htab->elf.dynobj, + (sizeof (struct cud_gd_range) + * num)); + + /* FIXME ... */ + if (ranges == NULL) + { + /* Hopefully this will make the linkage fail. */ + _bfd_error_handler (_("allocation of address ranges for CUD and GD " + "failed")); + /* There's no point in trying anymore. */ + pack_cud_gd = FALSE; + return offset; + } + + for (m = elf_seg_map (info->output_bfd), p = phdrs, i = 0; m != NULL; + m = m->next, p++) + { + if (p->p_type == PT_LOAD) + { + if (p->p_align < 0x1000 + || ((p->p_vaddr - p->p_offset) & (p->p_align - 1)) != 0) + { + _bfd_error_handler (_("inappropriately aligned segments " + "cannot be packed")); + pack_cud_gd = FALSE; + return offset; + } + + ranges[i].min = p->p_vaddr; + ranges[i].max = p->p_vaddr + p->p_memsz; + ranges[i].align = p->p_align; + ranges[i].in_cud = (p->p_flags & PF_X) ? TRUE : FALSE; + i++; + } + } + + qsort (ranges, num, sizeof (struct cud_gd_range), compare_cud_gd_ranges); + + cud_size = gd_size = 0; + max_page_aligned = 0; + for (i = 0; i < num; i++) + { + bfd_vma min_page_aligned = ranges[i].min & ~(ranges[i].align - 1); + bfd_vma b, r, pos; + + /* MAX_PAGE_ALIGNED corresponds to the preceding segment in this + comparison, of course. */ + if (min_page_aligned < max_page_aligned) + { + _bfd_error_handler (_("compactification of CUD/GD segments " + "with overlapping pages is not supported")); + pack_cud_gd = FALSE; + return offset; + } + + max_page_aligned = (ranges[i].max + 0xfffULL) & ~(0xfffULL); + + + if (ranges[i].in_cud) + pos = cud_size; + else + pos = gd_size; + + pos = (pos + 0xfffULL) & ~0xfffULL; + r = ranges[i].min & (ranges[i].align - 1); + b = (pos + ranges[i].align - (r + 1)) / ranges[i].align; + pos = b * ranges[i].align + r; + + ranges[i].delta = pos - ranges[i].min; + pos += ranges[i].max - ranges[i].min; + + if (ranges[i].in_cud) + cud_size = pos; + else + gd_size = pos; + } + + htab->ranges_num = num; + htab->ranges = ranges; + } + else + ranges = htab->ranges; + + /* FIXME: consider optimizing this search. */ + for (i = 0; i < htab->ranges_num; i++) + { + if (offset < ranges[i].min) + break; + + if (offset >= ranges[i].max) + continue; + + return offset + ranges[i].delta; + } + + /* Give a chance to an "_end"-like symbol formally lying one byte beyond + its range. */ + int j; + j = htab->ranges_num - 1; + if (offset == ranges[j].max) + return offset + ranges[j].delta; + + /* If the trailing address range in CUD (GD) didn't match look for another + trailing range GD (CUD) respectively. */ + bfd_boolean in_cud = !ranges[j].in_cud; + for (i = j - 1; i >= 0; i--) + { + if (ranges[i].in_cud == in_cud) + { + if (offset == ranges[i].max) + return offset + ranges[i].delta; + else + /* No point in trying any longer as we have checked trailing ranges + both in CUD and GD. */ + break; + } + } + + + + /* FIXME: this may happen for ABS symbols. */ +#if 0 + _bfd_error_handler (_("address 0x%lx doesn't correspond to any " + "PT_LOAD segment and thus can't be reliably " + "compactified"), offset); +#endif /* 0 */ + return offset; +} + +#define WSZ(wsz) \ + /* LTS0 */ (0x00000010 | (wsz << 5)) + /* A pattern for Protected Mode self-init function header. */ static const unsigned int selfinit_header[] = { /* 0: */ /* HS */ 0x00008011, - /* CS1 */ 0x00000000, /* setwd wsz = 0x4, nfx = 0x1 */ + /* CS1 */ 0x00000000, /* setwd wsz = 0x{4,8}, nfx = 0x1 */ /* LTS1 */ 0x00000000, - /* LTS0 */ 0x00000090, +#ifndef NEW_PM_ABI + /* LTS0 */ WSZ (0x4) +#else /* defined NEW_PM_ABI */ + /* LTS0 */ WSZ (0x8), +#endif /* defined NEW_PM_ABI */ }; @@ -567,13 +896,17 @@ add_selfinit_ap (struct bfd_link_info *info, bfd_vma relocation, bfd_vma size, bfd_vma addend, - bfd_vma targ_off) + bfd_vma targ_off, + const char *name ATTRIBUTE_UNUSED) { bfd *output_bfd = info->output_bfd; struct _bfd_e2k_elf_link_hash_table *htab = _bfd_e2k_elf_hash_table (info); unsigned char *ptr; unsigned int i; + // printf ("%s: AP\n", name); + // fflush (NULL); + BFD_ASSERT (htab->selfinit_off + sizeof (selfinit_ap) + sizeof (selfinit_tail) <= htab->selfinit->size); add_selfinit_header (info); @@ -612,7 +945,8 @@ add_selfinit_ap (struct bfd_link_info *info, bfd_put_32 (output_bfd, addq[i], ptr + 4 + 4 * i); } else - bfd_put_32 (output_bfd, relocation, ptr + 12); + bfd_put_32 (output_bfd, adjust_offset_in_cud_gd (info, relocation), + ptr + 12); if (relocation == 0 || size == 0) { @@ -629,7 +963,7 @@ add_selfinit_ap (struct bfd_link_info *info, /* Customize the addend to be added to the obtained %qr0. */ bfd_put_32 (output_bfd, addend, ptr + 52); - bfd_put_32 (output_bfd, targ_off, ptr + 68); + bfd_put_32 (output_bfd, adjust_offset_in_cud_gd (info, targ_off), ptr + 68); htab->selfinit_off += sizeof (selfinit_ap); add_selfinit_tail (info); @@ -638,13 +972,17 @@ add_selfinit_ap (struct bfd_link_info *info, static void add_selfinit_pl (struct bfd_link_info *info, bfd_vma relocation, - bfd_vma targ_off) + bfd_vma targ_off, + const char *name ATTRIBUTE_UNUSED) { bfd *output_bfd = info->output_bfd; struct _bfd_e2k_elf_link_hash_table *htab = _bfd_e2k_elf_hash_table (info); unsigned char *ptr; unsigned int i; + // printf ("%s: PL\n", name); + // fflush (NULL); + BFD_ASSERT (htab->selfinit_off + sizeof (selfinit_pl) + sizeof (selfinit_tail) <= htab->selfinit->size); add_selfinit_header (info); @@ -679,34 +1017,17 @@ add_selfinit_pl (struct bfd_link_info *info, bfd_put_32 (output_bfd, addd, ptr + 12); } else - bfd_put_32 (output_bfd, relocation, ptr + 20); + { + bfd_put_32 (output_bfd, adjust_offset_in_cud_gd (info, relocation), + ptr + 20); + } - bfd_put_32 (output_bfd, targ_off, ptr + 36); + bfd_put_32 (output_bfd, adjust_offset_in_cud_gd (info, targ_off), ptr + 36); htab->selfinit_off += sizeof (selfinit_pl); add_selfinit_tail (info); } - - - -/* These ones are set to values of the respective options. See my comments - in `elfxx-e2k.h' on why they are not placed into e2k link hash table. */ -static int e2k_ipd; -static int e2k_is_x86app; -static int e2k_is_4mpages; -static bfd_boolean arch_set_via_cmdline; -static bfd_boolean restrict_to_arch; -static bfd_boolean relaxed_e2k_machine_check; -static bfd_boolean output_new_e_machine = TRUE; -bfd_boolean simulating_mode; - -static int link_mixed_eir_phase; - -bfd_boolean e2k_dsp_linux_mode; - - - void _bfd_e2k_elf_after_parse (int phase) { @@ -726,7 +1047,8 @@ _bfd_e2k_elf_after_open (int ipd, bfd_boolean restrict_to, bfd_boolean machine_check, bfd_boolean new_e_machine, - bfd_boolean simulate) + bfd_boolean simulate, + bfd_boolean pack_cg) { /* Note that in S-records test INFO->HTAB turns out to be zero somehow when this function gets called . . . */ @@ -739,6 +1061,7 @@ _bfd_e2k_elf_after_open (int ipd, relaxed_e2k_machine_check = machine_check; output_new_e_machine = new_e_machine; simulating_mode = simulate; + pack_cud_gd = pack_cg; } static bfd_boolean @@ -755,7 +1078,7 @@ check_magic (bfd *abfd, asection *magic_sec) data = xmalloc (magic_sec->size); if (! bfd_get_section_contents (abfd, magic_sec, data, 0, magic_sec->size)) { - _bfd_error_handler (_("%B: cannot read contents of section %A\n"), + _bfd_error_handler (_("%pB: cannot read contents of section %pA\n"), abfd, magic_sec); } @@ -790,7 +1113,7 @@ decorated_arch_name (bfd *abfd) /* FIXME: it's too early to check `hdr->e_machine == EM_MCST_ELBRUS' for OBFD here, since it may have not been set up so far. */ bfd_boolean fi = (hdr->e_flags & EF_E2K_INCOMPAT) != 0; - unsigned long mach = abfd->arch_info->mach / 3; + unsigned long mach = abfd->arch_info->mach / 4; switch (mach) { @@ -805,22 +1128,36 @@ decorated_arch_name (bfd *abfd) case bfd_mach_e2k_ev4: return fi ? "forward incompatible elbrus-v4" : "elbrus-v4"; case bfd_mach_e2k_ev5: - return fi ? "forward incompatible elbrus-v5" : "elbrus-v5"; + return fi ? "elbrus-8c2" : "elbrus-v5"; case bfd_mach_e2k_ev6: return fi ? "forward incompatible elbrus-v6" : "elbrus-v6"; case bfd_mach_e2k_8c: return "elbrus-8c"; case bfd_mach_e2k_1cplus: return "elbrus-1c+"; + case bfd_mach_e2k_12c: + return "elbrus-12c"; + case bfd_mach_e2k_16c: + return "elbrus-16c"; + case bfd_mach_e2k_2c3: + return "elbrus-2c3"; default: BFD_ASSERT (0); return NULL; } } +static const char * +bitness (unsigned long mach) +{ + static const char *names[] = {"64-bit", "32-bit", "PM", "any"}; + return names[mach % 4]; +} + + bfd_boolean _bfd_e2k_elf_merge_private_bfd_data_1 (bfd *ibfd, bfd *obfd, - bfd_boolean protected_mode ATTRIBUTE_UNUSED) + bfd_boolean uclibc_output ATTRIBUTE_UNUSED) { unsigned long imach, omach; int incompatible_input; @@ -840,7 +1177,9 @@ _bfd_e2k_elf_merge_private_bfd_data_1 (bfd *ibfd, bfd *obfd, e8c, e1cplus, ev5, - ev6, + e12c, + e16c, + e2c3, /* The related bit in mask stands for "all future processor models". */ ev7 }; @@ -849,6 +1188,7 @@ _bfd_e2k_elf_merge_private_bfd_data_1 (bfd *ibfd, bfd *obfd, can be executed. */ #define AT(p) (1L << p) +#define AT_ev6 (AT (e12c) | AT (e16c) | AT (e2c3)) /* This is a machine compatibility table. It provides the mask of machines an object file compiled (or linked) for a given machine (specified by the row) @@ -858,7 +1198,7 @@ _bfd_e2k_elf_merge_private_bfd_data_1 (bfd *ibfd, bfd *obfd, static const unsigned long mask[][2] = { [bfd_mach_e2k_generic] = {(AT (ev1) | AT (ev2) | AT (ev3) | AT (e8c) - | AT (e1cplus) | AT (ev5) | AT (ev6) + | AT (e1cplus) | AT (ev5) | AT_ev6 | AT (ev7)), (AT (ev1) | AT (ev2))}, @@ -866,29 +1206,65 @@ _bfd_e2k_elf_merge_private_bfd_data_1 (bfd *ibfd, bfd *obfd, AT (ev1)}, [bfd_mach_e2k_ev2] = {(AT (ev2) | AT (ev3) | AT (e8c) | AT (e1cplus) - | AT (ev5) | AT (ev6) | AT (ev7)), + | AT (ev5) | AT_ev6 | AT (ev7)), (AT (ev2))}, [bfd_mach_e2k_ev3] = {(AT (ev3) | AT (e8c) | AT (e1cplus) | AT (ev5) - | AT (ev6) | AT (ev7)), + | AT_ev6 | AT (ev7)), AT (ev3)}, - [bfd_mach_e2k_ev4] = {(AT (e8c) | AT (e1cplus) | AT (ev5) | AT (ev6) + [bfd_mach_e2k_ev4] = {(AT (e8c) | AT (e1cplus) | AT (ev5) | AT_ev6 | AT (ev7)), (AT (e8c) | AT (e1cplus))}, - [bfd_mach_e2k_ev5] = {(AT (ev5) | AT (ev6) | AT (ev7)), + [bfd_mach_e2k_ev5] = {(AT (ev5) | AT_ev6 | AT (ev7)), AT (ev5)}, - [bfd_mach_e2k_ev6] = {(AT (ev6) | AT (ev7)), - AT (ev6)}, + [bfd_mach_e2k_ev6] = {(AT_ev6 | AT (ev7)), + AT_ev6}, [bfd_mach_e2k_8c] = {AT (e8c), AT (e8c)}, [bfd_mach_e2k_1cplus] = {AT (e1cplus), - AT (e1cplus)} + AT (e1cplus)}, + + [bfd_mach_e2k_12c] = {AT (e12c), + AT (e12c)}, + + [bfd_mach_e2k_16c] = {AT (e16c), + AT (e16c)}, + + [bfd_mach_e2k_2c3] = {AT (e2c3), + AT (e2c3)} }; + { + static bfd_boolean first_ibfd_saved = TRUE; + bfd_boolean res = TRUE, first_ibfd = first_ibfd_saved; + int iuclibc = + elf_known_obj_attributes (ibfd)[OBJ_ATTR_GNU][Tag_GNU_E2K_UCLIBC].i; + + /* Next time `first_ibfd' will be set to FALSE. */ + first_ibfd_saved = FALSE; + + if ((uclibc_output && iuclibc == 0) + || (! uclibc_output && iuclibc != 0)) + { + _bfd_error_handler (_("%s input object %pB is not compatible with " + "%s output"), + uclibc_output ? "GNU" : "uclibc", + ibfd, + uclibc_output ? "uclibc" : "GNU"); + res = FALSE; + } + + if (uclibc_output && first_ibfd) + bfd_elf_add_obj_attr_int (obfd, OBJ_ATTR_GNU, Tag_GNU_E2K_UCLIBC, 1); + + if (! res) + return FALSE; + } + if (bfd_get_flavour (ibfd) == bfd_target_elf_flavour && getenv ("MAGIC")) { asection *magic_sec; @@ -901,7 +1277,7 @@ _bfd_e2k_elf_merge_private_bfd_data_1 (bfd *ibfd, bfd *obfd, magic_sec = bfd_get_section_by_name (ibfd, ".magic"); if (magic_sec == NULL) { - _bfd_error_handler (_("Input object %B doesn't have a .magic " + _bfd_error_handler (_("Input object %pB doesn't have a .magic " "section"), ibfd); return FALSE; } @@ -918,15 +1294,11 @@ _bfd_e2k_elf_merge_private_bfd_data_1 (bfd *ibfd, bfd *obfd, if (! res) { - _bfd_error_handler (_("Input object %B contains wrong MAGIC "), + _bfd_error_handler (_("Input object %pB contains wrong MAGIC "), ibfd); return FALSE; } - } - - /* I don't actually want to check anything in relaxed case. */ - if (relaxed_e2k_machine_check) - return TRUE; + } /* My further checks are meaningful if both input and output files are ELFs only. Well, probably the check for `obfd' is redundant, because @@ -945,6 +1317,69 @@ _bfd_e2k_elf_merge_private_bfd_data_1 (bfd *ibfd, bfd *obfd, ihdr = elf_elfheader (ibfd); ohdr = elf_elfheader (obfd); + imach = ibfd->arch_info->mach; + omach = obfd->arch_info->mach; + + /* We shouldn't find ourselves here if `bfd_e2k_compatible ()' failed, + should we? */ + if (imach % 4 != omach % 4) + { + _bfd_error_handler + (_("%s input file `%pB' is incompatible with %s output"), + bitness (imach), ibfd, bitness (omach)); + return FALSE; + } + + /* Input object file with "any bitness" mach should not appear in + principle. */ + BFD_ASSERT (imach % 4 != 3); + + if ((ihdr->e_ident[EI_OSABI] == ELFOSABI_KPDA + || get_elf_backend_data (obfd)->elf_osabi == ELFOSABI_KPDA) + && ihdr->e_ident[EI_OSABI] != get_elf_backend_data (obfd)->elf_osabi) + { + bfd_boolean kpda_input = ihdr->e_ident[EI_OSABI] == ELFOSABI_KPDA; + const char *linux_abi = "Linux"; + const char *kpda_abi = "KPDA"; + + _bfd_error_handler + (_("%pB: input with `%s' ABI cannot be processed by `%s' target"), + ibfd, kpda_input ? kpda_abi : linux_abi, + kpda_input ? linux_abi : kpda_abi); + return FALSE; + } + + /* Shared objects' machine shouldn't have an impact on the one eventually set + for OBFD as they can be very different from the ones used at runtime in + this respect. The above tests not allowing for the mixture of different + ABIs and GNU, Uclibc and KPDA object files seem to be reasonable because + the user should NOT allow for such mixtures at link-time. */ + if ((ibfd->flags & DYNAMIC) != 0) + return TRUE; + + /* Now that we are guaranteed that input and output bfds have the same mode, + migrate to e2k machine masks defined in `MCST E2K' section of + `bfd/archures.c'. */ + imach /= 4; + omach /= 4; + + /* Explicitly prohibit the linkage of "generic" and "elbrus-v1" input ELFs as + proposed in Bug #96498, Comment #11 so as to make it impossible in + principle. */ + if (imach == bfd_mach_e2k_generic || imach == bfd_mach_e2k_ev1) + { + _bfd_error_handler + (_("%pB: link of `%s' input files is no longer supported"), + ibfd, + imach == bfd_mach_e2k_generic ? "generic" : "elbrus-v1"); + return FALSE; + } + + /* Further machine compatibility checks should not be performed in + `--relaxed-e2k-machine' mode. */ + if (relaxed_e2k_machine_check) + return TRUE; + /* Is the currently considered input file incompatible? */ incompatible_input = (((ihdr->e_machine == EM_MCST_ELBRUS) && (ihdr->e_flags & EF_E2K_INCOMPAT)) @@ -955,9 +1390,9 @@ _bfd_e2k_elf_merge_private_bfd_data_1 (bfd *ibfd, bfd *obfd, { if (incompatible_input ) { - _bfd_error_handler (_("New style object %B with `EF_E2K_INCOMPAT' " + _bfd_error_handler (_("New style object %pB with `EF_E2K_INCOMPAT' " "flag set cannot be linked into an old " - "style %B"), ibfd, obfd); + "style %pB"), ibfd, obfd); return FALSE; } @@ -973,41 +1408,12 @@ _bfd_e2k_elf_merge_private_bfd_data_1 (bfd *ibfd, bfd *obfd, } - - imach = ibfd->arch_info->mach; - omach = obfd->arch_info->mach; - - /* We shouldn't find ourselves here if `bfd_e2k_compatible ()' failed, - should we? */ - BFD_ASSERT (imach % 3 == omach % 3); - - if ((ihdr->e_ident[EI_OSABI] == ELFOSABI_KPDA - || get_elf_backend_data (obfd)->elf_osabi == ELFOSABI_KPDA) - && ihdr->e_ident[EI_OSABI] != get_elf_backend_data (obfd)->elf_osabi) - { - bfd_boolean kpda_input = ihdr->e_ident[EI_OSABI] == ELFOSABI_KPDA; - const char *linux_abi = "Linux"; - const char *kpda_abi = "KPDA"; - - _bfd_error_handler - (_("%B: input with `%s' ABI cannot be processed by `%s' target"), - ibfd, kpda_input ? kpda_abi : linux_abi, - kpda_input ? linux_abi : kpda_abi); - return FALSE; - } - - /* Now that we are guaranteed that input and output bfds have the same mode, - migrate to e2k machine masks defined in `MCST E2K' section of - `bfd/archures.c'. */ - imach /= 3; - omach /= 3; - /* Provided that `--restrict-to-arch OUTPUT_ARCH' has been specified, an input file's architecture should exactly match OUTPUT_ARCH. */ if (restrict_to_arch && imach != omach) { _bfd_error_handler - (_("input file `%B' of `%s' architecture does not match " + (_("input file `%pB' of `%s' architecture does not match " "`%s' specified via `--restrict-to-arch' option"), ibfd, decorated_arch_name (ibfd), decorated_arch_name (obfd)); return FALSE; @@ -1029,7 +1435,7 @@ _bfd_e2k_elf_merge_private_bfd_data_1 (bfd *ibfd, bfd *obfd, something different (e.g. the user wants E3S while the combination of input files makes us choose E2S). */ if (arch_set_via_cmdline - && omach != mask[obfd->arch_info->mach / 3][incompatible_output]) + && omach != mask[obfd->arch_info->mach / 4][incompatible_output]) omach = 0; if (omach != 0) @@ -1054,8 +1460,8 @@ _bfd_e2k_elf_merge_private_bfd_data_1 (bfd *ibfd, bfd *obfd, BFD_ASSERT (i < sizeof (mask) / sizeof (mask[0])); - i *= 3; - i += obfd->arch_info->mach % 3; + i *= 4; + i += obfd->arch_info->mach % 4; if (obfd->arch_info->mach != (unsigned long) i) bfd_set_arch_mach (obfd, bfd_arch_e2k, (unsigned long) i); @@ -1064,7 +1470,7 @@ _bfd_e2k_elf_merge_private_bfd_data_1 (bfd *ibfd, bfd *obfd, } _bfd_error_handler - (_("input file `%B' of `%s' architecture is incompatible " + (_("input file `%pB' of `%s' architecture is incompatible " "with `%s' output"), ibfd, decorated_arch_name (ibfd), decorated_arch_name (obfd)); @@ -1433,6 +1839,7 @@ static const unsigned int plt32_got_pic_header[] = /* ipd 2 */ }; +#define PLT32_GOT_PIC_HEADER_NOP_OFFSET 0x10 #define PLT32_GOT_PIC_LINK_MAP_LD_OFFSET 0x24 #define PLT32_GOT_PIC_DL_FIXUP_LD_OFFSET 0x20 #define PLT32_GOT_PIC_HEADER_SIZE sizeof (plt32_got_pic_header) @@ -1467,6 +1874,7 @@ static const unsigned int plt32_got_non_pic_header[] = /* ipd 2 */ }; +#define PLT32_GOT_NON_PIC_HEADER_NOP_OFFSET 0x0 #define PLT32_GOT_NON_PIC_LINK_MAP_LD_OFFSET 0xc #define PLT32_GOT_NON_PIC_HEADER_SIZE sizeof (plt32_got_non_pic_header) @@ -1490,6 +1898,7 @@ static const unsigned int plt32_got_pic_primary_entry[] = /* ipd 2 */ }; +#define PLT32_GOT_PIC_ENTRY_NOP_OFFSET 0x18 #define PLT32_GOT_PIC_TARGET_LD_OFFSET 0x24 #define PLT32_GOT_PIC_PRIMARY_ENTRY_SIZE sizeof (plt32_got_pic_primary_entry) @@ -1515,6 +1924,7 @@ static const unsigned int plt32_got_non_pic_primary_entry[] = }; +#define PLT32_GOT_NON_PIC_ENTRY_NOP_OFFSET 0x0 #define PLT32_GOT_NON_PIC_TARGET_LD_OFFSET 0x10 #define PLT32_GOT_NON_PIC_PRIMARY_ENTRY_SIZE sizeof (plt32_got_non_pic_primary_entry) @@ -1533,13 +1943,41 @@ build_plt_entry (struct bfd_link_info *info, asection *sgotplt = htab->elf.sgotplt; unsigned char *plt_literal = splt->contents + offset + htab->plt_got_target_ld_offset; + unsigned long omach = bfd_get_mach (output_bfd) / 4;; + + /* Until support for specific elbrus-v6 machines has been added I can check + it this way. Note that `>= 6' can't be used here because specific machines + (say, elbrus-{8c,1c+} for elbrus-v4) are marked with numbers exceeding the + maximal possible iset version. */ + /* Take into account that delay between load and its consumer has been + increased from 3 to 5 ticks starting from elbrus-v6 (see Bug #112004, + Comment #8). */ + unsigned int nops = ((omach == bfd_mach_e2k_ev6 + || omach == bfd_mach_e2k_12c + || omach == bfd_mach_e2k_16c + || omach == bfd_mach_e2k_2c3) ? 4 : 2); + + unsigned int hs_nop = + htab->plt_got_primary_entry[htab->plt_got_entry_nop_offset / 4]; + + for (i = 0; i < htab->plt_got_primary_entry_size / 4; i++) bfd_put_32 (output_bfd, htab->plt_got_primary_entry[i], (splt->contents + offset + 4 * i)); - slot_addr = (sgotplt->output_section->vma + sgotplt->output_offset - + gotplt_offset); + /* Adjust HS.nop according to the aforesaid. */ + hs_nop = (hs_nop & 0xfffffc7fu) | (nops << 7); + bfd_put_32 (output_bfd, hs_nop, + (htab->elf.splt->contents + + offset + + htab->plt_got_entry_nop_offset)); + + + slot_addr = adjust_offset_in_cud_gd (info, + (sgotplt->output_section->vma + + sgotplt->output_offset + + gotplt_offset)); if (! ABI_PM_P (htab->elf.dynobj) && bfd_link_pic (info)) { @@ -1577,7 +2015,8 @@ static void build_secondary_plt_entry (struct bfd_link_info *info, bfd_vma offset, bfd_vma gotplt_offset, - bfd_vma *r_offset) + bfd_vma *r_offset, + const char *name) { unsigned int i; struct _bfd_e2k_elf_link_hash_table *htab = _bfd_e2k_elf_hash_table (info); @@ -1619,7 +2058,8 @@ build_secondary_plt_entry (struct bfd_link_info *info, (splt->output_section->vma + splt->output_offset + offset), (sgotplt->output_section->vma + sgotplt->output_offset - + gotplt_offset)); + + gotplt_offset), + name); } } @@ -1665,6 +2105,7 @@ static const unsigned int plt64_got_pic_header[] = }; +#define PLT64_GOT_PIC_HEADER_NOP_OFFSET 0x10 #define PLT64_GOT_PIC_LINK_MAP_LD_OFFSET 0x24 #define PLT64_GOT_PIC_DL_FIXUP_LD_OFFSET 0x20 #define PLT64_GOT_PIC_HEADER_SIZE sizeof (plt64_got_pic_header) @@ -1700,6 +2141,7 @@ static const unsigned int plt64_got_non_pic_header[] = }; +#define PLT64_GOT_NON_PIC_HEADER_NOP_OFFSET 0x0 #define PLT64_GOT_NON_PIC_LINK_MAP_LD_OFFSET 0x10 #define PLT64_GOT_NON_PIC_HEADER_SIZE sizeof (plt64_got_non_pic_header) @@ -1724,6 +2166,7 @@ static const unsigned int plt64_got_pic_primary_entry[] = /* ipd 2 */ }; +#define PLT64_GOT_PIC_ENTRY_NOP_OFFSET 0x18 #define PLT64_GOT_PIC_TARGET_LD_OFFSET 0x24 #define PLT64_GOT_PIC_PRIMARY_ENTRY_SIZE sizeof (plt64_got_pic_primary_entry) @@ -1749,182 +2192,223 @@ static const unsigned int plt64_got_non_pic_primary_entry[] = }; +#define PLT64_GOT_NON_PIC_ENTRY_NOP_OFFSET 0x0 #define PLT64_GOT_NON_PIC_TARGET_LD_OFFSET 0xc #define PLT64_GOT_NON_PIC_PRIMARY_ENTRY_SIZE sizeof (plt64_got_non_pic_primary_entry) +#define MOVTD_TARGET(ind) \ + /* HS */ 0x04000001, \ + /* ALS0 */ (0x61c080d1 | (ind << 8)) /* movtd,0 %dr{ind}, %ctpr1 */ + +#define LOAD_LINK_MAP_DL_FIXUP(reg1, reg2) \ + /* HS */ 0xb6d00034, \ + /* ALS0 */ (0x79c0d880 | reg1), /* ldgdq,0 0x0, _f32s,_lts0 0x12345678, %qr{reg1} */ \ + /* ALS2 */ (0x79c0d880 | (reg1 + 1)), \ + /* ALS3 */ (0x79d0d880 | reg2), /* ldgdq,3 0x10, _f32s,_lts0 0x12345678, %qr{reg2} */ \ + /* ALS5 */ (0x79d0d880 | (reg2 + 1)), \ + /* ALES03*/ 0x01c001c0, \ + /* LTS1 */ 0x00000000, \ + /* LTS0 */ 0x12345678 + +#define MOVTQ_PAIR(src, dst) \ + /* HS */ 0x6db00034, \ + /* ALS0 */ (0x57c08080 | ((src + 0) << 8) | (dst + 0)), /* movtq,0 %qr{src}, %qr{dst} */ \ + /* ALS1 */ (0x57c08080 | ((src + 1) << 8) | (dst + 1)), \ + /* ALS3 */ (0x57c08080 | ((src + 2) << 8) | (dst + 2)), /* movtq,3 %qr{src+2}, %qr{dst+2} */ \ + /* ALS4 */ (0x57c08080 | ((src + 3) << 8) | (dst + 3)), \ + /* ALES */ 0x01c001c0, \ + /* ALES */ 0x01c001c0, \ + /* LTS0 */ 0x00000000 + + + +#define CALL_WBS(wbs) \ + /* CS1 */ (0x50000000 | wbs) /* call %ctpr1, wbs = wbs */ + + static const unsigned int plt128_got_header[] = { - /* 0: */ - /* HS */ 0xb6d00034, - /* ALS0 */ 0x79c0d88a, /* ldgdq,0 0x0, _f32s,_lts0 0x12345678, %qr10 */ - /* ALS2 */ 0x79c0d88b, - /* ALS3 */ 0x79d0d88e, /* ldgdq,3 0x10, _f32s,_lts0 0x12345678, %qr14 */ - /* ALS5 */ 0x79d0d88f, - /* ALES03*/ 0x01c001c0, - /* LTS1 */ 0x00000000, - /* LTS0 */ 0x12345678, + LOAD_LINK_MAP_DL_FIXUP ( +#ifndef NEW_PM_ABI + 10, 14 +#else /* defined NEW_PM_ABI */ + 18, 22 +#endif + ), - /* 20: */ - /* HS */ 0x04000001, - /* ALS0 */ 0x61c08ed1, /* movtd,0 %dr14, %ctpr1 */ + MOVTD_TARGET( +#ifndef NEW_PM_ABI + 14 +#else /* defined NEW_PM_ABI */ + 22 +#endif /* defined NEW_PM_ABI */ + ), /* 28: */ /* HS */ 0x00009012, /* SS */ 0x80000420, /* ipd 2 */ - /* CS1 */ 0x50000004, /* call %ctpr1, wbs = 0x4 */ + /* CS1 */ CALL_WBS ( +#ifndef NEW_PM_ABI + 0x4 +#else /* defined NEW_PM_ABI */ + 0x8 +#endif /* defined NEW_PM_ABI */ + ), /* LTS0 */ 0x00000000, - /* 38: */ - /* HS */ 0x04000001, - /* ALS0 */ 0x61c088d1, /* movtd,0 %dr8, %ctpr1 */ + MOVTD_TARGET ( +#ifndef NEW_PM_ABI + 8 +#else /* defined NEW_PM_ABI */ + 16 +#endif /* defined NEW_PM_ABI */ + ), + +#ifndef NEW_PM_ABI + MOVTQ_PAIR (0, 8), + MOVTQ_PAIR (4, 12), +#else /* defined NEW_PM_ABI */ + MOVTQ_PAIR (0, 16), + MOVTQ_PAIR (4, 20), + MOVTQ_PAIR (8, 24), + MOVTQ_PAIR (12, 28), +#endif /* defined NEW_PM_ABI */ - /* 40: */ - /* HS */ 0x6db00034, - /* ALS0 */ 0x57c08088, /* movtq,0 %qr0, %qr8 */ - /* ALS1 */ 0x57c08189, - /* ALS3 */ 0x57c0828a, /* movtq,3 %qr2, %qr10 */ - /* ALS4 */ 0x57c0838b, - /* ALES01*/ 0x01c001c0, - /* ALES34*/ 0x01c001c0, - /* LTS0 */ 0x00000000, - - /* 60: */ - /* HS */ 0x6db00034, - /* ALS0 */ 0x57c0848c, /* movtq,0 %qr4, %qr12 */ - /* ALS1 */ 0x57c0858d, - /* ALS3 */ 0x57c0868e, /* movtq,3 %qr6, %qr14 */ - /* ALS4 */ 0x57c0878f, - /* ALES01*/ 0x01c001c0, - /* ALES34*/ 0x01c001c0, - /* LTS0 */ 0x00000000, - - /* 80: */ /* HS */ 0x00009012, /* SS */ 0x80000420, /* ipd 2 */ - /* CS1 */ 0x50000004, /* call %ctpr1, wbs = 0x4 */ + /* CS1 */ CALL_WBS ( +#ifndef NEW_PM_ABI + 0x4 +#else /* defined NEW_PM_ABI */ + 0x8 +#endif /* defined NEW_PM_ABI */ + ), /* LTS0 */ 0x00000000, - /* 90: */ /* HS */ 0x00004001, /* CS0 */ 0xf0000000, /* return %ctpr3 */ - /* 98: */ - /* HS */ 0x6db00034, - /* ALS0 */ 0x57c08880, /* movtq,0 %qr8, %qr0 */ - /* ALS1 */ 0x57c08981, - /* ALS3 */ 0x57c08a82, /* movtq,3 %qr10, %qr2 */ - /* ALS4 */ 0x57c08b83, - /* ALES01*/ 0x01c001c0, - /* ALES34*/ 0x01c001c0, - /* LTS0 */ 0x00000000, +#ifndef NEW_PM_ABI + MOVTQ_PAIR (8, 0), + MOVTQ_PAIR (12, 4), +#else /* defined NEW_PM_ABI */ + MOVTQ_PAIR (16, 0), + MOVTQ_PAIR (20, 4), + MOVTQ_PAIR (24, 8), + MOVTQ_PAIR (28, 12), +#endif /* defined NEW_PM_ABI */ - /* b8: */ - /* HS */ 0x6db00034, - /* ALS0 */ 0x57c08c84, /* movtq,0 %qr12, %qr4 */ - /* ALS1 */ 0x57c08d85, - /* ALS3 */ 0x57c08e86, /* movtq,3 %qr14, %qr6 */ - /* ALS4 */ 0x57c08f87, - /* ALES01*/ 0x01c001c0, - /* ALES34*/ 0x01c001c0, - /* LTS0 */ 0x00000000, - - /* d8: */ /* HS */ 0x00001001, /* SS */ 0x80000c20, /* ct %ctpr3 */ /* ipd 2 */ }; +#define PLT128_GOT_HEADER_NOP_OFFSET 0x0 #define PLT128_GOT_LINK_MAP_LD_OFFSET 0x1c #define PLT128_GOT_HEADER_SIZE sizeof (plt128_got_header); +#define LOAD_TARGET(ind) \ + /* ALS0 */ (0x79c0d980 | ind), /* ldgdq,0 0x0, _f32s,_lts1 0x0, %qr{ind} */ \ + /* ALS2 */ (0x79c0d980 | (ind + 1)) + static const unsigned int plt128_got_primary_entry[] = { /* 0: */ - /* HS */ 0x04108022, - /* ALS0 */ 0x67c0d988, /* ldgdd,0 0x0, _f32s,_lts1 0x0, %dr8 */ - /* CS1 */ 0x00000000, /* setwd wsz = 0x8, nfx = 0x1 */ + /* HS */ 0x14508033, + /* ALS{0,2} */ LOAD_TARGET ( +#ifndef NEW_PM_ABI + 8 +#else /* defined NEW_PM_ABI */ + 16 +#endif /* defined NEW_PM_ABI */ + ), + /* CS1 */ 0x00000000, /* setwd wsz = 0x{8,10}, nfx = 0x1 */ /* ALES0 */ 0x01c00000, + /* LTS2 */ 0x00000000, /* LTS1 */ 0x00000000, - /* LTS0 */ 0x00000110, + /* LTS0 */ WSZ ( +#ifndef NEW_PM_ABI + 0x8 +#else /* defined NEW_PM_ABI */ + 0x10 +#endif /* defined NEW_PM_ABI */ + ), - /* 18: */ - /* HS */ 0x04000001, - /* ALS0 */ 0x61c088d1, /* movtd,0 %dr8, %ctpr1 */ +#ifndef NEW_PM_ABI + MOVTD_TARGET (8), + MOVTQ_PAIR (0, 8), + MOVTQ_PAIR (4, 12), +#else /* defined NEW_PM_ABI */ + MOVTD_TARGET (16), + MOVTQ_PAIR (0, 16), + MOVTQ_PAIR (4, 20), + MOVTQ_PAIR (8, 24), + MOVTQ_PAIR (12, 28), +#endif /* defined NEW_PM_ABI */ - /* 20: */ - /* HS */ 0x6db00034, - /* ALS0 */ 0x57c08088, /* movtq,0 %qr0, %qr8 */ - /* ALS1 */ 0x57c08189, - /* ALS3 */ 0x57c0828a, /* movtq,3 %qr2, %qr10 */ - /* ALS4 */ 0x57c0838b, - /* ALES */ 0x01c001c0, - /* ALES */ 0x01c001c0, - /* LTS0 */ 0x00000000, - - /* 40: */ - /* HS */ 0x6db00034, - /* ALS0 */ 0x57c0848c, /* movtq,0 %qr4, %qr12 */ - /* ALS1 */ 0x57c0858d, - /* ALS3 */ 0x57c0868e, /* movtq,3 %qr6, %qr14 */ - /* ALS4 */ 0x57c0878f, - /* ALES */ 0x01c001c0, - /* ALES */ 0x01c001c0, - /* LTS0 */ 0x00000000, - - /* 60: */ /* HS */ 0x00009012, /* SS */ 0x80000420, /* ipd 2 */ - /* CS1 */ 0x50000004, /* call %ctpr1, wbs = 0x4 */ + /* CS1 */ CALL_WBS ( +#ifndef NEW_PM_ABI + 0x4 +#else /* defined NEW_PM_ABI */ + 0x8 +#endif /* defined NEW_PM_ABI */ + ), /* LTS0 */ 0x00000000, - /* 70: */ /* HS */ 0x00005012, /* SS */ 0x80000000, /* ipd 2 */ /* CS0 */ 0xf0000000, /* return %ctpr3 */ /* LTS0 */ 0x00000000, +#ifndef NEW_PM_ABI + MOVTQ_PAIR (8, 0), + MOVTQ_PAIR (12, 4), +#else /* defined NEW_PM_ABI */ + MOVTQ_PAIR (16, 0), + MOVTQ_PAIR (20, 4), + MOVTQ_PAIR (24, 8), + MOVTQ_PAIR (28, 12), +#endif /* defined NEW_PM_ABI */ - /* 80: */ - /* HS */ 0x6db00034, - /* ALS0 */ 0x57c08880, /* movtq,0 %qr8, %qr0 */ - /* ALS1 */ 0x57c08981, - /* ALS3 */ 0x57c08a82, /* movtq,3 %qr10, %qr2 */ - /* ALS4 */ 0x57c08b83, - /* ALES */ 0x01c001c0, - /* ALES */ 0x01c001c0, - /* LTS0 */ 0x00000000, - - /* a0: */ - /* HS */ 0x6db00034, - /* ALS0 */ 0x57c08c84, /* movtq,0 %qr12, %qr4 */ - /* ALS1 */ 0x57c08d85, - /* ALS3 */ 0x57c08e86, /* movtq,3 %qr14, %qr6 */ - /* ALS4 */ 0x57c08f87, - /* ALES */ 0x01c001c0, - /* ALES */ 0x01c001c0, - /* LTS0 */ 0x00000000, - - /* c0: */ /* HS */ 0x00001001, /* SS */ 0x80000c20, /* ct %ctpr3 */ /* ipd 2 */ }; -#define PLT128_GOT_TARGET_LD_OFFSET 0x10 +#define PLT128_GOT_ENTRY_NOP_OFFSET 0x0 +#define PLT128_GOT_TARGET_LD_OFFSET 0x18 #define PLT128_GOT_PRIMARY_ENTRY_SIZE sizeof (plt128_got_primary_entry) + +#define RELOC_ARG(ind) \ + /* ALS0 */ (0x10c0d980 | ind) /* adds,0 0x0, _f32s,_lts1 0x12345678, %r{ind} */ + static const unsigned int plt128_got_secondary_entry[] = { /* 0: */ /* HS */ 0x0400d034, /* SS */ 0x80000020, /* ipd 2 */ - /* ALS0 */ 0x10c0d98c, /* adds,0 0x0, _f32s,_lts1 0x12345678, %r12 */ + /* ALS0 */ RELOC_ARG ( +#ifndef NEW_PM_ABI + 12 +#else /* defined NEW_PM_ABI */ + 20 +#endif /* defined NEW_PM_ABI */ + ), /* CS0 */ 0x00000000, /* ibranch 0x0 */ - /* CS1 */ 0x00000000, /* setwd wsz = 0x8, nfx = 0x1 */ + /* CS1 */ 0x00000000, /* setwd wsz = 0x{8,10}, nfx = 0x1 */ /* LTS2 */ 0x00000000, /* LTS1 */ 0x12345678, - /* LTS0 */ 0x00000110, + /* LTS0 */ WSZ ( +#ifndef NEW_PM_ABI + 0x8 +#else /* defined NEW_PM_ABI */ + 0x10 +#endif /* defined NEW_PM_ABI */ + ) }; #define PLT128_GOT_DISP_OFFSET 0xc @@ -1940,7 +2424,7 @@ static const unsigned int plt_got_secondary_entry[] = /* 0: */ /* HS */ 0x0400d034, /* SS */ 0x80000020, /* ipd 2 */ - /* ALS0 */ 0x10c0d989, /* adds,0 0x0, _f32s,_lts1 0x76543210, %r9 */ + /* ALS0 */ 0x11c0d989, /* addd,0 0x0, _f32s,_lts1 0x76543210, %r9 */ /* CS0 */ 0x00000000, /* ibranch 0x0 */ /* CS1 */ 0x00000000, /* setwd wsz = 0x8, nfx = 0x1 */ /* LTS2 */ 0x00000000, @@ -1972,9 +2456,6 @@ e2k64_plt_lazy_entry_adjust_reloc_offset (bfd *output_bfd, -#define ABI_64_P(abfd) \ - (get_elf_backend_data (abfd)->s->elfclass == ELFCLASS64) - /* Create an entry in an E2k ELF linker hash table. */ static struct bfd_hash_entry * @@ -2033,22 +2514,26 @@ _bfd_e2k_elf_link_hash_table_finalize (struct bfd_link_info *info) if (bfd_link_pic (info)) { htab->plt_got_header = plt64_got_pic_header; + htab->plt_got_header_nop_offset = PLT64_GOT_PIC_HEADER_NOP_OFFSET; htab->plt_got_link_map_ld_offset = PLT64_GOT_PIC_LINK_MAP_LD_OFFSET; htab->plt_got_dl_fixup_ld_offset = PLT64_GOT_PIC_DL_FIXUP_LD_OFFSET; htab->plt_got_header_size = PLT64_GOT_PIC_HEADER_SIZE; htab->plt_got_primary_entry = plt64_got_pic_primary_entry; + htab->plt_got_entry_nop_offset = PLT64_GOT_PIC_ENTRY_NOP_OFFSET; htab->plt_got_target_ld_offset = PLT64_GOT_PIC_TARGET_LD_OFFSET; htab->plt_got_primary_entry_size = PLT64_GOT_PIC_PRIMARY_ENTRY_SIZE; } else { htab->plt_got_header = plt64_got_non_pic_header; + htab->plt_got_header_nop_offset = PLT64_GOT_NON_PIC_HEADER_NOP_OFFSET; htab->plt_got_link_map_ld_offset = PLT64_GOT_NON_PIC_LINK_MAP_LD_OFFSET; htab->plt_got_header_size = PLT64_GOT_NON_PIC_HEADER_SIZE; htab->plt_got_primary_entry = plt64_got_non_pic_primary_entry; + htab->plt_got_entry_nop_offset = PLT64_GOT_NON_PIC_ENTRY_NOP_OFFSET; htab->plt_got_target_ld_offset = PLT64_GOT_NON_PIC_TARGET_LD_OFFSET; htab->plt_got_primary_entry_size = PLT64_GOT_NON_PIC_PRIMARY_ENTRY_SIZE; @@ -2059,22 +2544,26 @@ _bfd_e2k_elf_link_hash_table_finalize (struct bfd_link_info *info) if (bfd_link_pic (info)) { htab->plt_got_header = plt32_got_pic_header; + htab->plt_got_header_nop_offset = PLT32_GOT_PIC_HEADER_NOP_OFFSET; htab->plt_got_link_map_ld_offset = PLT32_GOT_PIC_LINK_MAP_LD_OFFSET; htab->plt_got_dl_fixup_ld_offset = PLT32_GOT_PIC_DL_FIXUP_LD_OFFSET; htab->plt_got_header_size = PLT32_GOT_PIC_HEADER_SIZE; htab->plt_got_primary_entry = plt32_got_pic_primary_entry; + htab->plt_got_entry_nop_offset = PLT32_GOT_PIC_ENTRY_NOP_OFFSET; htab->plt_got_target_ld_offset = PLT32_GOT_PIC_TARGET_LD_OFFSET; htab->plt_got_primary_entry_size = PLT32_GOT_PIC_PRIMARY_ENTRY_SIZE; } else { htab->plt_got_header = plt32_got_non_pic_header; + htab->plt_got_header_nop_offset = PLT32_GOT_NON_PIC_HEADER_NOP_OFFSET; htab->plt_got_link_map_ld_offset = PLT32_GOT_NON_PIC_LINK_MAP_LD_OFFSET; htab->plt_got_header_size = PLT32_GOT_NON_PIC_HEADER_SIZE; htab->plt_got_primary_entry = plt32_got_non_pic_primary_entry; + htab->plt_got_entry_nop_offset = PLT32_GOT_NON_PIC_ENTRY_NOP_OFFSET; htab->plt_got_target_ld_offset = PLT32_GOT_NON_PIC_TARGET_LD_OFFSET; htab->plt_got_primary_entry_size = PLT32_GOT_NON_PIC_PRIMARY_ENTRY_SIZE; @@ -2094,10 +2583,12 @@ _bfd_e2k_elf_link_hash_table_finalize (struct bfd_link_info *info) else /* if (ABI_PM_P (info->output_bfd)) */ { htab->plt_got_header = plt128_got_header; + htab->plt_got_header_nop_offset = PLT128_GOT_HEADER_NOP_OFFSET; htab->plt_got_link_map_ld_offset = PLT128_GOT_LINK_MAP_LD_OFFSET; htab->plt_got_header_size = PLT128_GOT_HEADER_SIZE; htab->plt_got_primary_entry = plt128_got_primary_entry; + htab->plt_got_entry_nop_offset = PLT128_GOT_ENTRY_NOP_OFFSET; htab->plt_got_target_ld_offset = PLT128_GOT_TARGET_LD_OFFSET; htab->plt_got_primary_entry_size = PLT128_GOT_PRIMARY_ENTRY_SIZE; @@ -2130,16 +2621,39 @@ _bfd_e2k_elf_link_hash_table_create (bfd *abfd) if (ret == NULL) return NULL; + /* FIXME: this is a bit of a duplication of _bfd_e2k_elf_init_file_header_1 + () which is likely to be called after all input files have been opened + which is too late for ABI_{64,PM}_P (OUTPUT_BFD) to work properly in all + places of interest. */ + if (abfd->arch_info->mach % 4 == 2) + elf_elfheader (abfd)->e_flags |= EF_E2K_PM; + + + if (ELF64_P (abfd)) + { + ret->r_info = e2k_elf_r_info_64; + ret->bytes_per_sym = sizeof (Elf64_External_Sym); + ret->bytes_per_rela = sizeof (Elf64_External_Rela); + + ret->ancient_semantics = E2K_MPTR_64; + } + else + { + ret->r_info = e2k_elf_r_info_32; + ret->bytes_per_sym = sizeof (Elf32_External_Sym); + ret->bytes_per_rela = sizeof (Elf32_External_Rela); + + ret->ancient_semantics = E2K_MPTR_32; + } + if (ABI_64_P (abfd)) { ret->put_word = e2k_put_word_64; - ret->r_info = e2k_elf_r_info_64; ret->adjust_plt_lazy_entry_reloc_offset = e2k64_plt_lazy_entry_adjust_reloc_offset; ret->word_align_power = 3; ret->bytes_per_word = 8; - ret->bytes_per_sym = sizeof (Elf64_External_Sym); - ret->bytes_per_rela = sizeof (Elf64_External_Rela); + ret->abs_reloc = R_E2K_64_ABS; ret->abs_lit_reloc = R_E2K_64_ABS_LIT; ret->copy_reloc = R_E2K_64_COPY; @@ -2150,18 +2664,15 @@ _bfd_e2k_elf_link_hash_table_create (bfd *abfd) ret->tpoff_reloc = R_E2K_TLS_TPOFF64; ret->jmp_slot_reloc = R_E2K_64_JMP_SLOT; ret->irelative_reloc = R_E2K_64_IRELATIVE; - ret->ancient_semantics = E2K_MPTR_64; } else { ret->put_word = e2k_put_word_32; - ret->r_info = e2k_elf_r_info_32; ret->adjust_plt_lazy_entry_reloc_offset = e2k32_plt_lazy_entry_adjust_reloc_offset; ret->word_align_power = 2; ret->bytes_per_word = 4; - ret->bytes_per_sym = sizeof (Elf32_External_Sym); - ret->bytes_per_rela = sizeof (Elf32_External_Rela); + ret->abs_reloc = R_E2K_32_ABS; ret->abs_lit_reloc = R_E2K_32_ABS; ret->copy_reloc = R_E2K_32_COPY; @@ -2172,7 +2683,6 @@ _bfd_e2k_elf_link_hash_table_create (bfd *abfd) ret->tpoff_reloc = R_E2K_TLS_TPOFF32; ret->jmp_slot_reloc = R_E2K_32_JMP_SLOT; ret->irelative_reloc = R_E2K_32_IRELATIVE; - ret->ancient_semantics = E2K_MPTR_32; } ret->gdmod_zero_off = (bfd_vma) -1; @@ -2219,7 +2729,7 @@ _bfd_e2k_elf_create_dynamic_sections (bfd *dynobj, /* .got should be aligned to 2**4 in PM. */ if (ABI_PM_P (dynobj) - && ! bfd_set_section_alignment (dynobj, htab->elf.sgot, 4)) + && ! bfd_set_section_alignment (htab->elf.sgot, 4)) return FALSE; htab->sdynbss = bfd_get_linker_section (dynobj, ".dynbss"); @@ -2281,7 +2791,7 @@ search_pure_eir (bfd *abfd, asection *sec, void *no_pure_eir) if (strcmp (sec->name, ".pack_pure_eir") == 0) { *((bfd_boolean *) no_pure_eir) = FALSE; - _bfd_error_handler ("%B with '.pack_pure_eir' is illegal during " + _bfd_error_handler ("%pB with '.pack_pure_eir' is illegal during " "non-relocatable linkage", abfd); bfd_set_error (bfd_error_wrong_format); } @@ -2340,14 +2850,29 @@ _bfd_e2k_elf_mkobject (bfd *abfd) a `.gnu.warning.SYMBOL' section it calls `_bfd_generic_link_add_one_symbol ()' which requires all this canonicalization. */ -void +bfd_boolean _bfd_e2k_elf_info_to_howto (bfd *abfd, arelent *bfd_reloc, Elf_Internal_Rela *elf_reloc) { - bfd_reloc->howto - = &_bfd_e2k_elf_howto_table[ELF_R_TYPE (abfd, elf_reloc->r_info)]; + unsigned int r_type; + r_type = ELF_R_TYPE (abfd, elf_reloc->r_info); + if (r_type < (sizeof (_bfd_e2k_elf_howto_table) + / sizeof (_bfd_e2k_elf_howto_table[0]))) + bfd_reloc->howto = &_bfd_e2k_elf_howto_table[r_type]; + else + bfd_reloc->howto = NULL; + + if (bfd_reloc->howto == NULL || bfd_reloc->howto->name == NULL) + { + _bfd_error_handler (_("%pB: unsupported relocation type %#x"), + abfd, r_type); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + + return TRUE; } static asection * @@ -2470,7 +2995,7 @@ _bfd_e2k_elf_add_symbol_hook (bfd *abfd, struct bfd_link_info *info, && bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour && (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC || ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE)) - elf_tdata (info->output_bfd)->has_gnu_symbols = TRUE; + elf_tdata (info->output_bfd)->has_gnu_osabi = TRUE; /* When not linking EIR, special symbols related to sections containing EIR should be ignored. @@ -2587,15 +3112,14 @@ create_ifunc_sections (bfd *abfd, struct bfd_link_info *info) s = bfd_make_section_with_flags (abfd, ".iplt", pltflags); if (s == NULL - || ! bfd_set_section_alignment (abfd, s, bed->plt_alignment)) + || ! bfd_set_section_alignment (s, bed->plt_alignment)) return FALSE; htab->iplt = s; s = bfd_make_section_with_flags (abfd, ".rela.iplt", flags | SEC_READONLY); if (s == NULL - || ! bfd_set_section_alignment (abfd, s, - bed->s->log_file_align)) + || ! bfd_set_section_alignment (s, bed->s->log_file_align)) return FALSE; htab->irelplt = s; @@ -2756,7 +3280,7 @@ _bfd_e2k_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, for (; rel < rel_end; rel++) { unsigned int r_type; - unsigned long r_symndx; + unsigned int r_symndx; struct elf_link_hash_entry *h; Elf_Internal_Sym *isym; bfd_boolean size_reloc = FALSE; @@ -2766,7 +3290,7 @@ _bfd_e2k_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr)) { - _bfd_error_handler (_("%B: bad symbol index: %d"), + _bfd_error_handler (_("%pB: bad symbol index: %d"), abfd, r_symndx); return FALSE; } @@ -2917,7 +3441,7 @@ _bfd_e2k_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, && (tls_type & GOT_NORMAL) != (old_tls_type & GOT_NORMAL)) { _bfd_error_handler - (_("%B: `%s' accessed both as normal and thread local symbol"), + (_("%pB: `%s' accessed both as normal and thread local symbol"), abfd, h ? h->root.root.string : ""); return FALSE; } @@ -2928,6 +3452,7 @@ _bfd_e2k_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, _bfd_e2k_elf_local_got_tls_type (abfd) [r_symndx] |= tls_type; } + /* Fall through */ case R_E2K_GOTOFF: case R_E2K_64_GOTOFF: case R_E2K_64_GOTOFF_LIT: @@ -2943,8 +3468,7 @@ _bfd_e2k_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, /* .got should be aligned to 2**4 in PM. */ if (ABI_PM_P (htab->elf.dynobj) - && ! bfd_set_section_alignment (htab->elf.dynobj, - htab->elf.sgot, 4)) + && ! bfd_set_section_alignment (htab->elf.sgot, 4)) return FALSE; } break; @@ -3244,6 +3768,7 @@ _bfd_e2k_elf_gc_sweep_hook (bfd *abfd, eh->gdmod.refcount -= 1; } + /* Fall through */ case R_E2K_TLS_IE: if (h != NULL) { @@ -3316,13 +3841,13 @@ _bfd_e2k_elf_adjust_dynamic_symbol (struct bfd_link_info *info, /* If this is a weak symbol, and there is a real definition, the processor independent code will have arranged for us to see the real definition first, and we can just use the same value. */ - if (h->u.weakdef != NULL) + if (h->is_weakalias) { - BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined - || h->u.weakdef->root.type == bfd_link_hash_defweak); - h->root.u.def.section = h->u.weakdef->root.u.def.section; - h->root.u.def.value = h->u.weakdef->root.u.def.value; - h->non_got_ref = h->u.weakdef->non_got_ref; + struct elf_link_hash_entry *def = weakdef (h); + BFD_ASSERT (def->root.type == bfd_link_hash_defined); + h->root.u.def.section = def->root.u.def.section; + h->root.u.def.value = def->root.u.def.value; + h->non_got_ref = def->non_got_ref; return TRUE; } @@ -3386,6 +3911,18 @@ _bfd_e2k_elf_adjust_dynamic_symbol (struct bfd_link_info *info, return _bfd_elf_adjust_dynamic_copy (info, h, htab->sdynbss); } +static void +reserve_space_for_selfinit (struct _bfd_e2k_elf_link_hash_table *htab, + size_t size_of_item, + size_t items, + const char *name ATTRIBUTE_UNUSED) +{ + htab->selfinit->size += items * size_of_item; + // printf ("%s: %ld %s slots\n", name, items, + // size_of_item == sizeof (selfinit_ap) ? "AP" : "PL"); + // fflush (NULL); +} + static bfd_boolean allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) { @@ -3574,7 +4111,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) "self-initialize" the secondary PLT entry. The code will be emitted in `build_secondary_plt_entry ()'. */ if (ABI_PM_P (htab->elf.dynobj)) - htab->selfinit->size += sizeof (selfinit_pl); + reserve_space_for_selfinit (htab, sizeof (selfinit_pl), 1, + h->root.root.string); } /* We may find ourselves here, for example, if the symbol is not defined anywhere. What should be done then? */ @@ -3633,6 +4171,14 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) against a locally resolved symbol in PM shared(?) OBFD. */ && ! (ABI_PM_P (htab->elf.dynobj) + /* In a PM shared library runtime relocation can be + avoided for a locally symbol only via GOT_NORMAL, + not via GOT_TLS_IE, of course. The latter case is + quite analogous to ordinary modes since the offset + of the symbol in the static TLS block is unknown at + link-time whichever mode the library is intended + for. */ + && types[i] == GOT_NORMAL && SYMBOL_REFERENCES_LOCAL (info, h))) || (bfd_link_pic (info) && SYMBOL_REFERENCES_LOCAL (info, h) && ! ABI_PM_P (htab->elf.dynobj)))) @@ -3652,7 +4198,10 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) if (htab->gdmod_zero_off == (bfd_vma) -1) { htab->gdmod_zero_off = htab->elf.sgot->size; - htab->elf.sgot->size += htab->bytes_per_word; + htab->elf.sgot->size + += (ABI_PM_P (htab->elf.dynobj) + ? 16 : htab->bytes_per_word); + if (bfd_link_pic (info)) htab->elf.srelgot->size += htab->bytes_per_rela; } @@ -3661,9 +4210,11 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) else if (ABI_PM_P (htab->elf.dynobj)) { if (eh->pm_got_type == 1) - htab->selfinit->size += sizeof (selfinit_ap); + reserve_space_for_selfinit (htab, sizeof (selfinit_ap), 1, + h->root.root.string); else if (eh->pm_got_type == 2) - htab->selfinit->size += sizeof (selfinit_pl); + reserve_space_for_selfinit (htab, sizeof (selfinit_pl), 1, + h->root.root.string); } } else @@ -3727,7 +4278,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) to work properly. */ if (ABI_PM_P (htab->elf.dynobj) && (ELF_ST_VISIBILITY (h->other) == STV_HIDDEN - || SYMBOL_REFERENCES_LOCAL (info, h) + || SYMBOL_REFERENCES_LOCAL (info, h) || h->forced_local) && eh->dyn_relocs != NULL) goto discard_dyn_relocs; @@ -3762,10 +4313,12 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) if (ABI_PM_P (htab->elf.dynobj)) { for (p = eh->dyn_relocs; p != NULL; p = p->next) - htab->selfinit->size - += (p->count - p->pc_count) * (p->type == 1 - ? sizeof (selfinit_ap) - : sizeof (selfinit_pl)); + reserve_space_for_selfinit (htab, + (p->type == 1 + ? sizeof (selfinit_ap) + : sizeof (selfinit_pl)), + p->count - p->pc_count, + h->root.root.string); } eh->dyn_relocs = NULL; @@ -3803,7 +4356,8 @@ finalize_plt_offsets (struct elf_link_hash_entry *h, void *inf) struct export_pl_list *next = htab->export_pl_list; htab->export_pl->size += 16; - htab->selfinit->size += sizeof (selfinit_pl); + reserve_space_for_selfinit (htab, sizeof (selfinit_pl), 1, + h->root.root.string); htab->export_pl_list = ((struct export_pl_list *) bfd_alloc @@ -3840,9 +4394,9 @@ readonly_dynrelocs (struct elf_link_hash_entry *h, void * inf) info->flags |= DF_TEXTREL; - if (info->warn_shared_textrel && bfd_link_pic (info)) - info->callbacks->einfo (_("%P: %B: warning: relocation against `%s' " - "in readonly section `%A'.\n"), + if (bfd_link_textrel_check (info)) + info->callbacks->einfo (_("%P: %pB: warning: relocation against `%s' " + "in readonly section `%pA'.\n"), p->sec->owner, h->root.root.string, p->sec); @@ -3902,10 +4456,10 @@ _bfd_e2k_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, && (info->flags & DF_TEXTREL) == 0) { info->flags |= DF_TEXTREL; - if (info->warn_shared_textrel && bfd_link_pic (info)) + if (bfd_link_textrel_check (info)) info->callbacks->einfo - (_("%P: %B: warning: relocation in readonly " - "section `%A'.\n"), p->sec->owner, p->sec); + (_("%P: %pB: warning: relocation in readonly " + "section `%pA'.\n"), p->sec->owner, p->sec); } } else @@ -3915,10 +4469,11 @@ _bfd_e2k_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, should one require dynamic relocations against local symbols in Protected Mode. */ BFD_ASSERT (p->type == 1 || p->type == 2); - htab->selfinit->size - += p->count * (p->type == 1 - ? sizeof (selfinit_ap) - : sizeof (selfinit_pl)); + reserve_space_for_selfinit (htab, + (p->type == 1 + ? sizeof (selfinit_ap) + : sizeof (selfinit_pl)), + p->count, s->name); } } } @@ -3978,7 +4533,7 @@ _bfd_e2k_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, && htab->gdmod_zero_off == (bfd_vma) -1) { htab->gdmod_zero_off = s->size; - s->size += htab->bytes_per_word; + s->size += ABI_PM_P (dynobj) ? 16 : htab->bytes_per_word; if (bfd_link_pic (info)) srel->size += htab->bytes_per_rela; /* I don't increase *local_relgot_cntr here intentionally @@ -3993,7 +4548,7 @@ _bfd_e2k_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, if (types[i] != GOT_TLS_GDMOD) { *entry = s->size; - s->size += htab->bytes_per_word; + s->size += ABI_PM_P (dynobj) ? 16 : htab->bytes_per_word; } @@ -4026,7 +4581,7 @@ _bfd_e2k_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, if (ABI_PM_P (htab->elf.dynobj) && bfd_link_executable (info)) { htab->export_pl->size += 16; - htab->selfinit->size += sizeof (selfinit_pl); + reserve_space_for_selfinit (htab, sizeof (selfinit_pl), 1, "_start"); } /* We now have determined the sizes of the various dynamic sections. @@ -4036,7 +4591,7 @@ _bfd_e2k_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, if ((s->flags & SEC_LINKER_CREATED) == 0) continue; - if (CONST_STRNEQ (bfd_get_section_name (dynobj, s), ".rela")) + if (CONST_STRNEQ (bfd_section_name (s), ".rela")) { /* We use the reloc_count field as a counter if we need to copy relocs into the output file. */ @@ -4098,7 +4653,9 @@ _bfd_e2k_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, if (dyn.d_tag == DT_INIT || dyn.d_tag == DT_FINI) { htab->export_pl->size += 16; - htab->selfinit->size += sizeof (selfinit_pl); + reserve_space_for_selfinit (htab, sizeof (selfinit_pl), 1, + (dyn.d_tag == DT_INIT + ? "_init" : "_fini")); } } } @@ -4385,10 +4942,12 @@ _bfd_e2k_elf_relocate_section (bfd *output_bfd, case R_ELCORE_S16PC_FAKE: case R_ELCORE_I32_FAKE: case R_E2K_NONE: + case R_E2K_64_DYNOPT: + case R_E2K_32_DYNOPT: break; default: _bfd_error_handler - (_("%B: unrecognized relocation (0x%x) in section `%A'"), + (_("%pB: unrecognized relocation (0x%x) in section `%pA'"), input_bfd, r_type, input_section); bfd_set_error (bfd_error_bad_value); return FALSE; @@ -4422,6 +4981,12 @@ _bfd_e2k_elf_relocate_section (bfd *output_bfd, h, sec, relocation, unresolved_reloc, warned, ignored); + if (strcmp (h[0].root.root.string, "ASN1_ANY_it") == 0) + { + static int cntr; + cntr++; + } + st_size = h->size; /* The following checks probably make sense for relocations against @@ -4452,7 +5017,7 @@ _bfd_e2k_elf_relocate_section (bfd *output_bfd, && !eh->dsp_symbol) { info->callbacks->einfo - (_("%XReferencing non-DSP symbol `%s' from DSP object `%B'\n"), + (_("%XReferencing non-DSP symbol `%s' from DSP object `%pB'\n"), h->root.root.string, input_bfd); /* return FALSE; */ } @@ -4467,7 +5032,7 @@ _bfd_e2k_elf_relocate_section (bfd *output_bfd, || r_type == R_E2K_64_ABS_LIT )) { info->callbacks->einfo - (_("%XReferencing DSP symbol `%s' from non-DSP object `%B' " + (_("%XReferencing DSP symbol `%s' from non-DSP object `%pB' " "via `%s' relocation. \n"), h->root.root.string, input_bfd, howto->name); /* return FALSE; */ @@ -4676,12 +5241,14 @@ _bfd_e2k_elf_relocate_section (bfd *output_bfd, add_selfinit_ap (info, relocation, st_size, r_addend, (htab->elf.sgot->output_section->vma + htab->elf.sgot->output_offset - + off)); + + off), + h->root.root.string); else if (r_type == R_E2K_PL_GOT) add_selfinit_pl (info, relocation + r_addend, (htab->elf.sgot->output_section->vma + htab->elf.sgot->output_offset - + off)); + + off), + h->root.root.string); entry_created = TRUE; @@ -4786,7 +5353,7 @@ _bfd_e2k_elf_relocate_section (bfd *output_bfd, } _bfd_error_handler - (_("%B: relocation `%s' against undefined %s `%s' can not be used when making a shared object"), + (_("%pB: relocation `%s' against undefined %s `%s' can not be used when making a shared object"), input_bfd, howto->name, v, h->root.root.string); bfd_set_error (bfd_error_bad_value); return FALSE; @@ -4797,7 +5364,7 @@ _bfd_e2k_elf_relocate_section (bfd *output_bfd, && ELF_ST_VISIBILITY (h->other) == STV_PROTECTED) { _bfd_error_handler - (_("%B: relocation `%s' against protected %s `%s' can not be used when making a shared object"), + (_("%pB: relocation `%s' against protected %s `%s' can not be used when making a shared object"), input_bfd, howto->name, h->type == STT_FUNC ? "function" : "data", @@ -4876,8 +5443,8 @@ _bfd_e2k_elf_relocate_section (bfd *output_bfd, relocation -= (input_section->output_section->vma + input_section->output_offset + rel->r_offset); - /* Fall through */ + /* Fall through */ case R_E2K_64_ABS_LIT: process_r_e2k_64_abs_lit: relocation += r_addend; @@ -4891,8 +5458,7 @@ _bfd_e2k_elf_relocate_section (bfd *output_bfd, break; } - /* Otherwise fall through */ - + /* Fall through */ case R_E2K_32_ABS: case R_E2K_64_ABS: case R_E2K_AP: @@ -4960,7 +5526,19 @@ _bfd_e2k_elf_relocate_section (bfd *output_bfd, if (ABI_PM_P (input_bfd) && (h == NULL || h->dynindx == -1 - || SYMBOLIC_BIND (info, h))) + /* SYMBOLIC_BIND itself does NOT imply the presence + of the symbol's definition required to build self- + initialization code. If the symbol was NOT defined in + an input object file space for its self-init code might + not have been allocated before, which would trigger an + assertion failure if one tried to emit this code here + (Bug #127084). Note that h->def_regular is likely to be + set for COMMON and defined weak symbols as well, but is + NOT set for undefined weaks not(?) requiring self- + initialization in dynamic case (ld.so is capable of + creating NULL itself). */ + || (SYMBOLIC_BIND (info, h) + && h->def_regular))) { /* What could be a useless (in case `skip == 1') selfinit code sequence, used instead of a relative relocaton in PM, @@ -5069,11 +5647,13 @@ _bfd_e2k_elf_relocate_section (bfd *output_bfd, + input_section->output_offset); if (r_type == R_E2K_AP) - add_selfinit_ap (info, relocation, st_size, r_addend, targ_off); + add_selfinit_ap (info, relocation, st_size, r_addend, targ_off, + h ? h->root.root.string : sec->name); else { BFD_ASSERT (r_type == R_E2K_PL); - add_selfinit_pl (info, relocation + r_addend, targ_off); + add_selfinit_pl (info, relocation + r_addend, targ_off, + h ? h->root.root.string : sec->name); } } else if (r_type == R_E2K_64_ABS_LIT) @@ -5223,8 +5803,10 @@ _bfd_e2k_elf_relocate_section (bfd *output_bfd, relocation = (htab->elf.sgot->output_section->vma + htab->elf.sgot->output_offset + off - - htab->elf.sgotplt->output_section->vma - - htab->elf.sgotplt->output_offset); + - (ABI_PM_P (input_bfd) + ? 0 + : (htab->elf.sgotplt->output_section->vma + + htab->elf.sgotplt->output_offset))); } break; @@ -5258,6 +5840,18 @@ _bfd_e2k_elf_relocate_section (bfd *output_bfd, relocation = SYMBOL_CALLS_LOCAL (info, h) ? 0x1 : 0x0; break; + case R_E2K_32_DYNOPT: + case R_E2K_64_DYNOPT: + /* According to the purpose of @DYNOPT expressed in Bug #117734, + Comment #11 leave relocation intact for local ELF symbols and + those global ones which are sure to be defined in the same + compilation unit, otherwise zero it out. */ + if (h != NULL + && (h->root.type != bfd_link_hash_defined + || h->root.u.def.section->owner != input_bfd)) + relocation = 0; + break; + case R_ELCORE_NONE: case R_ELCORE_I5: case R_ELCORE_I16: @@ -5319,10 +5913,44 @@ _bfd_e2k_elf_relocate_section (bfd *output_bfd, if (r_type == R_E2K_AP || r_type == R_E2K_PL) continue; + bfd_boolean restore_output_section_vma = FALSE; + bfd_vma saved_output_section_vma; + /* Do not adjust relocations having other meanings than offset by + mistake. Are all of them taken into account below? */ + if (ABI_PM_P (input_bfd) + && (input_section->flags & SEC_ALLOC) != 0 /* ??? */ + /* What else relocations operate on offsets in CUD and GD? */ + && (((r_type == R_E2K_32_ABS + || r_type == R_E2K_DISP) + && ! (h != NULL + && h->root.type == bfd_link_hash_defined + && bfd_is_abs_section (h->root.u.def.section))) + /* For these relocations the offset (i.e. with respect to GD.base) + of a .got entry is evaluated here. It obviously needs to be + adjusted no matter if the target symbol is absolute or not. */ + || r_type == R_E2K_AP_GOT + || r_type == R_E2K_PL_GOT + || r_type == R_E2K_TLS_IE + || r_type == R_E2K_TLS_GDMOD + || r_type == R_E2K_TLS_GDREL + || r_type == R_E2K_32_PC)) + { + /* All this idiotism is required for PC-relative relocations to be + performed properly in "packed mode". */ + saved_output_section_vma = input_section->output_section->vma; + input_section->output_section->vma + = adjust_offset_in_cud_gd (info, saved_output_section_vma); + restore_output_section_vma = TRUE; + relocation = adjust_offset_in_cud_gd (info, relocation); + } + r = _bfd_final_link_relocate (howto, input_bfd, input_section, contents, rel->r_offset, relocation, r_addend); + if (restore_output_section_vma) + input_section->output_section->vma = saved_output_section_vma; + if (r != bfd_reloc_ok) { const char *name; @@ -5337,7 +5965,7 @@ _bfd_e2k_elf_relocate_section (bfd *output_bfd, if (name == NULL) return FALSE; if (*name == '\0') - name = bfd_section_name (input_bfd, sec); + name = bfd_section_name (sec); } if (r == bfd_reloc_overflow) @@ -5350,7 +5978,7 @@ _bfd_e2k_elf_relocate_section (bfd *output_bfd, else { _bfd_error_handler - (_("%B(%A+0x%lx): reloc against `%s': error %d"), + (_("%pB(%pA+0x%lx): reloc against `%s': error %d"), input_bfd, input_section, (long) rel->r_offset, name, (int) r); return FALSE; @@ -5426,7 +6054,8 @@ _bfd_e2k_elf_finish_dynamic_symbol (bfd *output_bfd, if (secondary_plt_idx (h) != (bfd_vma) -1) { build_secondary_plt_entry (info, secondary_plt_offset (h, htab), - gotplt_offset, &rela.r_offset); + gotplt_offset, &rela.r_offset, + h->root.root.string); } if (secondary_plt_idx (h) != (bfd_vma) -1) @@ -5643,9 +6272,16 @@ e2k_finish_dyn (bfd *output_bfd, struct bfd_link_info *info, || h->root.type == bfd_link_hash_defweak)) { asection *o = h->root.u.def.section; - dyn.d_un.d_val = (h->root.u.def.value - + o->output_section->vma - + o->output_offset); + dyn.d_un.d_val + = (adjust_offset_in_cud_gd (info, + (h->root.u.def.value + + o->output_section->vma + + o->output_offset + /* Ensures that address of "_end" + fits within the range. */ + - 1)) + /* Account for -1 hack above. */ + + 1); bed->s->swap_dyn_out (output_bfd, &dyn, dyncon); } else @@ -5703,11 +6339,12 @@ e2k_finish_dyn (bfd *output_bfd, struct bfd_link_info *info, shared libraries. */ if (ABI_PM_P (dynobj)) { - add_selfinit_pl (info, dyn.d_un.d_ptr, *export_pl_off); + add_selfinit_pl (info, dyn.d_un.d_ptr, *export_pl_off, + dyn.d_tag == DT_INIT ? "_init" : "_fini"); *export_pl_off += 16; } - /* Fall through. */ + /* Fall through */ default: name = NULL; @@ -5833,6 +6470,29 @@ _bfd_e2k_elf_finish_dynamic_sections (bfd *output_bfd, asection *splt; asection *sgotplt; + unsigned long omach = bfd_get_mach (output_bfd) / 4;; + + /* Until support for specific elbrus-v6 machines has been added I can + check it this way. Note that `>= 6' can't be used here because + specific machines (say, elbrus-{8c,1c+} for elbrus-v4) are marked + with numbers exceeding the maximal possible iset version. */ + + /* Take into account that delay between load and its consumer has been + increased from 3 to 5 ticks starting from elbrus-v6 (see Bug #112004, + Comment #8). */ + unsigned int nops = ((omach == bfd_mach_e2k_ev6 + || omach == bfd_mach_e2k_12c + || omach == bfd_mach_e2k_16c + || omach == bfd_mach_e2k_2c3) ? 4 : 2); + + unsigned int hs_nop = + htab->plt_got_header[htab->plt_got_header_nop_offset / 4]; + + /* Adjust HS.nop according to the aforesaid. */ + hs_nop = (hs_nop & 0xfffffc7fu) | (nops << 7); + bfd_put_32 (output_bfd, hs_nop, + htab->elf.splt->contents + htab->plt_got_header_nop_offset); + // BFD_ASSERT (htab->elf.splt->size >= htab->plt_lazy_header_size); splt = htab->elf.splt; @@ -5867,8 +6527,10 @@ _bfd_e2k_elf_finish_dynamic_sections (bfd *output_bfd, means of specifying `size_of_PLT_entry' for SRC1 and the same 32-bit LTS for SRC2 for another load within the same wide instruction. */ - bfd_vma addr = (sgotplt->output_section->vma + sgotplt->output_offset - + starting_got_entry_size); + bfd_vma addr = adjust_offset_in_cud_gd (info, + (sgotplt->output_section->vma + + sgotplt->output_offset + + starting_got_entry_size)); unsigned int ld_offset = htab->plt_got_link_map_ld_offset; if (ABI_64_P (output_bfd)) @@ -5891,7 +6553,11 @@ _bfd_e2k_elf_finish_dynamic_sections (bfd *output_bfd, const struct elf_backend_data *bed = get_elf_backend_data (output_bfd); BFD_ASSERT (htab->elf.sgotplt->size >= bed->got_header_size); - val = sdyn ? sdyn->output_section->vma + sdyn->output_offset : 0; + val = (sdyn + ? adjust_offset_in_cud_gd (info, + (sdyn->output_section->vma + + sdyn->output_offset)) + : 0); htab->put_word (output_bfd, val, htab->elf.sgotplt->contents); /* The second and the third entries will be filled in by ld.so with the @@ -5914,7 +6580,7 @@ _bfd_e2k_elf_finish_dynamic_sections (bfd *output_bfd, bfd_vma addr = (s->output_section->vma + s->output_offset + e->h->root.u.def.value); - add_selfinit_pl (info, addr, targ_off); + add_selfinit_pl (info, addr, targ_off, e->h->root.root.string); targ_off += 16; } @@ -5923,7 +6589,7 @@ _bfd_e2k_elf_finish_dynamic_sections (bfd *output_bfd, executable. */ if (bfd_link_executable (info)) add_selfinit_pl (info, bfd_get_start_address (output_bfd), - targ_off); + targ_off, "_start"); } } @@ -5973,11 +6639,9 @@ _bfd_e2k_elf_object_p_1 (bfd *abfd, } else { -#if 0 if ((!protected_mode && (i_ehdrp->e_flags & EF_E2K_PM) != 0) || (protected_mode && (i_ehdrp->e_flags & EF_E2K_PM) != EF_E2K_PM)) return FALSE; -#endif /* 0 */ pm = (i_ehdrp->e_flags & EF_E2K_PM) == EF_E2K_PM; mach = EF_E2K_FLAG_TO_MACH (i_ehdrp->e_flags); @@ -5985,7 +6649,7 @@ _bfd_e2k_elf_object_p_1 (bfd *abfd, /* Information about ABI is encoded into machine number nowadays. */ - mach *= 3; + mach *= 4; if (pm) mach += 2; else if (! ABI_64_P (abfd)) @@ -6054,6 +6718,26 @@ _bfd_e2k_elf_link_setup_gnu_properties (struct bfd_link_info *info) `.text.selfinit' and `.data.export_pl' sections. */ if (htab->elf.dynobj && ABI_PM_P (htab->elf.dynobj)) { + /* Now that "_end" is defined conditionally (i.e. via PROVIDE ()) in + shared libraries we need to refer to it so as not to be left without + its definition when it comes to setting the value of DT_PLTGOTSZ. Note + that it seems to be too late to take care of that both in `{size, + finish}_dynamic_sections ()', but quite OK to do this here. */ + if (bfd_link_dll (info) + /* This should prevent us from creating a reference if "_end" has + already been referred to from an input relocatable object. FIXME: + can't this happen after we create a reference here? Aren't the two + references going to interfere in some unpredictable way? */ + && elf_link_hash_lookup (elf_hash_table (info), "_end", FALSE, + FALSE, TRUE) == NULL) + { + if (! _bfd_generic_link_add_one_symbol (info, htab->elf.dynobj, + "_end", 0, + bfd_und_section_ptr, 0, + NULL, FALSE, FALSE, + NULL)) + return FALSE; + } /* FIXME: the use of `bfd_make_section ()' here results in a section filled in with zeroes despite the fact that I allocate its contents and set it up appropriately. */ @@ -6068,31 +6752,43 @@ _bfd_e2k_elf_link_setup_gnu_properties (struct bfd_link_info *info) (SEC_LINKER_CREATED | SEC_HAS_CONTENTS)); /* Ensure that ".data.export_pl" is appropriately aligned in PM. */ - if (!bfd_set_section_alignment (htab->elf.dynobj, htab->export_pl, 4)) - info->callbacks->einfo (_("%F%A: failed to align section\n"), + if (!bfd_set_section_alignment (htab->export_pl, 4)) + info->callbacks->einfo (_("%F%pA: failed to align section\n"), htab->export_pl); - + htab->export_pl->size = 0; } return pbfd; } +struct plt_symbol_indices +{ + int *rel_indices; +}; + static bfd_vma * _bfd_e2k_elf_plt_sym_val (bfd *abfd, asymbol **dynsyms, asection *plt, asection *relplt, - int kind) + int kind, + void *dummy) { bfd_boolean (*slurp_relocs) (bfd *, asection *, asymbol **, bfd_boolean); - arelent *rel; - asection *got; - bfd_byte *got_contents; + asection *got = NULL; + bfd_byte *got_contents = NULL; bfd_byte *plt_contents = plt->contents; long i, count; + long j; bfd_vma *plt_sym_val; Elf_Internal_Shdr *hdr; + bfd_vma off; + bfd_boolean abi64 = ABI_64_P (plt->owner); + bfd_vma addr_in_got; + int max_plt_entries_num; + int *plt_rel_idx; + arelent *rel = relplt->relocation; if (plt_contents == NULL) { @@ -6117,6 +6813,8 @@ _bfd_e2k_elf_plt_sym_val (bfd *abfd, if (kind == 1) { + /* .got is required only for calculation of "@secondary_plt" synthetic + symbols. */ got = bfd_get_section_by_name (abfd, ".got"); got_contents = got->contents; if (got_contents == NULL) @@ -6141,137 +6839,252 @@ _bfd_e2k_elf_plt_sym_val (bfd *abfd, return NULL; hdr = &elf_section_data (relplt)->this_hdr; + /* The number of relocations in .rela.plt for `kind == {0,1}' and in + .rela.dyn for `kind == 2'. */ count = relplt->size / hdr->sh_entsize; plt_sym_val = (bfd_vma *) bfd_malloc (sizeof (bfd_vma) * count); if (plt_sym_val == NULL) return NULL; + if (kind == 0) + { + /* Allocate array storing relocation indices matching primary PLT entries + in the assumption that there are at most 8 entries for now. It'll be + reallocated later if needed. */ + max_plt_entries_num = 8; + plt_rel_idx = (int *) bfd_malloc (max_plt_entries_num * sizeof (int)); + if (plt_rel_idx == NULL) + { + free (plt_sym_val); + return NULL; + } + } + else + { + /* Use the array prepared during invocation with KIND == 0. */ + struct plt_symbol_indices *plt_inds + = (struct plt_symbol_indices *) dummy; + plt_rel_idx = plt_inds->rel_indices; + } + + + /* -1 means that no symbol of KIND matching the i-th relocation entry has + been found. */ for (i = 0; i < count; i++) plt_sym_val[i] = -1; - rel = relplt->relocation; - for (i = 0; i < count; i++, rel++) + + for (off = 0, j = 0; off < plt->size;) { - bfd_vma off; - bfd_boolean abi64 = ABI_64_P (plt->owner); + bfd_vma next_off; + bfd_vma hs = H_GET_32 (plt->owner, plt_contents + off); - for (off = 0; off < plt->size;) - { - bfd_vma next_off; - bfd_vma hs = H_GET_32 (plt->owner, plt_contents + off); + /* Secondary PLT entries are shared between 32/64-bit modes. Skip a + new-style secondary PLT entry. */ + if (hs == plt_got_secondary_entry[0]) + { + off += 0x20; + continue; + } + /* Skip an old-style secondary PLT entry. It's not used within this + backend anywhere except for this point, therefore an immediate + value for it is used in the comparison below. */ + else if (hs == 0x0400c023) + { + off += 0x20; + continue; + } + else if (abi64) + { + /* Skip PIC and non-PIC PLT headers. */ + if (hs == plt64_got_non_pic_header[0]) + { + off += sizeof (plt64_got_non_pic_header); + continue; + } + else if ((hs & 0xfffffc7f) + == (plt64_got_pic_header[0] & 0xfffffc7f)) + { + off += sizeof (plt64_got_pic_header); + continue; + } + /* This is a primary PLT entry which the address of the related entry + in .got may be extracted from and thereby the correspondence with + the dynamic relocation be established. */ + else if (hs == plt64_got_non_pic_primary_entry[0] + || ((hs & 0xfffffc7f) + == (plt64_got_pic_primary_entry[0] & 0xfffffc7f))) + { + /* Handle non-PIC primary PLT entry. */ + if (hs == plt64_got_non_pic_primary_entry[0]) + { + addr_in_got = ((H_GET_32 (plt->owner, + plt_contents + off + 12) << 32) + + H_GET_32 (plt->owner, + plt_contents + off + 16)); + next_off = off + sizeof (plt64_got_non_pic_primary_entry); + } + else + /* Process PIC one. */ + { + addr_in_got = plt->vma + off; + addr_in_got += (int) H_GET_32 (plt->owner, + plt_contents + off + 36); + next_off = off + sizeof (plt64_got_pic_primary_entry); + } + } + /* PLT is damaged and can't be parsed to the end. Let the caller + benefit from partial results of our job. Note that for subsequent + KINDs we should break here as well, which is why there is no risk + of violating plt_rel_idx[] boundaries. */ + else + return plt_sym_val; + } + else /* if (!abi64) */ + { + /* Skip PIC and non-PIC PLT headers. */ + if (hs == plt32_got_non_pic_header[0]) + { + off += sizeof (plt32_got_non_pic_header); + continue; + } + else if ((hs & 0xfffffc7f) + == (plt32_got_pic_header[0] & 0xfffffc7f)) + { + off += sizeof (plt32_got_pic_header); + continue; + } + /* This is a primary PLT entry which the address of the related entry + in .got may be extracted from and thereby the correspondence with + the dynamic relocation be established. */ + else if (hs == plt32_got_non_pic_primary_entry[0] + || ((hs & 0xfffffc7f) + == (plt32_got_pic_primary_entry[0] & 0xfffffc7f))) + { + /* Handle non-PIC primary PLT entry. */ + if (hs == plt32_got_non_pic_primary_entry[0]) + { + addr_in_got = H_GET_32 (plt->owner, + plt_contents + off + 16); + next_off = off + sizeof (plt32_got_non_pic_primary_entry); + } + /* Process PIC one. */ + else + { + addr_in_got = plt->vma + off; + addr_in_got += (int) H_GET_32 (plt->owner, + plt_contents + off + 36); + next_off = off + sizeof (plt32_got_pic_primary_entry); + } + } + /* PLT is damaged and can't be parsed to the end. Let the caller + benefit from partial results of our job. Note that for subsequent + KINDs we should break here as well, which is why there is no risk + of violating plt_rel_idx[] boundaries. */ + else + return plt_sym_val; + } - /* Secondary PLT entries are shared between 32/64-bit modes. Skip a - new-style secondary PLT entry. */ - if (hs == plt_got_secondary_entry[0]) - off += 0x20; - /* Skip an old-style secondary PLT entry. It's not used within this - backend anywhere except for this point, therefore an immediate - value for it is used in the comparison below. */ - else if (hs == 0x0400c023) - off += 0x20; - else if (abi64) - { - if (hs == plt64_got_non_pic_header[0]) - off += sizeof (plt64_got_non_pic_header); - else if ((hs & 0xfffffc7f) - == (plt64_got_pic_header[0] & 0xfffffc7f)) - off += sizeof (plt64_got_pic_header); - else if (hs == plt64_got_non_pic_primary_entry[0] - || ((hs & 0xfffffc7f) - == (plt64_got_pic_primary_entry[0] & 0xfffffc7f))) - { - /* Handle non-PIC primary PLT entry. */ - bfd_vma addr_in_got; + /* We are looking for either "@plt" or "@plt.got" symbol matching the + currently processed primary PLT entry. Searching the latter makes + sense only if the former hasn't been found, since there should be no + .rela.dyn and .rela.plt dynamic relocations corresponding to the same + primary PLT entry. This saves one the trouble of iterating through a + potentially huge .rela.dyn for most hopeless primary PLT entries.*/ + if (kind == 0 + || (kind == 2 + /* If there's .rela.dyn but no .rela.plt in ABFD this function + may be called with KIND == 2 only, in which case there's no + `plt_rel_idx[]'. */ + && (plt_rel_idx == NULL + || plt_rel_idx[j] == -1))) + { + if (kind == 0 && j == max_plt_entries_num) + { + /* There are more primary PLT entries than one supposed. */ + max_plt_entries_num *= 2; + plt_rel_idx = bfd_realloc (plt_rel_idx, + max_plt_entries_num * sizeof (int)); + if (plt_rel_idx == NULL) + { + free (plt_sym_val); + return NULL; + } + } - if (hs == plt64_got_non_pic_primary_entry[0]) - { - addr_in_got = ((H_GET_32 (plt->owner, - plt_contents + off + 12) << 32) - + H_GET_32 (plt->owner, - plt_contents + off + 16)); - next_off = off + sizeof (plt64_got_non_pic_primary_entry); - } - else - { - addr_in_got = plt->vma + off; - addr_in_got += (int) H_GET_32 (plt->owner, - plt_contents + off + 36); - next_off = off + sizeof (plt64_got_pic_primary_entry); - } + /* Look for the matching dynamic relocation in `.rela.{plt,dyn}' + starting from the index next to the previous hit in hope that + primary PLT entries have more or less the same order as their + matching relocations. */ + for (i = 0; i < count; i++, rel++) + { + /* Resume from the beginning if the upper boundary has been + crossed. */ + if (rel == relplt->relocation + count) + rel = relplt->relocation; - if (addr_in_got == rel->address) - { - if (kind == 0 || kind == 2) - { - plt_sym_val[i] = plt->vma + off; - break; - } - else if (addr_in_got >= got->vma - && addr_in_got < got->vma + got->size) - { - plt_sym_val[i] - = H_GET_64 (got->owner, - got_contents + addr_in_got - got->vma); - break; - } - } + if (addr_in_got == rel->address) + { + int k = rel - relplt->relocation; + plt_sym_val[k] = plt->vma + off; - off = next_off; - } - else - return NULL; - } - else /* if (!abi64) */ - { - if (hs == plt32_got_non_pic_header[0]) - off += sizeof (plt32_got_non_pic_header); - else if ((hs & 0xfffffc7f) - == (plt32_got_pic_header[0] & 0xfffffc7f)) - off += sizeof (plt32_got_pic_header); - else if (hs == plt32_got_non_pic_primary_entry[0] - || ((hs & 0xfffffc7f) - == (plt32_got_pic_primary_entry[0] & 0xfffffc7f))) - { - bfd_vma addr_in_got; + /* Save the index of the matching .rela.plt entry. There's no + point in doing so when processing .rela.dyn as there'll be + no subsequent invocations. */ + if (kind == 0) + plt_rel_idx[j] = k; - if (hs == plt32_got_non_pic_primary_entry[0]) - { - addr_in_got = H_GET_32 (plt->owner, - plt_contents + off + 16); - next_off = off + sizeof (plt32_got_non_pic_primary_entry); - } - else - { - addr_in_got = plt->vma + off; - addr_in_got += (int) H_GET_32 (plt->owner, - plt_contents + off + 36); - next_off = off + sizeof (plt32_got_pic_primary_entry); - } + /* Ensure that the search for the relocation matching the + next primary PLT entry starts from the next one in + `.rela.{plt,dyn}'. */ + rel++; + break; + } + } - if (addr_in_got == rel->address) - { - if (kind == 0 || kind == 2) - { - plt_sym_val[i] = plt->vma + off; - break; - } - else if (addr_in_got >= got->vma - && addr_in_got < got->vma + got->size) - { - plt_sym_val[i] - = H_GET_32 (got->owner, - got_contents + addr_in_got - got->vma); - break; - } - } + /* No .rela.plt relocation matching this primary PLT entry has + been found. Make it clear that one may hope to find the one + in .rela.dyn. */ + if (kind == 0 && i == count) + plt_rel_idx[j] = -1; + } + /* "@secondary_plt" symbol may exist only if the related "@plt" + one does. */ + else if (kind == 1 && plt_rel_idx[j] != -1) + { + /* There is no point in looking for its relocation index as it + coincides with the one of the "@plt" one. As for its address + it's read from .got. */ + if (addr_in_got >= got->vma + && addr_in_got < got->vma + got->size) + { + bfd_vma secondary_plt_vma; +#define H_GET_XX(o, p) abi64 ? H_GET_64 (o, p) : H_GET_32 (o, p) + secondary_plt_vma + = H_GET_XX (got->owner, + got_contents + addr_in_got - got->vma); +#undef H_GET_XX + /* Ensure that the obtained "@secondary_plt" symbol's address + does actually belong to .plt to be on the safe side. */ + if (secondary_plt_vma >= plt->vma + && secondary_plt_vma < plt->vma + plt->size) + plt_sym_val[plt_rel_idx[j]] = secondary_plt_vma; + } + } - off = next_off; - } - else - return NULL; - } - } + /* Proceed to the next J'th anticipated primary PLT entry which may be + located at NEXT_OFF or further. */ + j++; + off = next_off; + } + + /* Save plt_rel_idx[] for subsequent invocations. */ + if (kind == 0) + { + struct plt_symbol_indices *plt_inds + = (struct plt_symbol_indices *) dummy; + plt_inds->rel_indices = plt_rel_idx; } return plt_sym_val; @@ -6294,6 +7107,11 @@ _bfd_e2k_elf_get_synthetic_symtab (bfd *abfd, size_t size; char *names; long n; + struct plt_symbol_indices plt_sym_ind; + + /* This may remain uninitialized if `_bfd_e2k_elf_plt_sym_val ()' is not + called, for example, if there's no PLT in the disassembled file. */ + plt_sym_ind.rel_indices = NULL; for (i = 0; i < 3; i++) { @@ -6302,9 +7120,14 @@ _bfd_e2k_elf_get_synthetic_symtab (bfd *abfd, &sarr[i], plt, /* Primary or secondary PLT entry or `plt.got' entry. */ i, + &plt_sym_ind, & _bfd_e2k_elf_plt_sym_val); } + /* Free it only if it has really been allocated. */ + if (plt_sym_ind.rel_indices) + free (plt_sym_ind.rel_indices); + if (res[0] == -1 && res[1] == -1 && res[2] == -1) return -1; @@ -6357,10 +7180,9 @@ _bfd_e2k_elf_get_synthetic_symtab (bfd *abfd, -void -_bfd_e2k_elf_post_process_headers_1 (bfd *abfd, - struct bfd_link_info *info, - bfd_boolean protected_mode ATTRIBUTE_UNUSED) +bfd_boolean +_bfd_e2k_elf_init_file_header (bfd *abfd, + struct bfd_link_info *info) { Elf_Internal_Ehdr *i_ehdrp; unsigned int mach; @@ -6368,7 +7190,7 @@ _bfd_e2k_elf_post_process_headers_1 (bfd *abfd, i_ehdrp = elf_elfheader (abfd); /* Filter out info concerning ABI. */ - mach = bfd_get_mach (abfd) / 3; + mach = bfd_get_mach (abfd) / 4; /* Presumably this function is useless when called either by OBJCOPY or STRIP because all `e_flags' should be converted via the `copy_private @@ -6382,7 +7204,7 @@ _bfd_e2k_elf_post_process_headers_1 (bfd *abfd, if (output_new_e_machine) goto set_elf_osabi; - return; + return TRUE; } /* These flags are the same both for EM_E2K_OLD and EM_MCST_ELBRUS. I guess @@ -6412,7 +7234,7 @@ _bfd_e2k_elf_post_process_headers_1 (bfd *abfd, if (_bfd_e2k_elf_hash_table (info)) { /* In protected mode set an ancient PM semantic == 5. */ - if (abfd->arch_info->mach % 3 == 2) + if (abfd->arch_info->mach % 4 == 2) i_ehdrp->e_ident[7] = 5; else { @@ -6432,22 +7254,22 @@ _bfd_e2k_elf_post_process_headers_1 (bfd *abfd, set_elf_osabi: i_ehdrp->e_flags |= EF_E2K_MACH_TO_FLAG (mach); - if (abfd->arch_info->mach % 3 == 2) - i_ehdrp->e_flags |= EF_E2K_PM; + if (abfd->arch_info->mach % 4 == 2) + { + i_ehdrp->e_flags |= EF_E2K_PM; + if (pack_cud_gd) + i_ehdrp->e_flags |= EF_E2K_PACK_SEGMENTS; + } /* This sets e_ident[EI_OSABI == 7] in ELF header only. Nevertheless I wonder how I managed to do without it when creating new-style ELFs via binutils-2.18. Probably it worked because ELFOSABI_NONE, which is set by default, equals to zero. */ - _bfd_elf_post_process_headers (abfd, info); + if (! _bfd_elf_init_file_header (abfd, info)) + return FALSE; } -} -void -_bfd_e2k_elf_post_process_headers (bfd *abfd, - struct bfd_link_info *info) -{ - _bfd_e2k_elf_post_process_headers_1 (abfd, info, FALSE); + return TRUE; } bfd_boolean @@ -6486,8 +7308,8 @@ _bfd_e2k_elf_copy_private_bfd_data_1 (bfd *ibfd, bfd *obfd, if (iflags & EF_E2K_INCOMPAT) { _bfd_error_handler - (_("New style object %B with `EF_E2K_INCOMPAT' flag cannot be " - "converted to an old style %B"), ibfd, obfd); + (_("New style object %pB with `EF_E2K_INCOMPAT' flag cannot be " + "converted to an old style %pB"), ibfd, obfd); return FALSE; } @@ -6800,7 +7622,7 @@ _bfd_e2k_elf_check_directives (bfd *abfd, struct bfd_link_info *info) asection *s; /* What flags should be specified here? */ s = bfd_make_section_with_flags (abfd, ".dsp_mem", SEC_ALLOC); - bfd_set_section_alignment (abfd, s, 12); + bfd_set_section_alignment (s, 12); s->size = 2560 * 1024; } } diff --git a/bfd/elfxx-e2k.h b/bfd/elfxx-e2k.h index b178808ac6..488ccc9e58 100644 --- a/bfd/elfxx-e2k.h +++ b/bfd/elfxx-e2k.h @@ -72,12 +72,14 @@ struct _bfd_e2k_elf_link_hash_table /* PLTGOT header, its size and offsets at which it should be adjusted at link time. */ const unsigned int *plt_got_header; + unsigned int plt_got_header_nop_offset; unsigned int plt_got_link_map_ld_offset; unsigned int plt_got_dl_fixup_ld_offset; unsigned int plt_got_header_size; const unsigned int *plt_got_primary_entry; + unsigned int plt_got_entry_nop_offset; unsigned int plt_got_target_ld_offset; unsigned int plt_got_primary_entry_size; @@ -136,6 +138,9 @@ struct _bfd_e2k_elf_link_hash_table /* The numbers of primary and secondary PLT entries in the current link. */ bfd_vma primary_plt_num; bfd_vma secondary_plt_num; + + int ranges_num; + void *ranges; }; /* This variable should be accessible from multiple modules. Moreover, it @@ -185,7 +190,7 @@ extern bfd_boolean _bfd_e2k_elf_final_link /* Methods of struct elf_backend_data */ -extern void _bfd_e2k_elf_info_to_howto +extern bfd_boolean _bfd_e2k_elf_info_to_howto (bfd *, arelent *, Elf_Internal_Rela *); extern bfd_boolean _bfd_e2k_elf_add_symbol_hook @@ -221,6 +226,8 @@ extern unsigned int _bfd_e2k_elf_action_discarded extern bfd_boolean simulating_mode; +//extern bfd_boolean pack_cud_gd; + extern int simulate_relocate_section (bfd *input_bfd, asection *input_section, bfd_byte *contents, @@ -243,10 +250,7 @@ _bfd_e2k_elf_reloc_type_class (const struct bfd_link_info *, extern bfd_boolean _bfd_e2k_elf_finish_dynamic_sections (bfd *, struct bfd_link_info *); -extern void _bfd_e2k_elf_post_process_headers_1 - (bfd *, struct bfd_link_info *, bfd_boolean); - -extern void _bfd_e2k_elf_post_process_headers +extern bfd_boolean _bfd_e2k_elf_init_file_header (bfd *, struct bfd_link_info *); extern bfd_boolean _bfd_e2k_elf_ignore_discarded_relocs @@ -287,7 +291,8 @@ extern long _bfd_e2k_elf_get_synthetic_symtab extern void _bfd_e2k_elf_after_parse (int); extern void _bfd_e2k_elf_after_open (int, int, int, bfd_boolean, bfd_boolean, - bfd_boolean, bfd_boolean, bfd_boolean); + bfd_boolean, bfd_boolean, bfd_boolean, + bfd_boolean); extern const struct bfd_elf_special_section _bfd_e2k_elf_special_sections[]; diff --git a/bfd/elfxx-sparc.c b/bfd/elfxx-sparc.c index bd046aca6c..592c2f40f0 100644 --- a/bfd/elfxx-sparc.c +++ b/bfd/elfxx-sparc.c @@ -2294,6 +2294,16 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) return FALSE; } } + + /* Input relocations in `.rela.xxx' sections against ifunctions defined + in regular object files are not copied to the output file (see how + they are treated in relocate_section () below). Therefore, avoid + allocating redundant space for them below. The failure to recognize + this issue turned out to be the reason for Bugs #81941 and #88486. */ + if (h->dyn_relocs != NULL + && h->type == STT_GNU_IFUNC + && h->def_regular) + h->dyn_relocs = NULL; } else { @@ -2424,6 +2434,20 @@ _bfd_sparc_elf_size_dynamic_sections (bfd *output_bfd, { struct elf_dyn_relocs *p; + /* Don't allocate space for dynamic relocations not only if the + section to which they are applied is discarded (condition in the + loop a few lines below takes care of that), but also if the section + "against" which they are resolved is. This lets me resolve an issue + when LD manages without creation of dynamic relocations against + discarded `.gnu.linkonce'-sections within kept `.eh_frame's (as you + remember the contents of the latter is modified somehow to + eliminate the need for dynamic relocations then): allocation of + redundant space would lead to an assertion failure described in + Bug #79553. For a more detailed example see the commit. */ + if (!bfd_is_abs_section (s) + && bfd_is_abs_section (s->output_section)) + continue; + for (p = elf_section_data (s)->local_dynrel; p != NULL; p = p->next) { if (!bfd_is_abs_section (p->sec) @@ -4737,20 +4761,29 @@ _bfd_sparc_elf_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *i ? 0 : htab->plt_entry_size); } - /* Set the first entry in the global offset table to the address of - the dynamic section. */ - if (htab->elf.sgot && htab->elf.sgot->size > 0) - { - bfd_vma val = (sdyn ? - sdyn->output_section->vma + sdyn->output_offset : - 0); - - SPARC_ELF_PUT_WORD (htab, output_bfd, val, htab->elf.sgot->contents); - } - if (htab->elf.sgot) - elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize = - SPARC_ELF_WORD_BYTES (htab); + { + if (bfd_is_abs_section (htab->elf.sgot->output_section)) + { + _bfd_error_handler + (_("discarded output section: `%pA'"), htab->elf.sgot); + return FALSE; + } + + /* Set the first entry in the global offset table to the address of + the dynamic section. */ + if (htab->elf.sgot->size > 0) + { + bfd_vma val = (sdyn ? + sdyn->output_section->vma + sdyn->output_offset : + 0); + + SPARC_ELF_PUT_WORD (htab, output_bfd, val, htab->elf.sgot->contents); + } + + elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize = + SPARC_ELF_WORD_BYTES (htab); + } /* Fill PLT and GOT entries for local STT_GNU_IFUNC symbols. */ htab_traverse (htab->loc_hash_table, finish_local_dynamic_symbol, info); @@ -4805,11 +4838,23 @@ _bfd_sparc_elf_object_p (bfd *abfd) | ELF_SPARC_HWCAP2_RLE | ELF_SPARC_HWCAP2_SHA3); + unsigned int r2000_hwcaps_mask = ELF_SPARC_HWCAP_SAPPHIRE; + unsigned int r2000_plus_hwcaps2_mask = ELF_SPARC_HWCAP2_SAPPHIRE_PLUS; + if (ABI_64_P (abfd)) { unsigned long mach = bfd_mach_sparc_v9; - if (hwcaps2->i & m8_hwcaps2_mask) + if (elf_elfheader (abfd)->e_flags & EF_SPARC_MCST) + { + if (hwcaps2->i & r2000_plus_hwcaps2_mask) + mach = bfd_mach_sparc_v9_r2000_plus; + else if (hwcaps->i & r2000_hwcaps_mask) + mach = bfd_mach_sparc_v9_r2000; + else + mach = bfd_mach_sparc_v9_r1000; + } + else if (hwcaps2->i & m8_hwcaps2_mask) mach = bfd_mach_sparc_v9m8; else if (hwcaps2->i & v9m_hwcaps2_mask) mach = bfd_mach_sparc_v9m; @@ -4831,7 +4876,20 @@ _bfd_sparc_elf_object_p (bfd *abfd) { if (elf_elfheader (abfd)->e_machine == EM_SPARC32PLUS) { - if (hwcaps2->i & m8_hwcaps2_mask) + if (elf_elfheader (abfd)->e_flags & EF_SPARC_MCST) + { + if (hwcaps2->i & r2000_plus_hwcaps2_mask) + return + bfd_default_set_arch_mach (abfd, bfd_arch_sparc, + bfd_mach_sparc_v8plus_r2000_plus); + else if (hwcaps->i & r2000_hwcaps_mask) + return bfd_default_set_arch_mach (abfd, bfd_arch_sparc, + bfd_mach_sparc_v8plus_r2000); + else + return bfd_default_set_arch_mach (abfd, bfd_arch_sparc, + bfd_mach_sparc_v8plus_r1000); + } + else if (hwcaps2->i & m8_hwcaps2_mask) return bfd_default_set_arch_mach (abfd, bfd_arch_sparc, bfd_mach_sparc_v8plusm8); else if (hwcaps2->i & v9m_hwcaps2_mask) @@ -4933,3 +4991,380 @@ _bfd_sparc_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) return TRUE; } + + +/* EIR specific methods. */ + +static int link_mixed_eir_phase; +static bfd_boolean met_eir_section; +static bfd_boolean eir_in_this_bfd; + +void +_bfd_sparc_elf_after_parse (int phase) +{ + link_mixed_eir_phase = phase; +} + +static void +search_eir (bfd *abfd ATTRIBUTE_UNUSED, asection *sect, void *obj ATTRIBUTE_UNUSED) +{ + if (strcmp (sect->name, ".pack_pure_eir") == 0 + || strcmp (sect->name, ".pack_mixed_eir") == 0) + { + met_eir_section = TRUE; + eir_in_this_bfd = TRUE; + } +} + + +static void +discard_unsuitable_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sect, void *obj ATTRIBUTE_UNUSED) +{ + + if ((link_mixed_eir_phase == 1 && met_eir_section) + || (link_mixed_eir_phase == 3 + && (!(met_eir_section && !eir_in_this_bfd) + || abfd->my_archive))) + { + /* SEC_DEBUGGING is required to fool lang_gc_sections in ldlang.c */ + sect->flags |= (SEC_EXCLUDE | SEC_DEBUGGING); + } +} + + +static void +search_pure_eir (bfd *abfd, asection *sec, void *no_pure_eir) +{ + if (strcmp (sec->name, ".pack_pure_eir") == 0) + { + *((bfd_boolean *) no_pure_eir) = FALSE; + _bfd_error_handler ("%pB with '.pack_pure_eir' is illegal during " + "non-relocatable linkage", abfd); + } +} + + +bfd_boolean +_bfd_sparc_elf_link_add_symbols (bfd *abfd, struct bfd_link_info *info) +{ + bfd_boolean ret; + + /* Check for the absence of `.pack_pure_eir' sections during + non-relocatable linkage (see Bug #41413). */ + if (bfd_get_format (abfd) == bfd_object && info + && !bfd_link_relocatable (info)) + { + bfd_boolean no_pure_eir = TRUE; + bfd_map_over_sections (abfd, search_pure_eir, &no_pure_eir); + + if (! no_pure_eir) + return FALSE; + + } + + ret = bfd_elf_link_add_symbols (abfd, info); + + /* COMMON sections are created while COMMON symbols are being + read rather than while parsing input file's section headers. + Therefore, a call to `bfd_elf_link_add_symbols ()' should + precede the following, provided that we need to be able to + discard COMMON sections. And we actually need this (see + Bug #57962). */ + if ((link_mixed_eir_phase == 1 + || link_mixed_eir_phase == 3) + && bfd_get_format (abfd) == bfd_object) + { + eir_in_this_bfd = FALSE; + bfd_map_over_sections (abfd, search_eir, NULL); + bfd_map_over_sections (abfd, discard_unsuitable_section, NULL); + } + + return ret; +} + +bfd_boolean +_bfd_sparc_elf_final_link (bfd *abfd, struct bfd_link_info *info) +{ + /* There is nothing to be done here if we are going to output + a binary file when linking EIR (see Bug #59012, Comment # ). */ + if (link_mixed_eir_phase == 2) + return TRUE; + + return bfd_elf_final_link (abfd, info); +} + +bfd_boolean +_bfd_sparc_elf_ignore_discarded_relocs (asection *sec) +{ + bfd *abfd; + size_t locsymcount; + Elf_Internal_Shdr *symtab_hdr; + Elf_Internal_Rela *internal_relocs; + Elf_Internal_Rela *rel, *relend; + struct elf_link_hash_entry **sym_hashes; + const struct elf_backend_data *bed; + int r_sym_shift; + + if (link_mixed_eir_phase != 1 + && link_mixed_eir_phase !=3) + return FALSE; + + abfd = sec->owner; + symtab_hdr = &elf_tdata (abfd)->symtab_hdr; + locsymcount = symtab_hdr->sh_info; + + bed = get_elf_backend_data (abfd); + + internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL, FALSE); + rel = internal_relocs; + relend = rel + sec->reloc_count * bed->s->int_rels_per_ext_rel; + + r_sym_shift = (bed->s->arch_size == 32) ? 8 : 32; + + + sym_hashes = elf_sym_hashes (abfd); + for ( ; rel < relend; rel++) + { + unsigned long r_symndx = rel->r_info >> r_sym_shift; + struct elf_link_hash_entry *h = NULL; + + if (r_symndx == STN_UNDEF) + continue; + + if (r_symndx >= locsymcount) + { + h = sym_hashes[r_symndx - locsymcount]; + + while (h->root.type == bfd_link_hash_indirect + || h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; + + if (((h->root.type == bfd_link_hash_defined + || h->root.type == bfd_link_hash_defweak) + && discarded_section (h->root.u.def.section)) + /* Don't forget about common symbols. Their sections may + very well be discarded as well. */ + || (h->root.type == bfd_link_hash_common + && discarded_section (h->root.u.c.p->section))) +#if 0 + /* I don't have legal access to this (link) info . . . */ + && (h->root.u.def.next || . . .) +#endif /* 0 */ + { + /* Stupidly make it undefined. Is it going to work? */ + h->root.type = bfd_link_hash_undefined; + } + } + } + + /* free (internal_relocs); */ + return TRUE; +} + +void +_bfd_sparc_elf_hide_symbol (struct bfd_link_info *info, + struct elf_link_hash_entry *h, + bfd_boolean force_local) +{ + /* I don't want to hide (make local) symbols from unsuitable + (SEC_EXCLUDE | SEC_DEBUGGING) sections + (see discard_unsuitable_section () before) in EIR linkage + mode. Prevent the code in `elf_link_add_object_symbols ()' + from achieving this. Interestingly enough, there is no attempt + to hide these symbols in binutils-2.21. */ + + if (link_mixed_eir_phase != 1 && link_mixed_eir_phase != 3) + _bfd_elf_link_hash_hide_symbol (info, h, force_local); +} + +struct write_eir_info +{ + bfd_size_type max_size; + bfd_byte *contents; + /* This is set to FALSE if `_bfd_e2k_write_eir_contens ()' fails + for any section. */ + bfd_boolean res; +}; + +static void +write_eir_contents (bfd *abfd ATTRIBUTE_UNUSED, + asection *s, + void *param) +{ + static bfd_vma s_offset; + bfd_vma next_s_offset; + bfd_vma mask; + struct bfd_link_order *p; + struct write_eir_info *wei; + + /* There is nothing to do for non-EIR sections. */ + if (strcmp (s->name, ".pack_pure_eir") != 0 + && strcmp (s->name, ".pack_mixed_eir") != 0) + return; + + wei = (struct write_eir_info *) param; + /* If we've already failed, there is no point in continuing. */ + if (wei->res == FALSE) + return; + + mask = (1 << s->alignment_power) - 1; + s_offset = (s_offset + mask) & ~mask; + next_s_offset = s_offset; + + for (p = s->map_head.link_order; p != NULL; p = p->next) + { + asection *i; + + if (p->type != bfd_indirect_link_order) + continue; + + i = p->u.indirect.section; + + if (i->size > 0) + { + if (i->size > wei->max_size) + { + wei->max_size = i->size; + wei->contents = (bfd_byte *) bfd_realloc (wei->contents, + wei->max_size); + } + + if (s_offset + i->output_offset + i->size > next_s_offset) + next_s_offset = s_offset + i->output_offset + i->size; + + if (! bfd_get_section_contents (i->owner, i, wei->contents, + 0, i->size) + || bfd_seek (abfd, s_offset + i->output_offset, SEEK_SET) != 0 + || bfd_bwrite (wei->contents, i->size, abfd) != i->size) + { + wei->res = FALSE; + return; + } + } + } + + /* Setting initial `s_offset' value for the next invocation. */ + s_offset = next_s_offset; +} + + +/* This function gets called when BFD is being closed. Avoid calling + an ELF-specific method (which outputs strtab, . . .) when a raw + binary for EIR is required. */ +bfd_boolean +_bfd_sparc_elf_write_object_contents (bfd *abfd) +{ + struct write_eir_info wei; + + if (link_mixed_eir_phase != 2) + return _bfd_elf_write_object_contents (abfd); + + wei.max_size = 0; + wei.contents = NULL; + wei.res = TRUE; + + /* Calculating positions of EIR sections and setting their contents. */ + bfd_map_over_sections (abfd, write_eir_contents, &wei); + + if (wei.contents) + free (wei.contents); + + return wei.res; +} + + +/* This is a helper of `_bfd_sparc_elf_check_magic () below. */ +static bfd_boolean +check_magic (bfd *abfd, asection *magic_sec) +{ + char *magic = getenv ("MAGIC"); + size_t magic_size; + char *data; + bfd_boolean res = FALSE; + + BFD_ASSERT (magic); + magic_size = strlen (magic) + 1; + + data = xmalloc (magic_sec->size); + if (! bfd_get_section_contents (abfd, magic_sec, data, 0, magic_sec->size)) + { + _bfd_error_handler (_("%pB: cannot read contents of section %pA\n"), + abfd, magic_sec); + } + + if (magic_sec->size == (12 + ((sizeof ("MCST") + 3) & 0xfffffffc) + + ((magic_size + 3) & 0xfffffffc)) + && bfd_get_32 (abfd, data) == sizeof ("MCST") + && bfd_get_32 (abfd, data + 4) == magic_size + && bfd_get_32 (abfd, data + 8) == NT_MAGIC + && data[12 + sizeof ("MCST") - 1] == '\0' + && data[12 + ((sizeof ("MCST") + 3) & 0xfffffffc) + + magic_size - 1] == '\0' + && strncmp (data + 12, "MCST", sizeof ("MCST") - 1) == 0 + && strncmp (data + 12 + ((sizeof ("MCST") + 3) & 0xfffffffc), magic, + magic_size - 1) == 0) + res = TRUE; + + free (data); + return res; +} + + +/* This function is required to implement MCST-specific MAGIC checks + (see Bug #67430). It gets called from `elf{32,64}_sparc_merge_private_bfd + _data ()' so that they don't have a chance to `return TRUE' without + performing this test (see their code just after the call to this function + for how it may happen). + + FIXME: this function replicates the analogous part of + `_bfd_e2k_elf_merge_private_bfd_data_1 ()' in `elfxx-e2k.c'. Get rid of this + awful Copy/Paste by placing them in some common (for E2K and Sparc) source + file. Its`check_magic ()' helper and EIR-specific functions should probably + go there as well. */ + +bfd_boolean +_bfd_sparc_elf_check_magic (bfd *ibfd) +{ + if (! getenv ("MAGIC")) + return TRUE; + + asection *magic_sec; + static bfd_boolean first_ibfd_saved = TRUE; + bfd_boolean res, first_ibfd = first_ibfd_saved; + + /* Next time `first_ibfd' will be set to FALSE. */ + first_ibfd_saved = FALSE; + + magic_sec = bfd_get_section_by_name (ibfd, ".magic"); + if (magic_sec == NULL) + { + _bfd_error_handler (_("Input object %pB doesn't have a .magic " + "section"), ibfd); + return FALSE; + } + + res = check_magic (ibfd, magic_sec); + /* Exclude this section from output no matter what `check_magic ()' + returned, though it's not absolutely necessary if it failed: we are + not going to have any output in this case. */ + if (! first_ibfd) + { + magic_sec->flags |= SEC_EXCLUDE; + magic_sec->size = 0; + } + + if (! res) + { + _bfd_error_handler (_("Input object %pB contains wrong MAGIC "), + ibfd); + return FALSE; + } + + return TRUE; +} + +const struct bfd_elf_special_section _bfd_sparc_elf_special_sections[] = +{ + { STRING_COMMA_LEN (".magic"), 0, SHT_NOTE, 0 }, + { NULL, 0, 0, 0, 0 } +}; diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h index c2b828b499..ed10364034 100644 --- a/bfd/elfxx-target.h +++ b/bfd/elfxx-target.h @@ -84,7 +84,16 @@ #define bfd_elfNN_set_section_contents _bfd_elf_set_section_contents #endif #define bfd_elfNN_sizeof_headers _bfd_elf_sizeof_headers + +/* We should be able to override this method if output file format + is not ELF as it happens in case of EIR linkage (see Bug #59012, + Comment # ). Take into account that calling `bfd_elf_final_link' + is inappropriate in this case either, since it also performs some + ELF-specific output. */ +#ifndef bfd_elfNN_write_object_contents #define bfd_elfNN_write_object_contents _bfd_elf_write_object_contents +#endif + #define bfd_elfNN_write_corefile_contents _bfd_elf_write_corefile_contents #define bfd_elfNN_get_section_contents_in_window \ @@ -791,7 +800,11 @@ #ifndef elf_backend_symbol_section_index #define elf_backend_symbol_section_index NULL #endif - + +#ifndef elf_backend_r_none_info +#define elf_backend_r_none_info 0 +#endif + #ifndef elf_match_priority #define elf_match_priority \ (ELF_ARCH == bfd_arch_unknown ? 2 : ELF_OSABI == ELFOSABI_NONE ? 1 : 0) @@ -953,7 +966,8 @@ static struct elf_backend_data elfNN_bed = elf_backend_extern_protected_data, elf_backend_always_renumber_dynsyms, elf_backend_linux_prpsinfo32_ugid16, - elf_backend_linux_prpsinfo64_ugid16 + elf_backend_linux_prpsinfo64_ugid16, + elf_backend_r_none_info }; /* Forward declaration for use when initialising alternative_target field. */ diff --git a/bfd/libbfd.h b/bfd/libbfd.h index b97534fc9f..758c4a25d4 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -3392,6 +3392,41 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_CKCORE_PCREL_BLOOP_IMM4BY4", "BFD_RELOC_CKCORE_PCREL_BLOOP_IMM12BY4", "BFD_RELOC_S12Z_OPR", + "BFD_RELOC_E2K_64_ABS_LIT", + "BFD_RELOC_E2K_DISP", + "BFD_RELOC_E2K_GOT", + "BFD_RELOC_E2K_TLS_GDMOD", + "BFD_RELOC_E2K_TLS_GDREL", + "BFD_RELOC_E2K_TLS_IE", + "BFD_RELOC_E2K_32_TLS_LE", + "BFD_RELOC_E2K_64_TLS_LE", + "BFD_RELOC_E2K_32_DTPREL", + "BFD_RELOC_E2K_64_DTPREL", + "BFD_RELOC_E2K_PLT", + "BFD_RELOC_E2K_GOTPLT", + "BFD_RELOC_E2K_ISLOCAL", + "BFD_RELOC_E2K_AP_GOT", + "BFD_RELOC_E2K_PL_GOT", + "BFD_RELOC_E2K_PREF", + "BFD_RELOC_E2K_ISLOCAL32", + "BFD_RELOC_E2K_GOTOFF64", + "BFD_RELOC_E2K_GOTOFF64_LIT", + "BFD_RELOC_E2K_AP", + "BFD_RELOC_E2K_PL", + "BFD_RELOC_E2K_DYNOPT32", + "BFD_RELOC_E2K_DYNOPT64", + "BFD_RELOC_ELCORE32", + "BFD_RELOC_ELCORE16NPC", + "BFD_RELOC_ELCORE16PC", + "BFD_RELOC_ELCORE16S", + "BFD_RELOC_ELCORE16", + "BFD_RELOC_ELCORE5", + "BFD_RELOC_ELCORE32_FAKE", + "BFD_RELOC_ELCORE16NPC_FAKE", + "BFD_RELOC_ELCORE16PC_FAKE", + "BFD_RELOC_ELCORE16S_FAKE", + "BFD_RELOC_ELCORE16_FAKE", + "BFD_RELOC_ELCORE5_FAKE", "@@overflow: BFD_RELOC_UNUSED@@", }; #endif diff --git a/bfd/reloc.c b/bfd/reloc.c index 9aba84ca81..ba9cadce8d 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -8133,6 +8133,126 @@ ENUM ENUMDOC S12Z relocations. +ENUM + BFD_RELOC_E2K_64_ABS_LIT +ENUMDOC + This one corresponds to R_E2K_64_ABS_LIT. +ENUM + BFD_RELOC_E2K_DISP +ENUMDOC + This one corresponds to R_E2K_DISP. +ENUM + BFD_RELOC_E2K_GOT +ENUMDOC + This one corresponds to R_E2K_GOT. +ENUM + BFD_RELOC_E2K_TLS_GDMOD +ENUMDOC + This one corresponds to R_E2K_TLS_GDMOD. +ENUM + BFD_RELOC_E2K_TLS_GDREL +ENUMDOC + This one corresponds to R_E2K_TLS_GDREL. +ENUM + BFD_RELOC_E2K_TLS_IE +ENUMDOC + This one corresponds to R_E2K_TLS_IE. +ENUM + BFD_RELOC_E2K_32_TLS_LE +ENUMDOC + This one corresponds to R_E2K_32_TLS_LE. +ENUM + BFD_RELOC_E2K_64_TLS_LE +ENUMDOC + This one corresponds to R_E2K_64_TLS_LE. +ENUM + BFD_RELOC_E2K_32_DTPREL +ENUMDOC + This one corresponds to R_E2K_TLS_32_DTPREL. +ENUM + BFD_RELOC_E2K_64_DTPREL +ENUMDOC + This one corresponds to R_E2K_TLS_64_DTPREL. +ENUM + BFD_RELOC_E2K_PLT +ENUMDOC + This one corresponds to R_E2K_PLT. +ENUM + BFD_RELOC_E2K_GOTPLT +ENUMDOC + This one corresponds to R_E2K_GOTPLT. +ENUM + BFD_RELOC_E2K_ISLOCAL +ENUMDOC + This one corresponds to R_E2K_ISLOCAL. +ENUM + BFD_RELOC_E2K_AP_GOT +ENUMDOC + This one corresponds to R_E2K_AP_GOT. +ENUM + BFD_RELOC_E2K_PL_GOT +ENUMDOC + This one corresponds to R_E2K_PL_GOT. +ENUM + BFD_RELOC_E2K_PREF +ENUMDOC + This one corresponds to R_E2K_PREF. +ENUM + BFD_RELOC_E2K_ISLOCAL32 +ENUMDOC + This one corresponds to R_E2K_ISLOCAL32. +ENUM + BFD_RELOC_E2K_GOTOFF64 +ENUMDOC + This one corresponds to R_E2K_GOTOFF64. +ENUM + BFD_RELOC_E2K_GOTOFF64_LIT +ENUMDOC + This one corresponds to R_E2K_GOTOFF64_LIT. +ENUM + BFD_RELOC_E2K_AP +ENUMDOC + This one corresponds to R_E2K_AP. +ENUM + BFD_RELOC_E2K_PL +ENUMDOC + This one corresponds to R_E2K_PL. +ENUM + BFD_RELOC_E2K_DYNOPT32 +ENUMDOC + This one corresponds to R_E2K_32_DYNOPT. +ENUM + BFD_RELOC_E2K_DYNOPT64 +ENUMDOC + This one corresponds to R_E2K_64_DYNOPT. + +ENUM + BFD_RELOC_ELCORE32 +ENUMX + BFD_RELOC_ELCORE16NPC +ENUMX + BFD_RELOC_ELCORE16PC +ENUMX + BFD_RELOC_ELCORE16S +ENUMX + BFD_RELOC_ELCORE16 +ENUMX + BFD_RELOC_ELCORE5 +ENUMX + BFD_RELOC_ELCORE32_FAKE +ENUMX + BFD_RELOC_ELCORE16NPC_FAKE +ENUMX + BFD_RELOC_ELCORE16PC_FAKE +ENUMX + BFD_RELOC_ELCORE16S_FAKE +ENUMX + BFD_RELOC_ELCORE16_FAKE +ENUMX + BFD_RELOC_ELCORE5_FAKE +ENUMDOC + Elvees Elcore relocations. + ENDSENUM BFD_RELOC_UNUSED CODE_FRAGMENT diff --git a/bfd/targets.c b/bfd/targets.c index d47145be15..64f29094d0 100644 --- a/bfd/targets.c +++ b/bfd/targets.c @@ -710,9 +710,12 @@ extern const bfd_target d10v_elf32_vec; extern const bfd_target d30v_elf32_vec; extern const bfd_target dlx_elf32_be_vec; extern const bfd_target e2k_elf32_vec; -extern const bfd_target e2k_elf64_vec; extern const bfd_target e2k_pm_elf32_vec; +extern const bfd_target e2k_pm_uclibc_elf32_vec; +extern const bfd_target e2k_elf64_vec; extern const bfd_target e2k_kpda_elf64_vec; +extern const bfd_target e2k_pm_elf64_vec; +extern const bfd_target e2k_uclibc_elf64_vec; extern const bfd_target elcore_elf32_vec; extern const bfd_target elcore_elf64_vec; extern const bfd_target elf32_be_vec; diff --git a/binutils/configure b/binutils/configure index 89c99abfeb..a21c9a305f 100755 --- a/binutils/configure +++ b/binutils/configure @@ -15281,6 +15281,14 @@ cat >>confdefs.h <<_ACEOF _ACEOF +case "$target" in + e2k*) + +$as_echo "#define INHIBIT_RAW_INSN 1" >>confdefs.h + + ;; +esac + targ=$target . $srcdir/../bfd/config.bfd if test "x$targ_underscore" = "xyes"; then diff --git a/binutils/objdump.c b/binutils/objdump.c index 93508e2a34..61f1914df1 100644 --- a/binutils/objdump.c +++ b/binutils/objdump.c @@ -97,7 +97,14 @@ static int no_addresses; /* --no-addresses */ static int prefix_addresses; /* --prefix-addresses */ static int with_line_numbers; /* -l */ static bfd_boolean with_source_code; /* -S */ + +#ifndef INHIBIT_RAW_INSN static int show_raw_insn; /* --show-raw-insn */ +#else +static int show_raw_insn = -1; +static int show_raw_insn_fake; +#endif + static int dump_dwarf_section_info; /* --dwarf */ static int dump_stab_section_info; /* --stabs */ static int dump_ctf_section_info; /* --ctf */ @@ -370,7 +377,13 @@ static struct option long_options[]= {"help", no_argument, NULL, 'H'}, {"info", no_argument, NULL, 'i'}, {"line-numbers", no_argument, NULL, 'l'}, - {"no-show-raw-insn", no_argument, &show_raw_insn, -1}, + {"no-show-raw-insn", no_argument, +#ifndef INHIBIT_RAW_INSN + &show_raw_insn, +#else + &show_raw_insn_fake, +#endif + -1}, {"no-addresses", no_argument, &no_addresses, 1}, {"prefix-addresses", no_argument, &prefix_addresses, 1}, {"recurse-limit", no_argument, NULL, OPTION_RECURSE_LIMIT}, @@ -380,7 +393,13 @@ static struct option long_options[]= {"reloc", no_argument, NULL, 'r'}, {"section", required_argument, NULL, 'j'}, {"section-headers", no_argument, NULL, 'h'}, - {"show-raw-insn", no_argument, &show_raw_insn, 1}, + {"show-raw-insn", no_argument, +#ifndef INHIBIT_RAW_INSN + &show_raw_insn, +#else + &show_raw_insn_fake, +#endif + 1}, {"source", no_argument, NULL, 'S'}, {"source-comment", optional_argument, NULL, OPTION_SOURCE_COMMENT}, {"special-syms", no_argument, &dump_special_syms, 1}, diff --git a/binutils/readelf.c b/binutils/readelf.c index 6057515a89..f43227bfd9 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -104,6 +104,7 @@ #include "elf/d30v.h" #include "elf/dlx.h" #include "elf/bpf.h" +#include "elf/e2k.h" #include "elf/epiphany.h" #include "elf/fr30.h" #include "elf/frv.h" @@ -1632,6 +1633,10 @@ dump_relocations (Filedata * filedata, case EM_Z80: rtype = elf_z80_reloc_type (type); break; + + case EM_MCST_ELBRUS: + rtype = elf_e2k_reloc_type (type); + break; } if (rtype == NULL) @@ -2110,6 +2115,22 @@ get_nios2_dynamic_type (unsigned long type) } } +static const char * +get_e2k_dynamic_type (unsigned long type) +{ + switch (type) + { + case DT_E2K_LAZY_GOT: return "E2K_LAZY_GOT"; + case DT_PLTGOTSZ: return "PLTGOTSZ"; + case DT_INIT_GOT: return "INIT_GOT"; + case DT_EXPORT_PL: return "EXPORT_PL"; + case DT_EXPORT_PLSZ: return "EXPORT_PLSZ"; + case DT_REAL_PLTGOT: return "REAL_PLTGOT"; + default: return NULL; + } +} + + static const char * get_solaris_dynamic_type (unsigned long type) { @@ -2268,6 +2289,9 @@ get_dynamic_type (Filedata * filedata, unsigned long type) case EM_ALTERA_NIOS2: result = get_nios2_dynamic_type (type); break; + case EM_MCST_ELBRUS: + result = get_e2k_dynamic_type (type); + break; default: if (filedata->file_header.e_ident[EI_OSABI] == ELFOSABI_SOLARIS) result = get_solaris_dynamic_type (type); @@ -2387,7 +2411,10 @@ get_machine_name (unsigned e_machine) case EM_H8_300: return "Renesas H8/300"; case EM_H8_300H: return "Renesas H8/300H"; case EM_H8S: return "Renesas H8S"; +#if 0 case EM_H8_500: return "Renesas H8/500"; +#endif /* 0 */ + case EM_E2K_OLD: return "MCST Elbrus (old)"; /* 50 */ case EM_IA_64: return "Intel IA-64"; case EM_MIPS_X: return "Stanford MIPS-X"; @@ -3151,7 +3178,11 @@ get_machine_flags (Filedata * filedata, unsigned e_flags, unsigned e_machine) buf[0] = '\0'; - if (e_flags) + if (e_flags + /* We may have `e_flags == 0x0' at E2K which is worth being + described. */ + || e_machine == EM_MCST_ELBRUS + || e_machine == EM_E2K_OLD) { switch (e_machine) { @@ -3624,6 +3655,9 @@ get_machine_flags (Filedata * filedata, unsigned e_flags, unsigned e_machine) if (e_flags & EF_SPARC_SUN_US3) strcat (buf, ", ultrasparcIII"); + if (e_flags & EF_SPARC_MCST) + strcat (buf, ", MCST Sparc"); + if (e_flags & EF_SPARC_HAL_R1) strcat (buf, ", halr1"); @@ -3815,6 +3849,122 @@ get_machine_flags (Filedata * filedata, unsigned e_flags, unsigned e_machine) strcat (buf, _(", unknown")); break; } break; + + case EM_E2K_OLD: + case EM_MCST_ELBRUS: + { + unsigned mach = (e_machine == EM_MCST_ELBRUS + ? EF_E2K_FLAG_TO_MACH (e_flags) + : EF_E2K_OLD_FLAG_TO_MACH (e_flags)); + + switch (mach) + { + case E_E2K_MACH_BASE: + strcat (buf, ", generic"); + break; + case E_E2K_MACH_EV1: + strcat (buf, ", elbrus-v1"); + break; + case E_E2K_MACH_EV2: + /* Forward incompatible `elbrus-v2' ELF is currently interpreted + as `elbrus-2c+'-specific one at least until we have got other + processors of `elbrus-v2' family. */ + strcat (buf, + ((e_flags & EF_E2K_INCOMPAT) + ? ", elbrus-2c+" : ", elbrus-v2")); + break; + case E_E2K_MACH_EV3: + /* Forward incompatible `elbrus-v3' ELF is currently interpreted + as `elbrus-4c'-specific one at least until we have got other + processors of `elbrus-v3' family. */ + strcat (buf, + ((e_flags & EF_E2K_INCOMPAT) + ? ", elbrus-4c" : ", elbrus-v3")); + break; + case E_E2K_MACH_EV4: + strcat (buf, ", elbrus-v4"); + break; + case E_E2K_MACH_EV5: + /* Forward incompatible `elbrus-v5' ELF is interpreted as the + one fine-tuned for `elbrus-8c2' as there are no other + processors in this series. */ + strcat (buf, + ((e_flags & EF_E2K_INCOMPAT) + ? ", elbrus-8c2" : ", elbrus-v5")); + break; + case E_E2K_MACH_EV6: + strcat (buf, ", elbrus-v6"); + break; + case E_E2K_MACH_8C: + strcat (buf, ", elbrus-8c"); + break; + case E_E2K_MACH_1CPLUS: + strcat (buf, ", elbrus-1c+"); + break; + case E_E2K_MACH_12C: + strcat (buf, ", elbrus-12c"); + break; + case E_E2K_MACH_16C: + strcat (buf, ", elbrus-16c"); + break; + case E_E2K_MACH_2C3: + strcat (buf, ", elbrus-2c3"); + break; + default: + strcat (buf, ", unknown elbrus processor"); + break; + } + + /* Only a new-style ELF may be marked as forward incompatible As for + `elbrus-v1' it's considered to be forward incompatible even if + EF_E2K_INCOMPAT isn't set. A forward incompatible `elbrus-v{2,3, + 5}' ELF has already been identified as `elbrus-{2c+,4c,8c2}' + specific above. This flag makes little sense for fine-tuned + `elbrus-{8c,1c+}' and `elbrus-{12c,16c,2c3}' ELFs. Therefore, we + are formally left with generic and `elbrus-v{4,6}' cases here. + They shouldn't be met in practice, though, since there are no + `e2k-linux-{as,ld}' options for producing them. */ + if (e_machine == EM_MCST_ELBRUS + && (mach == E_E2K_MACH_EV1 + || ((e_flags & EF_E2K_INCOMPAT) + && (mach == E_E2K_MACH_BASE + || (mach == E_E2K_MACH_EV4 + || mach == E_E2K_MACH_EV6))))) + strcat (buf, " (forward incompatible)"); + + if (e_machine == EM_MCST_ELBRUS + && (e_flags & EF_E2K_PM)) + { + strcat (buf, " (Protected Mode"); + + if (e_flags & EF_E2K_PACK_SEGMENTS) + strcat (buf, " with packed CUD and GD"); + + strcat (buf, ")"); + } + + switch (e_flags & EF_E2K_IPD) + { + case 1: + strcat (buf, ", ipd 0"); + break; + case 2: + strcat (buf, ", ipd 1"); + break; + case 3: + strcat (buf, ", ipd 2"); + break; + default: + strcat (buf, ", default ipd"); + break; + } + + if (e_flags & EF_E2K_4MB_PAGES) + strcat (buf, ", 4MB pages"); + if (e_flags & EF_E2K_X86APP) + strcat (buf, ", x86 app"); + } + break; } } @@ -3845,6 +3995,7 @@ get_osabi_name (Filedata * filedata, unsigned int osabi) case ELFOSABI_FENIXOS: return "FenixOS"; case ELFOSABI_CLOUDABI: return "Nuxi CloudABI"; case ELFOSABI_OPENVOS: return "Stratus Technologies OpenVOS"; + case ELFOSABI_KPDA: return "KPDA"; default: if (osabi >= 64) switch (filedata->file_header.e_machine) @@ -15686,6 +15837,10 @@ display_sparc_hwcaps (unsigned int mask) printf ("%sima", first ? "" : "|"), first = FALSE; if (mask & ELF_SPARC_HWCAP_ASI_CACHE_SPARING) printf ("%scspare", first ? "" : "|"), first = FALSE; + if (mask & ELF_SPARC_HWCAP_R1000) + printf ("%sr1000", first ? "" : "|"), first = FALSE; + if (mask & ELF_SPARC_HWCAP_SAPPHIRE) + printf ("%ssapphire", first ? "" : "|"), first = FALSE; } else fputc ('0', stdout); @@ -15721,6 +15876,8 @@ display_sparc_hwcaps2 (unsigned int mask) printf ("%sfjdes", first ? "" : "|"), first = FALSE; if (mask & ELF_SPARC_HWCAP2_FJAES) printf ("%sfjaes", first ? "" : "|"), first = FALSE; + if (mask & ELF_SPARC_HWCAP2_SAPPHIRE_PLUS) + printf ("%ssapphire+", first ? "" : "|"), first = FALSE; } else fputc ('0', stdout); @@ -18894,6 +19051,33 @@ print_stapsdt_note (Elf_Internal_Note *pnote) return FALSE; } +static const char * +get_mcst_note_type (unsigned e_type) +{ + static char buff[64]; + + switch (e_type) + { + case NT_MAGIC: + return _("NT_MAGIC (magic conjuration used by certifiers)"); + + default: + break; + } + + snprintf (buff, sizeof (buff), _("Unknown note type: (0x%08x)"), e_type); + return buff; +} + +static int +print_mcst_note (Elf_Internal_Note *pnote) +{ + if (pnote->type == NT_MAGIC) + printf (_(" Secret phrase: %s\n"), pnote->descdata); + + return 1; +} + static const char * get_ia64_vms_note_type (unsigned e_type) { @@ -19603,6 +19787,9 @@ process_note (Elf_Internal_Note * pnote, else if (const_strneq (pnote->namedata, "stapsdt")) nt = get_stapsdt_note_type (pnote->type); + else if (const_strneq (pnote->namedata, "MCST")) + nt = get_mcst_note_type (pnote->type); + else /* Don't recognize this note name; just use the default set of note type strings. */ @@ -19630,6 +19817,8 @@ process_note (Elf_Internal_Note * pnote, return print_gnu_note (filedata, pnote); else if (const_strneq (pnote->namedata, "stapsdt")) return print_stapsdt_note (pnote); + else if (const_strneq (pnote->namedata, "MCST")) + return print_mcst_note (pnote); else if (const_strneq (pnote->namedata, "CORE")) return print_core_note (pnote); else if (((const_strneq (pnote->namedata, "GA") diff --git a/config.guess b/config.guess index e6f1f64689..f689556f84 100755 --- a/config.guess +++ b/config.guess @@ -968,7 +968,7 @@ EOF echo "$UNAME_MACHINE"-axis-linux-"$LIBC" exit ;; e2k:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + echo "$UNAME_MACHINE"-mcst-linux-"$LIBC" exit ;; frv:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" @@ -976,9 +976,6 @@ EOF hexagon:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; - e2k:Linux:*.*) - echo "${UNAME_MACHINE}-mcst-linux-gnu" - exit ;; i*86:Linux:*:*) echo "$UNAME_MACHINE"-pc-linux-"$LIBC" exit ;; diff --git a/config.sub b/config.sub index f02d43ad50..1104fb5aa9 100755 --- a/config.sub +++ b/config.sub @@ -940,6 +940,10 @@ EOF cpu=x86_64 vendor=pc ;; + e2k | e2k64 | e2k32 | e2k128) + cpu=$basic_machine + vendor=mcst + ;; # Recognize the basic CPU types without company name. *) cpu=$basic_machine @@ -1173,7 +1177,7 @@ case $cpu-$vendor in | c[123]* | c30 | [cjt]90 | c4x \ | c8051 | clipper | craynv | csky | cydra \ | d10v | d30v | dlx | dsp16xx \ - | e2k | elxsi | epiphany \ + | e2k | e2k64 | e2k32 | e2k128 | elxsi | epiphany \ | f30[01] | f700 | fido | fr30 | frv | ft32 | fx80 \ | h8300 | h8500 \ | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ @@ -1507,6 +1511,8 @@ case $os in ;; ios) ;; + kpda) + ;; none) ;; *-eabi) diff --git a/elfcpp/e2k.h b/elfcpp/e2k.h index def4755ced..6a77d17609 100644 --- a/elfcpp/e2k.h +++ b/elfcpp/e2k.h @@ -50,6 +50,7 @@ enum R_E2K_GOTPLT = 114, R_E2K_ISLOCAL = 115, R_E2K_ISLOCAL32 = 118, + R_E2K_64_GOTOFF_LIT = 256, }; } // End namespace elfcpp. diff --git a/gas/Makefile.in b/gas/Makefile.in index 85c7b04daa..cd8ac608b7 100644 --- a/gas/Makefile.in +++ b/gas/Makefile.in @@ -531,6 +531,8 @@ TARGET_CPU_CFILES = \ config/tc-d10v.c \ config/tc-d30v.c \ config/tc-dlx.c \ + config/tc-e2k.c \ + config/tc-stub.c \ config/tc-epiphany.c \ config/tc-fr30.c \ config/tc-frv.c \ @@ -607,6 +609,8 @@ TARGET_CPU_HFILES = \ config/tc-d10v.h \ config/tc-d30v.h \ config/tc-dlx.h \ + config/tc-e2k.h \ + config/tc-stub.h \ config/tc-epiphany.h \ config/tc-fr30.h \ config/tc-frv.h \ @@ -914,6 +918,10 @@ config/tc-d30v.$(OBJEXT): config/$(am__dirstamp) \ config/$(DEPDIR)/$(am__dirstamp) config/tc-dlx.$(OBJEXT): config/$(am__dirstamp) \ config/$(DEPDIR)/$(am__dirstamp) +config/tc-e2k.$(OBJEXT): config/$(am__dirstamp) \ + config/$(DEPDIR)/$(am__dirstamp) +config/tc-stub.$(OBJEXT): config/$(am__dirstamp) \ + config/$(DEPDIR)/$(am__dirstamp) config/tc-epiphany.$(OBJEXT): config/$(am__dirstamp) \ config/$(DEPDIR)/$(am__dirstamp) config/tc-fr30.$(OBJEXT): config/$(am__dirstamp) \ @@ -1163,6 +1171,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@config/$(DEPDIR)/tc-d10v.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@config/$(DEPDIR)/tc-d30v.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@config/$(DEPDIR)/tc-dlx.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@config/$(DEPDIR)/tc-e2k.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@config/$(DEPDIR)/tc-epiphany.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@config/$(DEPDIR)/tc-fr30.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@config/$(DEPDIR)/tc-frv.Po@am__quote@ @@ -1206,6 +1215,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@config/$(DEPDIR)/tc-sh.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@config/$(DEPDIR)/tc-sparc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@config/$(DEPDIR)/tc-spu.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@config/$(DEPDIR)/tc-stub.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@config/$(DEPDIR)/tc-tic30.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@config/$(DEPDIR)/tc-tic4x.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@config/$(DEPDIR)/tc-tic54x.Po@am__quote@ diff --git a/gas/config/tc-e2k.c b/gas/config/tc-e2k.c index 83300c0d52..b520657772 100644 --- a/gas/config/tc-e2k.c +++ b/gas/config/tc-e2k.c @@ -111,7 +111,7 @@ typedef struct e2k_als { /* PRED_NUM[0] should be non-negative if an operation in this ALS is under %pred{PRED_NUM}, PRED_NUM[1] should be non-negative only for merge operations - it's a merge pred. */ - e2k_pred preds[3]; + e2k_pred preds[4]; expressionS exp; @@ -162,10 +162,10 @@ struct option md_longopts[] = { #define OPTION_CPU (OPTION_MD_BASE) {"mcpu", required_argument, NULL, OPTION_CPU}, -#if ! defined TE_KPDA +#if ! defined TE_KPDA && ! defined TE_E2K_UCLIBC #define OPTION_32 (OPTION_MD_BASE + 1) {"mptr32", no_argument, NULL, OPTION_32}, -#endif /* ! TE_KPDA */ +#endif /* ! TE_KPDA && ! TE_E2K_UCLIBC */ /* Let lcc_q pass us `-mptr64'. */ #define OPTION_64 (OPTION_MD_BASE + 2) @@ -189,10 +189,10 @@ struct option md_longopts[] = { {"permissive", no_argument, NULL, OPTION_PERMISSIVE}, #define OPTION_PREPROCESS (OPTION_MD_BASE + 9) {"preprocess", no_argument, NULL, OPTION_PREPROCESS}, -#if ! defined TE_KPDA +#if ! defined TE_KPDA && ! defined TE_E2K_UCLIBC #define OPTION_128_64 (OPTION_MD_BASE + 10) {"mptr128-64", no_argument, NULL, OPTION_128_64}, -#endif /* ! TE_KPDA */ +#endif /* ! TE_KPDA && ! TE_E2K_UCLIBC */ {"", no_argument, NULL, 0}, }; @@ -277,7 +277,7 @@ s_e2k_section (int push) else obj_elf_section (push); - if (strcmp (bfd_get_section_name (stdoutput, now_seg), ".rodata") == 0) + if (strcmp (bfd_section_name (now_seg), ".rodata") == 0) rodata_section = now_seg; /* record_alignment (now_seg, 4); */ } @@ -299,10 +299,14 @@ static struct ilabel_list *last_ilabel; static struct ilabel_list *ss_ilabel, *cs0_ilabel, *cs1_ilabel; static struct ilabel_list *aa2f1_ilabel[4]; +/* FIXME: what's the maximal number of different ilabel locations per wide + instruction? I used to believe that it was 10 until I met a wide instruction + containing 11 different ilabels. Hopefully, 20 will be enough for now. To be + revisited . . . */ static struct { struct ilabel_list *list; u_int32_t off; -} ilabels[10]; +} ilabels[20]; int ilabels_num; @@ -348,6 +352,51 @@ s_e2k_lcomm (int ignore ATTRIBUTE_UNUSED) symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT; } +static int parse_generic_register (char **pstr, e2k_generic_register *preg); +static void encode_reg_in_src1 (u_int8_t *src1, e2k_generic_register *preg); + +/* úÄÅÓØ ÍÏÇÕÔ ËÏÄÉÒÏ×ÁÔØÓÑ ÅÝÅ ÎÅËÉÅ ÎÅÞÉÓÌÏ×ÙÅ ÒÅÇÉÓÔÒÙ, ÔÁË ÞÔÏ define'ÏÍ + × ÏÂÝÅÍ ÓÌÕÞÁÅ ÎÅ ÏÂÏÊÄÅÛØÓÑ. */ +#define encode_reg_in_dst(dst, preg) encode_reg_in_src1 (dst, preg) + + +static void +s_e2k_reg (int ignore ATTRIBUTE_UNUSED) +{ + e2k_generic_register reg; + u_int8_t code; + int i; + char *save_input_line_pointer; + char buf[5] = "0x00"; + + if (! parse_generic_register (&input_line_pointer, ®)) + { + as_bad (_("general-purpose register should be specified as an argument " + "to .reg directive")); + return; + } + + /* Get the register's code suitable for ALS.{SRC{1,2,3},DST} (special + registers that may be used only for DST canNOT be encoded by .reg), + ... */ + encode_reg_in_dst (&code, ®); + + /* , ... get its string representation and ... */ + for (i = 0; i < 2; i++) + { + u_int8_t digit = code & 0xf; + buf[3 - i] = digit <= 9 ? '0' + digit : 'a' + digit - 10; + code >>= 4; + } + + /* ... pretend that it has been provided by the user via `.byte'. This + saves one the trouble of copy/pasting the internals of the `.byte' + handler. */ + save_input_line_pointer = input_line_pointer; + input_line_pointer = buf; + cons (1); + input_line_pointer = save_input_line_pointer; +} const pseudo_typeS md_pseudo_table[] = @@ -378,6 +427,7 @@ const pseudo_typeS md_pseudo_table[] = {"bss", s_e2k_bss, 0}, {"label", s_e2k_label, 0}, {"lcomm", s_e2k_lcomm, 0}, + {"reg", s_e2k_reg, 0}, {0, 0, 0} }; @@ -385,14 +435,25 @@ const char * e2k_target_format () { #if !defined TE_KPDA - if (e2k_arch_size == 128) - return "elf32-e2k"; + return ( +# if ! defined TE_E2K_UCLIBC + "elf64-e2k-pm" +# else /* defined TE_E2K_UCLIBC */ + "elf32-e2k-pm-uclibc" +# endif /* define TE_E2K_UCLIBC */ + ); +#if ! defined TE_E2K_UCLIBC return e2k_arch_size == 64 ? "elf64-e2k" : "elf32-e2k"; +#else /* defined TE_E2K_UCLIBC */ + gas_assert (e2k_arch_size == 64); + return "elf64-e2k-uclibc"; +#endif /* defined TE_E2K_UCLIBC */ #else /* TE_KPDA */ + gas_assert (e2k_arch_size == 64); return "elf64-e2k-kpda"; #endif /* TE_KPDA */ @@ -414,18 +475,19 @@ e2k_mach (void) switch (mcpu) { - case 6: - mach = bfd_mach_e2k_ev6; - break; case 5: mach = bfd_mach_e2k_ev5; break; case 4: + case 6: { /* Currently we distinguish binaries for different processors only for - `elbrus-v4'. Particularly, the output binary may be intended for - execution on `elbrus-8c', `elbrus-1c+' and any `elbrus-v4' - processor. */ + `elbrus-v{4,6}'. Particularly, the output binary may be intended for + execution only on `elbrus-8c', `elbrus-1c+' or any `elbrus-v{X>=4}' + processor when we are talking about elbrus-v4. With respect to + elbrus-v6 the output may be intended for execution only on one of + elbrus-{1{2,6}c,2c3} processors of this series or any + `elbrus-v{X>=6}'. */ mach = output_mach; break; } @@ -454,7 +516,7 @@ e2k_mach (void) else addend = e2k_arch_size == 64 ? 0 : 1; - return 3 * mach + addend; + return 4 * mach + addend; } void @@ -490,17 +552,27 @@ md_parse_option (int c, const char *arg) switch (c) { #if ! defined TE_KPDA +# if ! defined TE_E2K_UCLIBC case OPTION_32: + case OPTION_128_64: +# endif /* ! defined TE_E2K_UCLIBC */ case OPTION_64: case OPTION_128: - case OPTION_128_64: + { const char **list, **l; if (c == OPTION_128) e2k_arch_size = 128; else - e2k_arch_size = c == OPTION_32 ? 32 : 64; + e2k_arch_size = ( +#if ! defined TE_E2K_UCLIBC + c == OPTION_32 + ? 32 + : +#endif /* ! defined TE_E2K_UCLIBC */ + 64 + ); list = bfd_target_list (); for (l = list; *l != NULL; l++) @@ -517,7 +589,7 @@ md_parse_option (int c, const char *arg) } else { - if (CONST_STRNEQ (*l, "elf32-e2k")) + if (CONST_STRNEQ (*l, "elf64-e2k")) break; } } @@ -535,12 +607,7 @@ md_parse_option (int c, const char *arg) #endif /* TE_KPDA */ case OPTION_CPU: - if (strcmp (arg, "generic") == 0) - mcpu = 0; - else if (strcmp (arg, "elbrus-v1") == 0 - || strcmp (arg, "elbrus") == 0) - mcpu = 1; - else if (strcmp (arg, "elbrus-v2") == 0 + if (strcmp (arg, "elbrus-v2") == 0 || strcmp (arg, "elbrus-2cm") == 0) mcpu = 2; else if (strcmp (arg, "elbrus-2c+") == 0) @@ -572,14 +639,36 @@ md_parse_option (int c, const char *arg) output_mach = bfd_mach_e2k_1cplus; forward_incompat = 1; } - else if (strcmp (arg, "elbrus-v5") == 0 - || strcmp (arg, "elbrus-8c2") == 0) - mcpu = 5; - else if (strcmp (arg, "elbrus-v6") == 0 - || strcmp (arg, "elbrus-12c") == 0 - || strcmp (arg, "elbrus-2c3") == 0 - || strcmp (arg, "elbrus-16c") == 0) - mcpu = 6; + else if (strcmp (arg, "elbrus-v5") == 0) + mcpu = 5; + else if (strcmp (arg, "elbrus-8c2") == 0) + { + mcpu = 5; + forward_incompat = 1; + } + else if (strcmp (arg, "elbrus-v6") == 0) + { + mcpu = 6; + output_mach = bfd_mach_e2k_ev6; + } + else if (strcmp (arg, "elbrus-12c") == 0) + { + mcpu = 6; + output_mach = bfd_mach_e2k_12c; + forward_incompat = 1; + } + else if (strcmp (arg, "elbrus-16c") == 0) + { + mcpu = 6; + output_mach = bfd_mach_e2k_16c; + forward_incompat = 1; + } + else if (strcmp (arg, "elbrus-2c3") == 0) + { + mcpu = 6; + output_mach = bfd_mach_e2k_2c3; + forward_incompat = 1; + } else { as_bad (_("invalid -mcpu argument")); @@ -613,10 +702,11 @@ md_parse_option (int c, const char *arg) static const char * cpu_name (void) { - static const char *names[] = {"generic", "elbrus-v1", "elbrus-v2", - "elbrus-v3", "elbrus-v4", "elbrus-v5"}; + static const char *names[] = {"", "", + "elbrus-v2", "elbrus-v3", + "elbrus-v4", "elbrus-v5"}; - gas_assert (mcpu >= 0 && mcpu <= 5); + gas_assert (mcpu >= 2 && mcpu <= 5); return names[mcpu]; } @@ -658,7 +748,7 @@ typedef struct { u_int32_t abnt : 1; u_int32_t abnf : 1; u_int32_t abg : 2; - u_int32_t x3 : 1; + u_int32_t crp : 1; u_int32_t vfdi : 1; u_int32_t srp : 1; u_int32_t bap : 1; @@ -676,28 +766,14 @@ typedef struct { u_int32_t abpf : 1; u_int32_t abnt : 1; u_int32_t abnf : 1; - u_int32_t abg : 2; + u_int32_t abg : 1; + u_int32_t crp : 1; u_int32_t vfdi : 1; + u_int32_t srp : 1; u_int32_t bap : 1; u_int32_t eap : 1; u_int32_t ipd : 1; - } set; - - struct { - u_int32_t ctcond : 1; - u_int32_t ctop : 1; - u_int32_t alct : 1; - u_int32_t alcf : 1; - u_int32_t abpt : 1; - u_int32_t abpf : 1; - u_int32_t abnt : 1; - u_int32_t abnf : 1; - u_int32_t abg : 2; - u_int32_t vfdi : 1; - u_int32_t bap : 1; - u_int32_t eap : 1; - u_int32_t ipd : 1; - } dflt; + } set, dflt; u_int8_t started; } ss; @@ -896,8 +972,12 @@ md_begin () int lose = 0; register unsigned int i = 0; - /* Reproduce the behaviour of LAS. */ - default_ipd = mcpu < 2 ? 2 : 3; + /* FIXME: this is a temporary assert inserted simultaneously with the + elimination of `mcpu < 2' case when deciding on default IPD. */ + gas_assert (mcpu >= 2); + + /* IPD should be set to 3 by default starting from elbrus-v2. */ + default_ipd = 3; /* Set the default alignment for the `.text' `section to (2**3) == 8'. As far as I understand, all subsequent `.align' directives setting smaller @@ -1333,10 +1413,11 @@ static const int dummy_table[3][8] = /* LITERAL_64 */ { 1, 0, 1, 0, 1, 0, 0, 0 } }; -/* ÷ ÌÉÔÅÒÁÌØÎÙÈ ÓÌÏÇÁÈ ÍÏÖÅÔ ÐÏÔÒÅÂÏ×ÁÔØÓÑ ÒÁÚÍÅÝÁÔØ ÍÁËÓÉÍÕÍ 6 ÌÉÔÅÒÁÌÏ×: ÄÌÑ ËÁÖÄÏÇÏ - ÉÚ ËÁÎÁÌÏ× ALS0 - ALS5 ÔÏÌØËÏ src2 ÍÏÖÅÔ ÐÒÅÄÓÔÁ×ÌÑÔØ ÓÏÂÏÊ ÌÉÔÅÒÁÌ ÉÚ LTS. ïÔËÕÄÁ ÅÝÅ - ÍÏÇÕÔ ×ÚÑÔØÓÑ ÓÓÙÌËÉ ÎÁ ÌÉÔÅÒÁÌÙ? */ -#define MAX_LITERAL_NMB 6 +/* There may be at most 6 ALS* commands (including GETSP and {LD,ST}AA*) and 1 + SETWD referencing LTSx syllables. GAS parser shouldn't allow to encode more + than (6 + 1) commands of this kind which could potentially overflow this + array. */ +#define MAX_LITERAL_NMB (6 + 1) static literal_placement allowed_placements[MAX_LITERAL_NMB]; @@ -1373,6 +1454,7 @@ static void encode_long_lit_in_src2 (u_int8_t *, literal_placement *); #define O_islocal32 O_md17 #define O_ap O_md18 #define O_pl O_md19 +#define O_dynopt O_md20 static int @@ -1527,6 +1609,12 @@ parse_literal (char **pstr, e2k_literal_size max_short_lit_size, save_input_line_pointer = input_line_pointer; input_line_pointer = copy_str; expression (&exp); + + if (input_line_pointer[0] != '\0') + /* FIXME: not quite perfect as it displays only a substring limited + by COPY_STR[] of the remaining to parse string. */ + as_bad (_("junk at `%s'"), input_line_pointer); + input_line_pointer = save_input_line_pointer; *pstr = str; @@ -1771,6 +1859,12 @@ encode_reg (int arg_idx, e2k_register_format fmt, { unsigned int i; + /* See special registers' encodings in parse_special_register () and 6.3.2 + of iset-vX.single. */ + if ((reg >= 192 && reg <= 223) + && (arg_idx >= 1 && arg_idx <= 3)) + as_bad (_("special register not allowed in position of SRC%d"), arg_idx); + for (i = 0; i < free_als->real_als_nmb; i++) { u_int8_t *p; @@ -1866,9 +1960,6 @@ encode_lit_ref_in_src2 (int f, int p) } } -/* úÄÅÓØ ÍÏÇÕÔ ËÏÄÉÒÏ×ÁÔØÓÑ ÅÝÅ ÎÅËÉÅ ÎÅÞÉÓÌÏ×ÙÅ ÒÅÇÉÓÔÒÙ, ÔÁË ÞÔÏ define'ÏÍ - × ÏÂÝÅÍ ÓÌÕÞÁÅ ÎÅ ÏÂÏÊÄÅÛØÓÑ. */ -#define encode_reg_in_dst(dst, preg) encode_reg_in_src1 (dst, preg) #if 0 static int @@ -1967,7 +2058,10 @@ parse_src3 (char **pstr, e2k_register_format fmt, int into_ales, /* Like parse_src1. I hope that src2 is always preceeded by `,'. */ if (comma_expected && ! slurp_char (&s, ',')) - return 0; + { + as_bad (_("comma followed by src3 expected at `%s'"), s); + return 0; + } slurp_char (&s, ' '); @@ -1985,7 +2079,7 @@ parse_src3 (char **pstr, e2k_register_format fmt, int into_ales, { if (reg.fmt != fmt && reg.fmt != SINGLE && reg.fmt != DOUBLE) { - as_bad ("register of invalid format in second operand (src2)"); + as_bad (_("register of invalid format at position of src3")); return 0; } @@ -2006,7 +2100,7 @@ parse_src3 (char **pstr, e2k_register_format fmt, int into_ales, } else { - as_bad (_("invalid src3")); + as_bad (_("invalid src3 at `%s'"), s); return 0; } @@ -2077,7 +2171,10 @@ parse_dst (char **pstr, e2k_register_format fmt) /* Like similar conditions in parse_src{1,2} - I hope that dst is always preceeded by `,' to avoid code duplication. */ if (! slurp_char (&s, ',')) - return 0; + { + as_bad (_("comma followed by dst expected at `%s'"), s); + return 0; + } if (parse_generic_register (&s, ®)) { @@ -2106,7 +2203,7 @@ parse_dst (char **pstr, e2k_register_format fmt) u_int8_t special_dst; if (! parse_special_register_for_dst (&s, &special_dst)) { - as_bad (_("invalid third argument (dst)")); + as_bad (_("invalid third argument (dst) at `%s'"), s); return 0; } @@ -2236,12 +2333,11 @@ parse_state_register (char **str, u_int8_t als_fmt) if ((mcpu != 0 || reg->min_cpu != 1 || reg->max_cpu != 6) && (mcpu < reg->min_cpu || mcpu > reg->max_cpu)) { - if (mcpu == 0) - as_bad (_("CU register `%s' is not available in generic case"), - reg->name); - else - as_bad (_("CU register `%s' is not available on elbrus-v%d"), - reg->name, mcpu); + /* This is a temporary assert inserted simultaneously with the + removal of the below user error message in "generic" case. */ + gas_assert (mcpu >= 2); + as_bad (_("CU register `%s' is not available on elbrus-v%d"), + reg->name, mcpu); return 0; } @@ -3098,6 +3194,10 @@ parse_alopf11_lit8_args (char **pstr, const e2k_opcode_templ *op) /* FIXME: the function is declared below. */ static void start_ss_syllable (int set_ilabel); +#define IBRANCH 1 +#define RBRANCH 2 +static int parse_ctcond (char **pstr, int ibranch); + static int parse_alf2_args (char **pstr, const e2k_opcode_templ *op) { @@ -3147,6 +3247,11 @@ parse_alf2_args (char **pstr, const e2k_opcode_templ *op) CHECK (parse_src2 (&s, alf->arg_fmt[0])); CHECK (parse_dst (&s, alf->arg_fmt[1])); + + /* The execution of `I{BRANCH,CALL}D' is controlled by `ctcond' rather + than by `alj_cond' unlike ordinary AL instructions! */ + if (alf->alopf == ALOPF12_IBRANCHD || alf->alopf == ALOPF12_ICALLD) + CHECK (parse_ctcond (&s, alf->alopf == ALOPF12_IBRANCHD ? IBRANCH : 0)); *pstr = s; @@ -3195,7 +3300,13 @@ parse_alf2_args (char **pstr, const e2k_opcode_templ *op) && (free_als->u[0].alf1.dst >= 0xd1 && free_als->u[0].alf2.dst <= 0xd3)) { gas_assert (free_als->plcmnt_nmb >= 1); - gas_assert (free_als->pos[0] == 0); + if (free_als->pos[0] != 0) + { + as_bad (_("`%s' to `%%ctpr{1,2,3}' registers may be encoded in " + "the 0-th channel only"), + alf->opc == 0x61 ? "movtd" : "getpl"); + return 0; + } free_als->plcmnt_nmb = 1; } @@ -3276,7 +3387,14 @@ struct mu_reg /* Specifies whether `mmurw,2 %rX, %mmu_reg' is allowed or not. Note that the only valid channel for MMURW seems to be ALC2 which has already been taken - into account in `opcode_templ'. */ + into account in `opcode_templ'. While the zero value of this field means + "not writable anywhere", non-zero stands for the minimal iset starting from + which the register becomes writable (consider `%us_cl_{b,up,m*}' which have + been present since elbrus-v1, but become writable starting from elbrus-v6 + only, see Bug #107736). Note, however, that this field may still contain 1 + being less than MIN_CPU for initially writable registers. This shouldn't + break anything but at the same time saves me the trouble of reworking + mu-regs.def to match the new meaning of this field. */ int writable; }; @@ -3333,12 +3451,11 @@ parse_mu_reg (char **pstr, struct mu_reg **preg) if ((mcpu != 0 || reg->min_cpu != 1) && (mcpu < reg->min_cpu)) { - if (mcpu == 0) - as_bad (_("MU register `%s' is not available for generic e2k machine"), - reg->name); - else - as_bad (_("MU register `%s' is not available for elbrus-v%d"), - reg->name, mcpu); + /* This is a temporary assert inserted simultaneously with the + removal of the below user error message in "generic" case. */ + gas_assert (mcpu >= 2); + as_bad (_("MU register `%s' is not available for elbrus-v%d"), + reg->name, mcpu); return 0; } @@ -3444,6 +3561,12 @@ parse_mmurw_args (char **pstr, const e2k_opcode_templ *op) as_bad (_("`%s' is not writable"), mmu_reg->name); break; } + else if (mcpu < mmu_reg->writable) + { + as_bad (_("`%s' is not writable on `elbrus-v%d'"), + mmu_reg->name, mcpu); + break; + } sprintf (fake_buf, "%d,", mmu_reg->addr); fake = &fake_buf[0]; @@ -3532,6 +3655,9 @@ parse_mova_args (char **pstr, const e2k_opcode_templ *op) {"am=", 1, 0}, {"be=", 1, 15}}; + /* Specify if the corresponding parameter has already been seen. */ + int seen[4] = {0, 0, 0, 0}; + int is_movaq = mova->opc == 5; /* FIXME: find out if IND may be used uninitialized below. */ u_int8_t ind = 0; @@ -3583,41 +3709,49 @@ parse_mova_args (char **pstr, const e2k_opcode_templ *op) for (i = 0; i < (is_movaq ? 2 : 1); i++) wc.aa2f1[chn + i] |= mova->opc << 12; - if (! slurp_char (&s, ' ')) - { - as_bad (_("` ' expected at `%s'"), s); - return 0; - } + /* Space may be present if the channel number has been specified in the + normal way (i.e. `mova,chn %dst') or absent in case of `mova, chn %dst' + where the generic GAS parser removes space between CHN and DST). */ + slurp_char (&s, ' '); - for (i = 0; i < 4; i++) + /* `16 == 4 * 4' stupidly takes into account that 4 MOVA* parameters may be + shuffled. */ + for (i = 0; i < 16; i++) { - int j; u_int8_t param_val; + int k = i % 4; - if (! slurp_str (&s, param[i].name)) - { - as_bad (_("`%s' expected at `%s'"), param[i].name, s); - return 0; - } + if (! slurp_str (&s, param[k].name)) + continue; + + if (seen[k]) + { + as_bad (_("`%s' has already been seen"), param[k].name); + return 0; + } + + seen[k] = 1; if (! parse_number (&s, ¶m_val, sizeof (param_val), 0)) { as_bad (_("numeric value should be specified for `%s'"), - param[i].name); - return 0; - } - if (param_val > param[i].max) - { - as_bad (_("%d exceeds maximal value for %s"), param_val, - param[i].name); + param[k].name); return 0; } - if (i != 1 || !is_movaq) + if (param_val > param[k].max) { + as_bad (_("%d exceeds maximal value for %s"), param_val, + param[k].name); + return 0; + } + + if (k != 1 || !is_movaq) + { + int j; /* Encode all parameters except for `ind' for MOVAQ . . . */ for (j = 0; j < (is_movaq ? 2 : 1); j++) - wc.aa2f1[chn + j] |= param_val << param[i].bit_offset; + wc.aa2f1[chn + j] |= param_val << param[k].bit_offset; } else { @@ -3863,7 +3997,7 @@ parse_alf5_args (char **pstr, const e2k_opcode_templ *op) do { CHECK (parse_src2 (&s, alf->arg_fmt)); /* It's a shame. Deal uniformly with all commas. */ - CHECK (slurp_char (&s, ',')); + CHECK_MSG (slurp_char (&s, ','), _("comma expected at `%s'"), s); CHECK (parse_state_register (&s, 5)); @@ -4106,9 +4240,54 @@ parse_aasti (char **pstr) return 1; } +/* This one parses arguments of LDAA{b,h,w,d,q{,p}} instructions. */ +static int +parse_alf19_args (char **pstr, const e2k_opcode_templ *op) +{ + char *s = *pstr; + const e2k_alf9_opcode_templ *alf = (const e2k_alf9_opcode_templ *) op; + + do { + u_int8_t aad_num; + unsigned i; + + free_als->need_ales = 1; + free_als->ales.alef2.opce = NONE_VALUE; + /* FIXME: this should be encoded within e2k_alf9_opcode_templ, of + course. */ + free_als->ales.alef2.opc2 + = strcmp (op->name, "ldaaqp") == 0 ? EXT1_VALUE : EXT_VALUE; + + CHECK_MSG (slurp_str (&s, "%aad"), _(", %%aad expected ")); + CHECK_MSG (parse_number (&s, &aad_num, sizeof (aad_num), 0), + _("%%aad index expected")); + CHECK_MSG (aad_num <= 31, _("invalid %%aad index specified")); + + for (i = 0; i < free_als->real_als_nmb; i++) + free_als->u[i].alf10.opce1_hi |= aad_num << 3; + + /* This deserves a dedicated parse function since it may be an + expression. */ + parse_aasti (&s); + + CHECK (parse_dst (&s, alf->arg_fmt)); + + if (! parse_mas (&s, 1)) + { + as_bad (_("Invalid MAS specified")); + return 0; + } + + *pstr = s; + return 1; + } + while (0); + + return 0; +} -/* This one parses arguments of STAA{b,h,w,d,q} instructions. */ +/* This one parses arguments of STAA{b,h,w,d,q{,p}} instructions. */ static int parse_alf10_args (char **pstr, const e2k_opcode_templ *op) { @@ -4338,7 +4517,8 @@ parse_alopf21_args (char **pstr, const e2k_opcode_templ *op) do { CHECK (parse_src1 (&s, alf->arg_fmt[0])); - CHECK (slurp_char (&s, ',')); + CHECK_MSG (slurp_char (&s, ','), + _("comma followed with src2 expected at `%s'"), s); CHECK (parse_src2 (&s, alf->arg_fmt[1])); CHECK (parse_src3 (&s, alf->arg_fmt[2], 1, 1)); CHECK (parse_dst (&s, alf->arg_fmt[3])); @@ -4406,6 +4586,7 @@ parse_alf_args (char **pstr, const e2k_opcode_templ *op) [ALOPF7] = parse_alf7_args, [ALOPF17] = parse_alf7_args, [ALOPF8] = parse_alf8_args, + [ALOPF19] = parse_alf19_args, [AAURR] = parse_aaurr_args, [ALOPF10] = parse_alf10_args, [AAURW] = parse_aaurw_args, @@ -4498,9 +4679,7 @@ parse_alf_args (char **pstr, const e2k_opcode_templ *op) || ((alf->alopf == ALOPF10 || alf->alopf == AAURW) && ((e2k_alf10_opcode_templ *) alf)->arg_fmt == QUAD) || ((alf->alopf == AAURR - /* Note that `LDDAA*' operations haven't been actually - supported yet . . . */ - /* || alf->alopf == ALOPF19 */) + || alf->alopf == ALOPF19) && ((e2k_alf9_opcode_templ *) alf)->arg_fmt == QUAD)) { /* It's one of the quad stores (including STAAQ and AAURWQ) or either of @@ -4559,7 +4738,12 @@ parse_alf_args (char **pstr, const e2k_opcode_templ *op) /* Parse arguments. This is specific to a particular encoding. */ CHECK (parse_alf_fn[alf->alopf] (&s, op)); - CHECK (parse_als_pred_optional (&s)); + /* The execution of `I{BRANCH,CALL}D' is controlled by `ct_cond', which + has already been processed in `parse_alf2_args ()'. `alj_cond' is not + applicable to these instructions and is said to result in `exc_illegal + _opcode'. Therefore, don't attempt to parse it here. */ + if (alf->alopf != ALOPF12_IBRANCHD && alf->alopf != ALOPF12_ICALLD) + CHECK (parse_als_pred_optional (&s)); /* At this point we have created a new ALS. It's possible to set an operation code and some other attributes now. I also set a so-called `finish function' @@ -4603,6 +4787,7 @@ parse_incr_args (char **pstr, const e2k_opcode_templ *op ATTRIBUTE_UNUSED) int chn; unsigned incr; e2k_als *related_als; + e2k_pred incr_pred; if (free_als == &free_alses[0]) { @@ -4636,6 +4821,11 @@ parse_incr_args (char **pstr, const e2k_opcode_templ *op ATTRIBUTE_UNUSED) return 0; } + if (slurp_char (&s, '?') + && parse_pred (&s, &incr_pred, 1)) + related_als->preds[3] = incr_pred; + + for (i = 0; i < related_als->real_als_nmb; i++) related_als->u[i].alf10.opce1_lo |= ((incr << 4) | 0x4); @@ -4695,7 +4885,7 @@ parse_copf2_args (char **pstr, const e2k_opcode_templ *op) SDISP .*/ slurp_str (&s, "disp="); - save_input_line_pointer= input_line_pointer; + save_input_line_pointer = input_line_pointer; input_line_pointer = s; expression (&cs0_exp); s = input_line_pointer; @@ -4703,11 +4893,12 @@ parse_copf2_args (char **pstr, const e2k_opcode_templ *op) if (cs0_exp.X_op == O_constant) { - /* FIXME: verify CS0.sdisp somehow for the sake of Bug #83996. */ + /* FIXME: verify CS0.disp in SDISP somehow for the sake of + Bug #83996. */ if (copf2->ctp_opc == 2 && (cs0_exp.X_add_number < 0 || cs0_exp.X_add_number >= 32)) { - as_bad (_("invalid value for CS0.sdisp specified")); + as_bad (_("invalid value for CS0.disp in SDISP specified")); return 0; } @@ -4718,9 +4909,21 @@ parse_copf2_args (char **pstr, const e2k_opcode_templ *op) } else if (cs0_exp.X_op == O_symbol || cs0_exp.X_op == O_plt) { + if (copf2->ctp_opc == 2) + { + as_bad (_("CS0.disp in SDISP should encode an immediate " + "value")); + return 0; + } + /* We'll probably need a relocation. */ wc.cs0.pexp = &cs0_exp; } + else + { + as_bad (_("invalid expression at `%s'"), input_line_pointer); + return 0; + } } else { @@ -5022,14 +5225,17 @@ int parse_wait_args (char **pstr, const e2k_opcode_templ *op ATTRIBUTE_UNUSED) { - static const char *param[12] = { + static const char *param[14] = { "all_c=", "all_e=", "st_c=", "ld_c=", "fl_c=", "ma_c=", "trap=", - "sas=", "sal=", "las=", "lal=", "mt=" + /* These have been added starting from elbrus-v5. */ + "sas=", "sal=", + /* These are available in elbrus-v6. */ + "las=", "lal=", "mt=", "int=", "mem_mod=" }; /* This array is used to track if the corresponding parameter has been specified explicitly. */ - int val[12] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; + int val[14] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; char *str = *pstr; @@ -5050,8 +5256,12 @@ parse_wait_args (char **pstr, { u_int8_t param_val; - if ((mcpu < 2 && j > 5) - || (mcpu < 5 && j > 6) + /* FIXME: this a temporary assert inserted simultaneously + with the elimination of `mcpu < 2' case from the runtime + condition below. */ + gas_assert (mcpu >= 2); + + if ((mcpu < 5 && j > 6) || (mcpu < 6 && j > 8)) { as_bad (_("Invalid `%s' WAIT parameter for %s"), param[j], @@ -5156,8 +5366,13 @@ parse_copf4_args (char **pstr ATTRIBUTE_UNUSED, const e2k_opcode_templ *op) if (strcmp (op->name, "flushr") == 0) wc.cs1.val.fields.call.param |= 1; - else + else if (strcmp (op->name, "flushc") == 0) wc.cs1.val.fields.call.param |= 2; + else if (strcmp (op->name, "fillr") == 0) + wc.cs1.val.fields.call.param |= 4; + /* This should be `fillc'. */ + else + wc.cs1.val.fields.call.param |= 8; wc.cs1.set = 1; @@ -5258,9 +5473,6 @@ parse_pl_ctcond (char **pstr, u_int32_t *psrc) return 0; } -#define IBRANCH 1 -#define RBRANCH 2 - static int parse_ctcond (char **pstr, int ibranch) { @@ -5452,19 +5664,24 @@ parse_ct_args (char **pstr, const e2k_opcode_templ *op) } int -parse_hcall_args (char **pstr, const e2k_opcode_templ *op) +parse_hicall_args (char **pstr, const e2k_opcode_templ *op) { char *str = *pstr; start_ss_syllable (1); do { - u_int8_t hdisp; u_int8_t wbs; + char *save_input_line_pointer; + int is_hcall = (op->name[0] == 'h'); wc.ss.val.fields.ctop = 0; + + save_input_line_pointer = input_line_pointer; + input_line_pointer = str; + expression (&cs0_exp); + str = input_line_pointer; + input_line_pointer = save_input_line_pointer; - CHECK_MSG (parse_number (&str, &hdisp, sizeof (hdisp), 2), - _("hdisp value expected")); slurp_char (&str, ','); if (wc.cs0.set) @@ -5474,13 +5691,48 @@ parse_hcall_args (char **pstr, const e2k_opcode_templ *op) break; } - /* Encode `CS0.ctp_opc = HCALL'. */ + if (cs0_exp.X_op == O_constant) + { + /* Check the value of hdisp parameter of HCALL. Note that it's encoded + in `CS0.disp[4:1]' unlike sdisp which is encoded in + `CS0.disp[4:0]'. This is taken into account below . . . */ + if (is_hcall && (cs0_exp.X_add_number < 0 + || cs0_exp.X_add_number >= 16)) + { + as_bad (_("invalid value for CS0.disp in HCALL specified")); + return 0; + } + + wc.cs0.val.fields.disp = (u_int32_t) cs0_exp.X_add_number; + /* . . . by shifting the parsed hdisp value (but not the disp one + for ICALL!) by one bit to the left. */ + if (is_hcall) + wc.cs0.val.fields.disp <<= 1; + + } + else if (cs0_exp.X_op == O_symbol || cs0_exp.X_op == O_plt) + { + if (is_hcall) + { + as_bad (_("CS0.disp in HCALL should encode an immediate " + "value")); + return 0; + } + + /* We'll probably need a relocation. */ + wc.cs0.pexp = &cs0_exp; + } + else + { + as_bad (_("invalid expression at `%s'"), input_line_pointer); + return 0; + } + + + /* Encode `CS0.ctp_opc = {H,I}CALL == 0' (see Table B.4.1). */ wc.cs0.val.fields.ctp_opc = 0; - wc.cs0.val.fields.disp = hdisp << 1; wc.cs0.set = 1; - - /* Should I really consider it optional? */ slurp_str (&str, "wbs="); @@ -5499,8 +5751,9 @@ parse_hcall_args (char **pstr, const e2k_opcode_templ *op) wc.cs1.set = 1; wc.cs1.val.fields.call.opc = 5; - /* Set CS1.param.wbs and `CS1.param.ctopc = HCALL'. */ - wc.cs1.val.fields.call.param = (2 << 7) | wbs; + /* Set CS1.param.wbs and `CS1.param.ctopc = {H,I}CALL == {2,1}' + (see Table B.4.2.1). */ + wc.cs1.val.fields.call.param = ((is_hcall ? 2 : 1) << 7) | wbs; /* Can call be followed by ctcond at all? Certainly it can. */ if (! parse_ctcond (&str, 0)) @@ -5602,8 +5855,8 @@ parse_ibranch_args (char **pstr, const e2k_opcode_templ *op) } int -parse_done_hret_glaunch_args (char **pstr, - const e2k_opcode_templ *op) +parse_done_hiret_glaunch_args (char **pstr, + const e2k_opcode_templ *op) { char *s = *pstr; @@ -5624,16 +5877,22 @@ parse_done_hret_glaunch_args (char **pstr, return 0; } - /* See Table B.4.1 in iset.single. */ + /* According to Table B.4.1 in iset.single providing the values to be encoded + in CS0.ctp_opc `DONE == IRET == HRET == GLAUNCH == 3', whereas the only + option for CS0.ctpr is 0. */ wc.cs0.val.fields.ctpr = 0; wc.cs0.val.fields.ctp_opc = 3; - /* If this is HRET or GLAUNCH take care of setting CS0.param.type - appropriately (FIXME: `param' is to be added yet). Otherwise silently - leave `CS0.disp' equal to zero for DONE. Note that DONE has C0F2 format - unlike the first two instructions. Hardly can I understand what role `disp' - value can play for it. Moreover, it's not prescribed by our iset. */ - if (op->name[0] == 'h') + /* If this is either of {H,I}RET or GLAUNCH take care of setting + CS0.param.type according to Table B.4.1.1 (FIXME: this field is to be + introduced yet, below I make use of the fact that it occupies the same + bits as CS0.disp). Otherwise silently leave `CS0.disp' equal to zero for + DONE. Note that DONE has C0F2 format unlike the first two instructions. + Hardly can I understand what role `disp' value can play for it. Moreover, + it's not prescribed by our iset. */ + if (op->name[0] == 'i') + wc.cs0.val.fields.disp = 2; + else if (op->name[0] == 'h') wc.cs0.val.fields.disp = 3; else if (op->name[0] == 'g') wc.cs0.val.fields.disp = 4; @@ -6101,8 +6360,8 @@ replace_nested_commas (char *s, size_t *pidx, size_t *plen) int l = 0; int llen = 0; - int min; - int max; + int min = 0; + int max = 0; f = slurp_fmt (&s[i], &ref, &row, &flen); @@ -6257,8 +6516,8 @@ md_assemble (char *str) if (insn_tmpl) { - size_t replace_idx; - size_t replace_len; + size_t replace_idx = 0; + size_t replace_len = 0; /* Take care of restoring the original STR by getting rid of '\0' inserted above. It's not necessary to restore a space ' ' in fact, but @@ -6448,7 +6707,7 @@ md_section_align (segT segment, valueT size) if (size != 0) record_alignment (segment, 4); else - bfd_set_section_alignment (stdoutput, segment, 0); + bfd_set_section_alignment (segment, 0); } return size; @@ -6458,8 +6717,16 @@ md_section_align (segT segment, valueT size) int tc_e2k_fix_adjustable (struct fix *fixP) { + /* Prevent local symbols from being replaced with the containing sections + in relocation entries so as not to lose info on the size of the former. + Obviously this should be done for `R_E2K_*_SIZE relocations and for + relocations intended to produce AP in PM so as not to obtain the one + extended to the end of GD because of unavailable info on its size (see + Bug #121736). */ if (fixP->fx_r_type == BFD_RELOC_SIZE32 - || fixP->fx_r_type == BFD_RELOC_SIZE64) + || fixP->fx_r_type == BFD_RELOC_SIZE64 + || (e2k_arch_size == 128 + && fixP->fx_r_type == BFD_RELOC_E2K_AP)) return 0; return 1; @@ -6708,7 +6975,7 @@ start_wide_command (void) { int j; memset (&free_alses[i], 0, sizeof (free_alses[i])); - for (j = 0; j < 3; j++) + for (j = 0; j < 4; j++) { free_alses[i].preds[j].pred_num = -1; free_alses[i].preds[j].negated = 0; @@ -6774,15 +7041,7 @@ hsyll_same_expr (struct hsyll *phs, expressionS *exp, unsigned int idx) return 1; return 0; } - else if (exp->X_op == O_symbol - || exp->X_op == O_gotoff - || exp->X_op == O_got - || exp->X_op == O_gotplt - || exp->X_op == O_tls_ie - || exp->X_op == O_size - || exp->X_op == O_ap_got - || exp->X_op == O_pl_got - || exp->X_op == O_islocal32) + else if (is_symbol (exp)) { if (phs->owner->exp.X_op != exp->X_op || phs->owner->exp.X_add_symbol != exp->X_add_symbol @@ -6825,8 +7084,21 @@ place_literal (literal_placement *pplcmnt, int plcmnt_idx, int prove, int finali { int pos_msk = 1 << (((pos >> 1) << 1) + 1 - (pos & 0x1)); if ((wc.busy_lts & pos_msk) != 0 - && (pplcmnt->size[plcmnt_idx] > 1 - || ! hsyll_same_expr (&wc.lts[pplcmnt->pos[plcmnt_idx] + i], &pplcmnt->exp, i))) + && ( +#if 0 + /* This condition used to prevent us from merging wider than + 16-bit (i.e. 32 and 64-bit) identical literals. However, + it hasn't been required since ugly `lit_ref's started + being treated separately from regular literals. It is + necessarily disabled now that we are going to get rid of + `lit_ref's in LCC by replacing them with duplicating + literal values (Bug #124870) and (TODO!) is to be + eventually removed if the new approach does not result + in any trouble. */ + pplcmnt->size[plcmnt_idx] > 1 + || +#endif /* 0 */ + ! hsyll_same_expr (&wc.lts[pplcmnt->pos[plcmnt_idx] + i], &pplcmnt->exp, i))) /* ïÞÅÒÅÄÎÏÊ ÐÏÌÕ-ÌÉÔÅÒÁÌ ÚÁÎÑÔ ÄÒÕÇÉÍ ÚÎÁÞÅÎÉÅÍ. ÷ÏÚ×ÒÁÝÁÅÍÓÑ, ÎÉÞÅÇÏ ÎÅ ÉÓÐÏÒÔÉ×. */ return 0; @@ -6852,7 +7124,7 @@ static int place_literals (void) { int i; - int crnt_idx[MAX_LITERAL_NMB] = {0, 0, 0, 0, 0, 0}; + int crnt_idx[MAX_LITERAL_NMB] = {0, 0, 0, 0, 0, 0, 0}; literal_placement *pplcmnt[MAX_LITERAL_NMB]; /* ÷ ÎÁÞÁÌÅ ÍÙ ÎÅ ÍÏÖÅÍ ÓËÁÚÁÔØ ÎÉ Ï ÏÄÎÏÍ ÒÁÚÍÅÝÅÎÉÉ, Ñ×ÌÑÅÔÓÑ ÌÉ ÏÎÏ ÄÅÊÓÔ×ÉÔÅÌØÎÙÍ (ÓÍ. ÉÓÐÏÌØÚÏ×ÁÎÉÅ ÎÉÖÅ). */ @@ -7149,10 +7421,17 @@ place_alses (void) static const u_int16_t al_to_rlp_mrgc[][2] = {{RLP0, MRGC0}, {RLP0, MRGC0}, {RLP0, MRGC0}, - {RLP1, MRGC1}, {RLP1, MRGC1}, {RLP1, MRGC1}}; + {RLP1, MRGC1}, {RLP1, MRGC1}, {RLP1, MRGC1}, + /* These two correspond to AM{2,5} "ALC"es. TODO(?): in theory the + first of them could be used to encode RPC == MRGC0 acting on {S/L + /C}RP, but this is not currently used in the underlying algorithm + and doesn't probably make much sense. */ + {RLP0, -1}, {RLP1, -1}}; - static u_int16_t al_to_mask[] = {0x1, 0x2, 0x4, 0x1, 0x2, 0x4}; - static u_int16_t al_to_neg[] = {0x1, 0x2, 0x4, 0x1, 0x2, 0x4}; + /* The trailing two elements in {MASK,NEG}[] correspond to RLP{0,1} + acting on AM{2,5} respectively. */ + static u_int16_t al_to_mask[] = {0x1, 0x2, 0x4, 0x1, 0x2, 0x4, 0x8, 0x8}; + static u_int16_t al_to_neg[] = {0x1, 0x2, 0x4, 0x1, 0x2, 0x4, 0x4, 0x4}; unsigned j; int al_num = pals[i]->pos[pals[i]->optimal_plcmnt_idx]; /* This will be used when setting al[] bits in HS when packing the wide @@ -7249,31 +7528,85 @@ place_alses (void) { unsigned l; - for (l = 0; l < 3; l++) + for (l = 0; l < 4; l++) { unsigned k; + /* `l == {0,2,3}' correspond to %p{red,cnt}X encoded in RLP, while + `l == 1' stands for MRGC predicate. */ int op_idx = (l < 2) ? l : 0; + /* No predicate of the type under consideration (i.e. ` ? %p{red, + cnt}X' or MRGC) acting on this ALS. */ if (pals[i]->preds[l].pred_num < 0) - continue; + continue; for (k = 0; k < pals[i]->real_als_nmb; k++) { int real_al_num = pals[i]->real_alses[al_num][k]; + /* preds[3] acts on AM{2,5} matching ALC{2,5} in fact. There + should be no `AMj's matching other ALCes. */ + if (l == 3) + { + if (real_al_num == 2) + real_al_num = 6; + else if (real_al_num == 5) + real_al_num = 7; + else + gas_assert (0); + } for (j = 0; j < 6; j++) { + /* Does this already employed CDS half syllable encode + the same operation as we need? */ if (wc.cds[j].rlp_mrgc.opc == al_to_rlp_mrgc[real_al_num][op_idx]) { + u_int16_t opc = al_to_rlp_mrgc[real_al_num][op_idx]; #if 0 - /* Having more than one RLP/MRGC acting on the same ALC should be + /* With things like `? %predX, %pcntY' possible there + may be more than one RLP acting on the same ALC, + which is why this assert is commented out. should be impossible at least while an explicit rlp command is not introduced. In the latter case this situation may very well become a user error. */ - gas_assert ((wc.cds[j].rlp_mrgc.mask & al_to_mask[real_al_num]) == 0); + gas_assert ((wc.cds[j].rlp_mrgc.mask + & al_to_mask[real_al_num]) == 0); #endif /* 0 */ - if (wc.cds[j].rlp_mrgc.pred == pals[i]->preds[l].pred_fld) + /* Does this already employed CDS half syllable encode + the same predicate as we need? */ + if (wc.cds[j].rlp_mrgc.pred + == pals[i]->preds[l].pred_fld) { + /* Should one check for a possible inconsistency + because of CDS.neg[2] shared between CDS.mask[2,3]? */ + if ((al_to_mask[real_al_num] == 0x4 + && (wc.cds[j].rlp_mrgc.mask & 0x8) != 0) + || (al_to_mask[real_al_num] == 0x8 + && (wc.cds[j].rlp_mrgc.mask & 0x4) != 0)) + { + /* Only RLP{0,1} and `MRGC0 together with RPC + == MRGC0' may act on such a combination of + "target syllables" as CDS.mask[3] seems to + be reserved for MRGC1 up to iset-v6. */ + gas_assert (opc == RLP0 || opc == RLP1 + || (/* RPC predicates may emerge + starting from elbrus-v3 + only. */ + mcpu > 2 + && opc == MRGC0)); + + if ((pals[i]->preds[l].negated + && (wc.cds[j].rlp_mrgc.neg + & al_to_neg[real_al_num]) == 0) + || (! pals[i]->preds[l].negated + && (wc.cds[j].rlp_mrgc.neg + & al_to_neg[real_al_num]) != 0)) + continue; + } + + /* This CDS half-syllable may be safely shared + between an already encoded operation and the + new one. */ wc.cds[j].rlp_mrgc.mask |= al_to_mask[real_al_num]; if (pals[i]->preds[l].negated) wc.cds[j].rlp_mrgc.neg |= al_to_neg[real_al_num]; @@ -7497,8 +7830,10 @@ pack_wide_command (void) int i; int crnt_syll = 0, lts_cntr = 0, cds_cntr = 0, pls_cntr = 0; e2k_hs *hs; - char *obj_buf, *bufs[10]; - fragS *sub_frags[10]; + /* FIXME: `bufs[]' and `sub_frags[]' arrays should obviously contain one + element more than `ilabels[]'. */ + char *obj_buf, *bufs[21]; + fragS *sub_frags[21]; u_int16_t *hsyllables; unsigned hsyllable_cntr; @@ -7549,11 +7884,17 @@ pack_wide_command (void) if (wc.ss.started) { /* If the same internal lable is attached both to SS and CS0 (consider - IBRANCH) or SS and CS1 (consider CALL) give preference to CS0 and CS1 - respectively. */ + IBRANCH) or SS and CS1 (consider CALL) or SS and ALS0 (consider I{CALL, + BRANCH}D) give preference to CS0, CS1 and ALS0 respectively. + + FIXME: ICALL is encoded in three syllables at once: SS, CS0 and CS1. + Despite the fact that the label eventually points to CS1, which is + probably OK as this is the most informative syllable, I suspect that + this case turns out to be workable only by chance . . . */ if (ss_ilabel != NULL && !((wc.cs0.set && cs0_ilabel == ss_ilabel) - || (wc.cs1.set && cs1_ilabel == ss_ilabel))) + || (wc.cs1.set && cs1_ilabel == ss_ilabel) + || ((wc.busy_al & (1 << 0)) && wc.al[0].label == ss_ilabel))) { ilabels[ilabels_num].list = ss_ilabel; ilabels[ilabels_num++].off = 4 * crnt_syll; @@ -8639,6 +8980,96 @@ parse_vfdi_args (char **pstr ATTRIBUTE_UNUSED, return 1; } +static int +parse_and_encode_rpc_optional (char **pstr) +{ + e2k_pred pred; + + /* Missing RPC is quite OK. */ + if (slurp_char (pstr, '?') == 0) + return 1; + + /* Let `%pcntX' be used in place of RPC as iset-v{X>=3}.single doesn't + seem to prohibit this. */ + if (! parse_pred (pstr, &pred, 1)) + return 0; + + if (mcpu == 2) + { + /* The predicate has been successfully parsed, but it is not supported + for this CPU. */ + as_bad (_("Recovery Point Conditions are not supported for elbrus-v2")); + return 0; + } + + /* We are called before RLP and MRGC predicates are assigned to CDS half- + syllables, therefore, the hi part of CDS0 from which allocation typically + starts should be free. */ + gas_assert (wc.cds[0].rlp_mrgc.mask == 0); + + /* Note that RPC has the same encoding as MRGC0 (see C.10.2; this lets later + encoded MRGC0 predicates share the hi part of CDS0 with us) and ... */ +#define RPC MRGC0 + wc.cds[0].rlp_mrgc.opc = RPC; + + /* ... this is the mask value irrelevant to MRGC0 (1, 2 and 4 are used to + encode ALC{0,1,2} MRGC0 acts on respectively) that distinguishes them. */ + wc.cds[0].rlp_mrgc.mask = 0x8; + wc.cds[0].rlp_mrgc.pred = pred.pred_fld; + + if (pred.negated) + wc.cds[0].rlp_mrgc.neg = 0x4; + + return 1; +} + +/* Starting from elbrus-v3 SRP can't be encoded together with CRP as this + combination of bits is used for SLRP, whereas on elbrus-v2 this is + formally possible. However, do these instructions together make any + sense even on elbrus-v2? This is rather doubtful which is why this + combination is prohibited for all isets by virtue of `SET_FIELD (.., + dfl = 0)'. FIXME: more intuitive error messages should be emitted on + an attempt to combine these instructions. */ +int +parse_srp_args (char **pstr, + const e2k_opcode_templ *op ATTRIBUTE_UNUSED) +{ + start_ss_syllable (1); + + /* Starting from iset-v3.single SRP implies `SS.(crp aka rp_opc_lo) == 0' + whereas `SS.crp == 1' corresponds to SLRP. */ + SET_FIELD (ss, crp, 0, 0 /* ensure that it can't be overridden! */); + SET_FIELD (ss, srp, 1, 0); + + return parse_and_encode_rpc_optional (pstr); +} + +int +parse_crp_args (char **pstr, + const e2k_opcode_templ *op ATTRIBUTE_UNUSED) +{ + start_ss_syllable (1); + + SET_FIELD (ss, crp, 1, 0); + /* Starting from iset-v3.single CRP implies SS.(srp aka rp_opc_hi) == 0. */ + SET_FIELD (ss, srp, 0, 0 /* ensure that it can't be overridden! */); + + return parse_and_encode_rpc_optional (pstr); +} + +int +parse_slrp_args (char **pstr, + const e2k_opcode_templ *op ATTRIBUTE_UNUSED) +{ + start_ss_syllable (1); + + /* SLRP appeared in iset-v3 and requires `SS.(crp aka rp_opc_lo) == SS.(srp + aka rp_opc_hi) == 1'. */ + SET_FIELD (ss, crp, 1, 0 /* ensure that it can't be overridden! */); + SET_FIELD (ss, srp, 1, 0); + + return parse_and_encode_rpc_optional (pstr); +} int parse_bap_args (char **pstr ATTRIBUTE_UNUSED, @@ -9032,6 +9463,8 @@ e2k_parse_name (char *name, expressionS *e, char *nextcharP) || (e2k_arch_size == 128 && (next_end = e2k_end_of_match (&input_line_pointer[1], "PL")) && (type = O_pl)) + || ((next_end = e2k_end_of_match (&input_line_pointer[1], "DYNOPT")) + && (type = O_dynopt)) ) { /* It's the place where the start of a symbol reference with an @@ -9120,17 +9553,39 @@ e2k_cons_fix_new (fragS *frag, else if (nbytes == 8) reloc = BFD_RELOC_E2K_64_DTPREL; else - as_bad (_("unsupported relocation size %d"), nbytes); + { + /* Formally assign a relocation even for a value of an unsuitable + size to prevent as_fatal () later. */ + reloc = BFD_RELOC_E2K_32_DTPREL; + as_bad (_("invalid @TLS_DTPREL value size %d, should be 4 or 8"), + nbytes); + } break; + case O_got: + /* Assign a meaningful relocation no matter whether NBYTES is suitable or + not so as to prevent a repetetive as_bad () below in this function and + as_fatal () in resolve_symbol_value () later if NBYTES doesn't match + the relocation. */ + reloc = BFD_RELOC_E2K_GOT; + if (nbytes != 4) + as_bad (_("invalid @GOT value size %d, should be 4"), nbytes); + break; + case O_gotoff: if (nbytes == 4) reloc = BFD_RELOC_32_GOTOFF; else if (nbytes == 8) reloc = BFD_RELOC_E2K_GOTOFF64; else - as_bad (_("unsupported gotoff relocation size %d"), nbytes); + { + /* Formally assign a relocation even for a value of an unsuitable + size to prevent as_fatal () later. */ + reloc = BFD_RELOC_32_GOTOFF; + as_bad (_("invalid @GOTOFF value size %d, should be 4 or 8"), + nbytes); + } break; case O_size: @@ -9139,21 +9594,67 @@ e2k_cons_fix_new (fragS *frag, else if (nbytes == 8) reloc = BFD_RELOC_SIZE64; else - as_bad (_("unsupported relocation size %d"), nbytes); + { + /* Formally assign a relocation even for a value of an unsuitable + size to prevent as_fatal () later. */ + reloc = BFD_RELOC_SIZE32; + as_bad (_("invalid @SIZE value size %d, should be 4 or 8"), nbytes); + } break; case O_ap: - gas_assert (e2k_arch_size == 128 && nbytes == 16); + gas_assert (e2k_arch_size == 128); + /* Formally assign a relocation even for a value of an unsuitable + size to prevent as_fatal () later. */ reloc = BFD_RELOC_E2K_AP; + if (nbytes != 16) + as_bad (_("invalid @AP value size %d, should be 16"), nbytes); break; case O_pl: - gas_assert (e2k_arch_size == 128 && (nbytes == 8 || nbytes == 16)); + gas_assert (e2k_arch_size == 128); + /* Formally assign a relocation even for a value of an unsuitable + size to prevent as_fatal () later. */ reloc = BFD_RELOC_E2K_PL; + /* FIXME: there's probably no point in allowing for 8-byte @PL values + here nowadays. Indeed, the only way to obtain such a value is via + a meaningless `.dword sym@PL'. */ + if (nbytes != 8 && nbytes != 16) + as_bad (_("invalid @PL value size %d, should be 8 or 16"), nbytes); + + break; + + case O_dynopt: + if (nbytes == 4) + reloc = BFD_RELOC_E2K_DYNOPT32; + else if (nbytes == 8 ) + reloc = BFD_RELOC_E2K_DYNOPT64; + else + { + /* Formally assign a relocation even for a value of an unsuitable + size to prevent as_fatal () later. */ + reloc = BFD_RELOC_E2K_DYNOPT32; + as_bad (_("invalid @DYNOPT value size %d, should be 4 or 8"), nbytes); + } + break; + + case O_gotplt: + case O_tls_gdmod: + case O_tls_gdrel: + case O_tls_le: + case O_tls_ie: + case O_plt: + case O_islocal: + /* Formally assign a "valid" relocation even for unsupported types of + values to prevent as_fatal () in `resolve_symbol_value ()' later. */ + reloc = BFD_RELOC_E2K_GOT; + as_bad (_("unsupported value type")); break; default: + /* TODO: recall if something different from a symbolic relocation + may come here. */ break; } @@ -9184,6 +9685,9 @@ e2k_cons_fix_new (fragS *frag, if (reloc == BFD_RELOC_NONE) { + /* FIXME(?): something different from a known relocation against a symbol + must have been obtained for the value under consideration. What can it + be and why should it be limited to sizes of 4 and 8? */ switch (nbytes) { case 4: @@ -9221,7 +9725,7 @@ e2k_add_magic_info (void) magic_size_aligned = (magic_size + 3) & 0xfffffffc; magic_sec = subseg_new (".magic", 0); - bfd_set_section_flags (stdoutput, magic_sec, SEC_HAS_CONTENTS | SEC_READONLY); + bfd_set_section_flags (magic_sec, SEC_HAS_CONTENTS | SEC_READONLY); /* Follow the standard note section layout: First write the length of the name string. */ @@ -9249,10 +9753,24 @@ e2k_add_magic_info (void) memcpy (p, magic, magic_size); } +#if defined TE_E2K_UCLIBC +static void +e2k_add_uclibc_poison (void) +{ + bfd_elf_add_obj_attr_int (stdoutput, OBJ_ATTR_GNU, Tag_GNU_E2K_UCLIBC, 1); + +} +#endif /* defined TE_E2K_UCLIBC */ + + void e2k_end (void) { e2k_add_magic_info (); + +#if defined TE_E2K_UCLIBC + e2k_add_uclibc_poison (); +#endif /* defined TE_E2K_UCLIBC */ } /* `.eh_frame' section in PM should be relocated at runtime and therefore @@ -9283,3 +9801,32 @@ e2k_cfi_reloc_for_encoding (int encoding) return BFD_RELOC_NONE; } + +/* Given a symbolic attribute NAME, return the proper integer value. + Returns -1 if the attribute is not known. */ + +int +e2k_convert_symbolic_attribute (const char *name) +{ + static const struct + { + const char * name; + const int tag; + } + attribute_table[] = + { +#define T(tag) {#tag, tag} + T (Tag_GNU_E2K_UCLIBC), +#undef T + }; + unsigned int i; + + if (name == NULL) + return -1; + + for (i = 0; i < ARRAY_SIZE (attribute_table); i++) + if (strcmp (name, attribute_table[i].name) == 0) + return attribute_table[i].tag; + + return -1; +} diff --git a/gas/config/tc-e2k.h b/gas/config/tc-e2k.h index 69eb29a638..03afcb49c9 100644 --- a/gas/config/tc-e2k.h +++ b/gas/config/tc-e2k.h @@ -109,4 +109,7 @@ extern int e2k_eh_frame_alignment (void); #define tc_cfi_reloc_for_encoding e2k_cfi_reloc_for_encoding extern bfd_reloc_code_real_type e2k_cfi_reloc_for_encoding (int encoding); +#define CONVERT_SYMBOLIC_ATTRIBUTE(name) e2k_convert_symbolic_attribute (name) +extern int e2k_convert_symbolic_attribute (const char *); + #endif /* TC_E2K */ diff --git a/gas/config/tc-sparc.c b/gas/config/tc-sparc.c index 7a7a3f7571..d9da6238de 100644 --- a/gas/config/tc-sparc.c +++ b/gas/config/tc-sparc.c @@ -278,6 +278,9 @@ static struct sparc_arch { /* This exists to allow configure.tgt to pass one value to specify both the default machine and default word size. */ { "v9-64", "v9", v9, 64, 0, 0, 0 }, + { "r1000", "r1000", v9, 0, 1, 0, 0 }, + { "r2000", "r2000", v9, 0, 1, HWCAP_SAPPHIRE, 0 }, + { "r2000+", "r2000+", v9, 0, 1, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS }, { NULL, NULL, v8, 0, 0, 0, 0 } }; @@ -494,6 +497,26 @@ md_parse_option (int c, const char *arg) if (opcode_arch == SPARC_OPCODE_ARCH_BAD) as_fatal (_("Bad opcode table, broken assembler.")); + /* This awful hack is required to let a user override an explicitly + specified `-Ar1000' with, say, `-Av9d' when assembling VIS3-dependent + glibc files. */ + if (architecture_requested + && (max_architecture == SPARC_OPCODE_ARCH_R1000 + || max_architecture == SPARC_OPCODE_ARCH_R2000 + || max_architecture == SPARC_OPCODE_ARCH_R2000_PLUS)) + { + architecture_requested = 0; + hwcap_allowed = 0; + } + + /* This hack won't let `-Ar1000' override `-Av9d' if they turn out to + be swapped by LCC. */ + if (architecture_requested + && (opcode_arch == SPARC_OPCODE_ARCH_R1000 + || opcode_arch == SPARC_OPCODE_ARCH_R2000 + || opcode_arch == SPARC_OPCODE_ARCH_R2000_PLUS)) + break; + if (!architecture_requested || opcode_arch > max_architecture) max_architecture = opcode_arch; @@ -1087,6 +1110,55 @@ md_begin (void) } } +/* FIXME: this is a Copy/Paste of `e2k_add_magic_info ()'. What can I do to + avoid it? */ +static void +sparc_add_magic_info (void) +{ + asection *magic_sec; + char *magic, *p; + size_t name_size, name_size_aligned; + size_t magic_size, magic_size_aligned; + static const char name[] = "MCST"; + + if (! (magic = getenv ("MAGIC"))) + return; + + name_size = sizeof (name); + name_size_aligned = (name_size + 3) & 0xfffffffc; + magic_size = strlen (magic) + 1; + magic_size_aligned = (magic_size + 3) & 0xfffffffc; + + magic_sec = subseg_new (".magic", 0); + bfd_set_section_flags (magic_sec, SEC_HAS_CONTENTS | SEC_READONLY); + + /* Follow the standard note section layout: + First write the length of the name string. */ + p = frag_more (4); + md_number_to_chars (p, (valueT) name_size, 4); + + /* Next comes the length of the "MAGIC" itself, i.e., the actual data. */ + p = frag_more (4); + md_number_to_chars (p, (valueT) magic_size, 4); + + /* Write the note NT_MAGIC type. */ + p = frag_more (4); + md_number_to_chars (p, (valueT) NT_MAGIC, 4); + + /* Write the name field. */ + p = frag_more (name_size_aligned); + /* FIXME: I don't remember for sure if `frag_more ()' zeroes out allocated + memory. */ + memset (p, 0, name_size_aligned); + memcpy (p, name, name_size); + + /* Finally, write the descriptor. */ + p = frag_more (magic_size_aligned); + memset (p, 0, magic_size_aligned); + memcpy (p, magic, magic_size); +} + + /* Called after all assembly has been done. */ void @@ -1095,6 +1167,24 @@ sparc_md_end (void) unsigned long mach; #ifndef TE_SOLARIS int hwcaps, hwcaps2; + + if (current_architecture == SPARC_OPCODE_ARCH_R1000 + || current_architecture == SPARC_OPCODE_ARCH_R2000 + || current_architecture == SPARC_OPCODE_ARCH_R2000_PLUS) + { + /* We may introduce ourselves as ultrasparc3 without any harm. This will + let us be executed on a natural ultrasparc3 host. FIXME: now that the + definition for HWS_VB has been moved to `opcodes/sparc-opc.c' I have + to instantiate it as a unification of HWCAP's. */ + if ((hwcap_seen & ~(HWCAP_MUL32 | HWCAP_DIV32 | HWCAP_FSMULD + | HWCAP_POPC | HWCAP_VIS | HWCAP_VIS2)) == 0) + current_architecture = SPARC_OPCODE_ARCH_V9B; + + /* There's no point in writing out this hwcap into an output r1000 file + because it's assumed by default. It's required within GAS to prevent + us from mistakenly falling back to ultrasparc3 one line above. */ + hwcap_seen &= ~HWCAP_R1000; + } #endif if (sparc_arch_size == 64) @@ -1108,6 +1198,9 @@ sparc_md_end (void) case SPARC_OPCODE_ARCH_V9V: mach = bfd_mach_sparc_v9v; break; case SPARC_OPCODE_ARCH_V9M: mach = bfd_mach_sparc_v9m; break; case SPARC_OPCODE_ARCH_M8: mach = bfd_mach_sparc_v9m8; break; + case SPARC_OPCODE_ARCH_R1000: mach = bfd_mach_sparc_v9_r1000; break; + case SPARC_OPCODE_ARCH_R2000: mach = bfd_mach_sparc_v9_r2000; break; + case SPARC_OPCODE_ARCH_R2000_PLUS: mach = bfd_mach_sparc_v9_r2000_plus; break; default: mach = bfd_mach_sparc_v9; break; } else @@ -1123,6 +1216,9 @@ sparc_md_end (void) case SPARC_OPCODE_ARCH_V9V: mach = bfd_mach_sparc_v8plusv; break; case SPARC_OPCODE_ARCH_V9M: mach = bfd_mach_sparc_v8plusm; break; case SPARC_OPCODE_ARCH_M8: mach = bfd_mach_sparc_v8plusm8; break; + case SPARC_OPCODE_ARCH_R1000: mach = bfd_mach_sparc_v8plus_r1000; break; + case SPARC_OPCODE_ARCH_R2000: mach = bfd_mach_sparc_v8plus_r2000; break; + case SPARC_OPCODE_ARCH_R2000_PLUS: mach = bfd_mach_sparc_v8plus_r2000_plus; break; /* The sparclite is treated like a normal sparc. Perhaps it shouldn't be but for now it is (since that's the way it's always been treated). */ @@ -1139,6 +1235,8 @@ sparc_md_end (void) if (hwcaps2) bfd_elf_add_obj_attr_int (stdoutput, OBJ_ATTR_GNU, Tag_GNU_Sparc_HWCAPS2, hwcaps2); #endif + + sparc_add_magic_info (); } /* Return non-zero if VAL is in the range -(MAX+1) to MAX. */ @@ -1676,6 +1774,10 @@ get_hwcap_name (bfd_uint64_t mask) return "cbcond"; if (mask & HWCAP_CRC32C) return "crc32c"; + if (mask & HWCAP_R1000) + return "r1000"; + if (mask & HWCAP_SAPPHIRE) + return "sapphire"; mask = mask >> 32; if (mask & HWCAP2_FJATHPLUS) @@ -3183,10 +3285,6 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn) bfd_uint64_t hwcaps = (((bfd_uint64_t) insn->hwcaps2) << 32) | insn->hwcaps; -#ifndef TE_SOLARIS - if (hwcaps) - hwcap_seen |= hwcaps; -#endif if (v9_arg_p) { needed_arch_mask &= @@ -3236,6 +3334,24 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn) char *p; char required_archs[SPARC_OPCODE_ARCH_MAX * 16]; + /* When identifying MCST-specific duplicates ensure that all + fields that should coincide (i.e. everything except for + `hwcaps{,2}'and `architecture') do really coincide with + the original insn. */ + if (&insn[1] - sparc_opcodes < sparc_num_opcodes + && (insn->match == insn[1].match + && insn->lose == insn[1].lose + && insn->flags == insn[1].flags + && (insn->name == insn[1].name + || !strcmp (insn->name, insn[1].name)) + && (insn->args == insn[1].args + || !strcmp (insn->args, insn[1].args)))) + { + ++insn; + s = argsStart; + continue; + } + /* Create a list of the architectures that support the insn. */ needed_arch_mask &= ~SPARC_OPCODE_SUPPORTED (max_architecture); p = required_archs; @@ -3260,9 +3376,16 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn) return special_case; } +#ifndef TE_SOLARIS + if (hwcaps) + hwcap_seen |= hwcaps; +#endif + + /* Make sure the hwcaps used by the instruction are currently enabled. */ - if (hwcaps & ~hwcap_allowed) + if (!warn_on_bump && architecture_requested + && (hwcaps & ~hwcap_allowed)) { const char *hwcap_name = get_hwcap_name(hwcaps & ~hwcap_allowed); @@ -4723,6 +4846,12 @@ sparc_elf_final_processing (void) elf_elfheader (stdoutput)->e_flags |= EF_SPARC_SUN_US1; else if (current_architecture == SPARC_OPCODE_ARCH_V9B) elf_elfheader (stdoutput)->e_flags |= EF_SPARC_SUN_US1|EF_SPARC_SUN_US3; + else if (current_architecture == SPARC_OPCODE_ARCH_R1000 + || current_architecture == SPARC_OPCODE_ARCH_R2000 + || current_architecture == SPARC_OPCODE_ARCH_R2000_PLUS) + elf_elfheader (stdoutput)->e_flags |= (EF_SPARC_SUN_US1 + | EF_SPARC_SUN_US3 + | EF_SPARC_MCST); } const char * diff --git a/gas/config/te-e2k-uclibc.h b/gas/config/te-e2k-uclibc.h new file mode 100644 index 0000000000..da24ea0ec8 --- /dev/null +++ b/gas/config/te-e2k-uclibc.h @@ -0,0 +1,3 @@ +#include "te-linux.h" + +# define TE_E2K_UCLIBC diff --git a/gas/configure b/gas/configure index 5bccfd9d1b..064bd7115d 100755 --- a/gas/configure +++ b/gas/configure @@ -811,6 +811,7 @@ enable_generate_build_notes enable_mips_fix_loongson3_llsc enable_x86_used_note enable_default_riscv_attribute +enable_e2k_opcodes enable_werror enable_build_warnings with_cpu @@ -1477,6 +1478,7 @@ Optional Features: --enable-x86-used-note generate GNU x86 used ISA and feature properties --enable-default-riscv-attribute generate RISC-V arch attribute by default + --enable-e2k-opcodes enable opcodes for E2K --enable-werror treat compile warnings as errors --enable-build-warnings enable build-time compiler warnings --disable-nls do not use Native Language Support @@ -11343,7 +11345,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11346 "configure" +#line 11348 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -11449,7 +11451,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11452 "configure" +#line 11454 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -11836,7 +11838,7 @@ else We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) +#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; @@ -11882,7 +11884,7 @@ else We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) +#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; @@ -11906,7 +11908,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) +#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; @@ -11951,7 +11953,7 @@ else We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) +#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; @@ -11975,7 +11977,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) +#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; @@ -12154,6 +12156,18 @@ fi using_cgen=no +# Check whether --enable-e2k-opcodes was given. +if test "${enable_e2k_opcodes+set}" = set; then : + enableval=$enable_e2k_opcodes; case "${enableval}" in + yes | no) enable_e2k_opcodes=$enableval ;; + *) as_fn_error $? "enable-e2k-opcodes option must specify either 'yes' or 'no'" "$LINENO" 5 + ;; +esac +else + enable_e2k_opcodes=yes +fi + + # Set the 'development' global. . $srcdir/../bfd/development.sh diff --git a/gas/configure.tgt b/gas/configure.tgt index 337249597c..f4bc4c0889 100644 --- a/gas/configure.tgt +++ b/gas/configure.tgt @@ -58,6 +58,15 @@ case ${cpu} in cr16*) cpu_type=cr16 endian=little ;; crisv32) cpu_type=cris arch=crisv32 ;; crx*) cpu_type=crx endian=little ;; + e2k) + if test $enable_e2k_opcodes = yes ; then + cpu_type=e2k + else + cpu_type=stub + fi + + endian=little + ;; epiphany*) cpu_type=epiphany endian=little ;; fido) cpu_type=m68k ;; hppa*) cpu_type=hppa ;; @@ -183,6 +192,13 @@ case ${generic_target} in dlx-*-*) fmt=elf ;; bpf-*-*) fmt=elf ;; + + e2k-*-linux-gnu) fmt=elf em=linux ;; + e2k-*-linux-uclibc) fmt=elf em=e2k-uclibc ;; + e2k-*-kpda) fmt=elf em=kpda ;; + + stub-*-linux*) fmt=elf em=linux ;; + epiphany-*-*) fmt=elf ;; fr30-*-*) fmt=elf ;; diff --git a/gas/dw2gencfi.c b/gas/dw2gencfi.c index 10ae5a6eff..2320d3cb46 100644 --- a/gas/dw2gencfi.c +++ b/gas/dw2gencfi.c @@ -211,7 +211,10 @@ emit_expr_encoded (expressionS *exp, int encoding, bfd_boolean emit_encoding) { reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, code); char *p = frag_more (size); - gas_assert (size == (unsigned) howto->bitsize / 8); + gas_assert (size == (unsigned) howto->bitsize / 8 + /* Take into account that `bitsize == 128' can't be encoded + now that HOWTOs have been packed. */ + || (size == 16 && howto->bitsize == 0)); md_number_to_chars (p, 0, size); fix_new (frag_now, p - frag_now->fr_literal, size, exp->X_add_symbol, exp->X_add_number, howto->pc_relative, code); @@ -1868,7 +1871,7 @@ static void output_cie (struct cie_entry *cie, bfd_boolean eh_frame, int align) { symbolS *after_size_address, *end_address; - symbolS *aug_start_address, *aug_end_address; + symbolS *aug_start_address, *aug_end_address = NULL; expressionS exp; struct cfi_insn_data *i; int enc; @@ -2019,7 +2022,7 @@ output_fde (struct fde_entry *fde, struct cie_entry *cie, int align) { symbolS *after_size_address, *end_address; - symbolS *aug_start_address, *aug_end_address; + symbolS *aug_start_address, *aug_end_address = NULL; expressionS exp; offsetT augmentation_size; enum dwarf2_format fmt = DWARF2_FORMAT (now_seg); @@ -2471,10 +2474,31 @@ cfi_finish (void) fde->end_address = fde->start_address; } - cie = select_cie_for_fde (fde, TRUE, &first, 2); + cie = select_cie_for_fde (fde, TRUE, &first, +#ifdef TC_E2K + /* Treat PM case specially. */ + (EH_FRAME_ALIGNMENT == 4 + ? EH_FRAME_ALIGNMENT + : +#endif /* defined TC_E2K */ + 2 +#ifdef TC_E2K + ) +#endif /* defined TC_E2K */ + ); fde->eh_loc = symbol_temp_new_now (); output_fde (fde, cie, TRUE, first, - fde->next == NULL ? EH_FRAME_ALIGNMENT : 2); +#ifdef TC_E2K + /* Treat PM case specially. */ + (EH_FRAME_ALIGNMENT == 4 + ? EH_FRAME_ALIGNMENT + : +#endif /* defined TC_E2K */ + (fde->next == NULL ? EH_FRAME_ALIGNMENT : 2) +#ifdef TC_E2K + ) +#endif /* defined TC_E2K */ + ); } } while (EH_FRAME_LINKONCE && seek_next_seg == 2); diff --git a/gas/expr.c b/gas/expr.c index 6f8ccb8230..de7833c769 100644 --- a/gas/expr.c +++ b/gas/expr.c @@ -58,6 +58,8 @@ struct expr_symbol_line { unsigned int line; }; +int hack_for_e2k = 0; + static struct expr_symbol_line *expr_symbol_lines; /* Build a dummy symbol to hold a complex expression. This is how we @@ -71,7 +73,15 @@ make_expr_symbol (expressionS *expressionP) symbolS *symbolP; struct expr_symbol_line *n; - if (expressionP->X_op == O_symbol + /* FIXME: I don't quite understand what this "optimization" is intended to + do. In case `O_add' is constructed for a register and a symbol (e.g., + `%b[3] + dummy') it replaces the latter (i.e. `O_symbol' expression) with + the underlying `O_constant' used to represent its `X_add_symbol' member. + Taking into account that currently I'm unable to properly recognize symbols + when parsing arguments of instructions unless they are `O_symbol's, undo + it. */ + if (hack_for_e2k == 0 + && expressionP->X_op == O_symbol && expressionP->X_add_number == 0) return expressionP->X_add_symbol; @@ -246,6 +256,11 @@ generic_bignum_to_int64 (void) } #endif +#ifdef TC_E2K +extern const char *maybe_symbol_ptr; +extern const char *symbol_ptr; +#endif /* TC_E2K */ + static void integer_constant (int radix, expressionS *expressionP) { @@ -510,6 +525,28 @@ integer_constant (int radix, expressionS *expressionP) && input_line_pointer - 1 == suffix) c = *input_line_pointer++; + + /* FIXME: for now stupidly support `UL', `llu', `ull' and `u' C constant + suffixes encountered while assembling the Kernel and binary compiler for + E2K. A more generic approach is required . . . */ + if (c == 'U' && input_line_pointer[0] == 'L') + { + c = input_line_pointer[1]; + input_line_pointer += 2; + } + else if ((c == 'l' && input_line_pointer[0] == 'l' + && input_line_pointer[1] == 'u') + || (c == 'u' && input_line_pointer[0] == 'l' + && input_line_pointer[1] == 'l')) + + { + c = input_line_pointer[2]; + input_line_pointer += 3; + } + else if ((c == 'u' && input_line_pointer[0] != 'l') + || c == 'U') + c = *input_line_pointer++; + #ifndef tc_allow_U_suffix #define tc_allow_U_suffix 1 #endif @@ -535,6 +572,13 @@ integer_constant (int radix, expressionS *expressionP) if (LOCAL_LABELS_FB && c == 'b') { +#ifdef TC_E2K + /* Now that we are certain that this is a reference to 'b' local + label remember its position for the sake of E2K preprocessing + mode. */ + symbol_ptr = maybe_symbol_ptr; +#endif /* TC_E2K */ + /* Backward ref to local label. Because it is backward, expect it to be defined. */ /* Construct a local label. */ @@ -565,6 +609,13 @@ integer_constant (int radix, expressionS *expressionP) } /* case 'b' */ else if (LOCAL_LABELS_FB && c == 'f') { +#ifdef TC_E2K + /* Now that we are certain that this is a reference to 'f' local + label remember its position for the sake of E2K preprocessing + mode. */ + symbol_ptr = maybe_symbol_ptr; +#endif /* TC_E2K */ + /* Forward reference. Expect symbol to be undefined or unknown. undefined: seen it before. unknown: never seen it before. @@ -775,6 +826,12 @@ operand (expressionS *expressionP, enum expr_mode mode) case '9': input_line_pointer--; +#ifdef TC_E2K + /* This may turn out to be just a constant, not a reference to a local + 'fb' label. Therefore, postpone setting SYMBOL_PTR until you are + absolutely certain. */ + maybe_symbol_ptr = input_line_pointer; +#endif /* TC_E2K */ integer_constant ((NUMBERS_WITH_SUFFIX || flag_m68k_mri) ? 0 : 10, expressionP); @@ -828,9 +885,21 @@ operand (expressionS *expressionP, enum expr_mode mode) } else { - /* The string was only zero. */ - expressionP->X_op = O_constant; - expressionP->X_add_number = 0; + /* FIXME: all this is for the sake of these awful `u', `ul{,}', + `lu', `UL' . . . suffixes which may follow this "only zero". + Ensure that they are slurped by `integer_constant ()' and don't + confuse subsequent parsing. */ + if (hack_for_e2k != 0) + { + input_line_pointer--; + integer_constant (10, expressionP); + } + else + { + /* The string was only zero. */ + expressionP->X_op = O_constant; + expressionP->X_add_number = 0; + } } break; @@ -850,6 +919,14 @@ operand (expressionS *expressionP, enum expr_mode mode) { /* Parse this as a back reference to label 0. */ input_line_pointer--; +#ifdef TC_E2K + /* As far as I understand, this is a special case of `0b' + symbolic reference. The peculiarity is that such labels are + believed to be decimal, while decimal constants don't normally + start with '0'. */ + maybe_symbol_ptr = input_line_pointer; +#endif /* TC_E2K */ + integer_constant (10, expressionP); break; } @@ -907,6 +984,13 @@ operand (expressionS *expressionP, enum expr_mode mode) if (is_label) { input_line_pointer--; +#ifdef TC_E2K + /* As far as I understand, this is a special case of `0f' + symbolic reference. The peculiarity is that such labels + are believed to be decimal, while decimal constants don't + normally start with '0'. */ + maybe_symbol_ptr = input_line_pointer; +#endif /* TC_E2K */ integer_constant (10, expressionP); break; } @@ -1309,6 +1393,13 @@ operand (expressionS *expressionP, enum expr_mode mode) } #endif +#ifdef TC_E2K + /* As far as I understand, here is the place to remember the start of + a symbol reference without an explicitly specified relocation for + the sake of E2K preprocessing mode. */ + symbol_ptr = name; +#endif /* TC_E2K */ + symbolP = symbol_find_or_make (name); /* If we have an absolute symbol or a reg, then we know its @@ -1982,7 +2073,15 @@ expr (int rankarg, /* Larger # is higher rank. */ break; } } - else if (resultP->X_op == O_symbol + + /* FIXME: this hack lets me prevent `O_add' of two `O_symbol's from being + converted to `O_add' of two underlying `O_constant's when parsing + arguments of LD/ST instructions. In the latter case I'd be unable to + properly recognize the (forbidden) sum of two symbols. I suspect that + it may very well break something when parsing `O_subtract' outside of + instructions . . . */ + else if (hack_for_e2k == 0 + && resultP->X_op == O_symbol && right.X_op == O_symbol && (op_left == O_add || op_left == O_subtract diff --git a/gas/testsuite/gas/sparc/r2000_plus.s b/gas/testsuite/gas/sparc/r2000_plus.s new file mode 100644 index 0000000000..6b421ee7aa --- /dev/null +++ b/gas/testsuite/gas/sparc/r2000_plus.s @@ -0,0 +1,85 @@ +# Instructions stolen by r2000+ from foreign Sparc CPUs. + + fchksm16 %f54, %f56, %f58 + + flcmps %fcc0, %f1, %f3 + flcmps %fcc1, %f3, %f5 + flcmps %fcc2, %f5, %f7 + flcmps %fcc3, %f7, %f9 + + flcmpd %fcc0, %f12, %f14 + flcmpd %fcc1, %f14, %f16 + flcmpd %fcc2, %f16, %f18 + flcmpd %fcc3, %f18, %f20 + + fmean16 %f50, %f52, %f54 + + pdistn %f48, %f50, %g1 + + xmulx %o1, %o2, %o3 + + xmulxhi %o4, %o5, %o6 + + fpadd64 %f52, %f54, %f56 + + fpsub64 %f56, %f58, %f60 + + fpadd8 %f2, %f4, %f8 + + fpadds8 %f8, %f10, %f12 + + fpaddus8 %f12, %f14, %f16 + + fpaddus16 %f16, %f18, %f20 + + fpsub8 %f2, %f4, %f6 + + fpsubs8 %f6, %f8, %f10 + + fpsubus8 %f10, %f12, %f14 + + fpsubus16 %f14, %f16, %f18 + + fpcmple8 %f2, %f4, %g1 + + fpcmpgt8 %f4, %f6, %g2 + + fpcmpule16 %f6, %f8, %g3 + + fpcmpugt16 %f8, %f10, %g4 + + fpcmpule32 %f10, %f12, %g5 + + fpcmpugt32 %f12, %f14, %g6 + + fpmax8 %f14, %f16, %f18 + + fpmax16 %f18, %f20, %f22 + + fpmax32 %f22, %f24, %f26 + + fpmaxu8 %f26, %f28, %f30 + + fpmaxu16 %f30, %f32, %f34 + + fpmaxu32 %f34, %f36, %f38 + + fpmin8 %f38, %f40, %f42 + + fpmin16 %f42, %f44, %f46 + + fpmin32 %f46, %f48, %f50 + + fpminu8 %f50, %f52, %f54 + + fpminu16 %f54, %f56, %f58 + + fpminu32 %f58, %f60, %f62 + + +# Original r2000+ instructions + + fpcsl32 %f0, %f2, %f4 + fpcsl64 %f6, %f8, %f10 + fpcsr32 %f12, %f14, %f16 + fpcsr64 %f18, %f20, %f22 diff --git a/gold/Makefile.in b/gold/Makefile.in index f2906ede8b..dca43c01d1 100644 --- a/gold/Makefile.in +++ b/gold/Makefile.in @@ -792,13 +792,14 @@ DEFFILES = arm-reloc.def aarch64-reloc.def EXTRA_DIST = yyscript.c yyscript.h TARGETSOURCES = \ i386.cc x86_64.cc sparc.cc powerpc.cc arm.cc arm-reloc-property.cc tilegx.cc \ - mips.cc aarch64.cc aarch64-reloc-property.cc s390.cc + mips.cc aarch64.cc aarch64-reloc-property.cc s390.cc e2k.cc ALL_TARGETOBJS = \ i386.$(OBJEXT) x86_64.$(OBJEXT) sparc.$(OBJEXT) powerpc.$(OBJEXT) \ arm.$(OBJEXT) arm-reloc-property.$(OBJEXT) tilegx.$(OBJEXT) \ mips.$(OBJEXT) aarch64.$(OBJEXT) aarch64-reloc-property.$(OBJEXT) \ - s390.$(OBJEXT) + s390.$(OBJEXT) \ + e2k.$(OBJEXT) libgold_a_SOURCES = $(CCFILES) $(HFILES) $(YFILES) $(DEFFILES) libgold_a_LIBADD = $(LIBOBJS) diff --git a/gold/e2k.cc b/gold/e2k.cc index de715d7a83..c5503cd342 100644 --- a/gold/e2k.cc +++ b/gold/e2k.cc @@ -25,6 +25,12 @@ public: protected: void do_write(Output_file*) { } + + // Write to a map file. + void + do_print_to_mapfile(Mapfile* mapfile) const + { mapfile->print_output_data(this, _("** GOT PLT")); } + }; // A class to handle the PLT data. @@ -43,6 +49,11 @@ public: protected: void do_write(Output_file*) { } + + // Write to a map file. + void + do_print_to_mapfile(Mapfile* mapfile) const + { mapfile->print_output_data(this, _("** PLT")); } }; template @@ -324,6 +335,7 @@ const Target::Target_info Target_e2k<32>::e2k_info = NULL, // attributes_vendor "_start", // entry_symbol_name 32, // hash_entry_size + elfcpp::SHT_PROGBITS, // unwind_section_type }; template<> @@ -352,6 +364,7 @@ const Target::Target_info Target_e2k<64>::e2k_info = NULL, // attributes_vendor "_start", // entry_symbol_name 64, // hash_entry_size + elfcpp::SHT_PROGBITS, // unwind_section_type }; // Class for performing E2K-specific sophisticated relocations for which @@ -576,6 +589,7 @@ Target_e2k::Scan::local( case elfcpp::R_E2K_64_TLS_LE: case elfcpp::R_E2K_GOT: case elfcpp::R_E2K_GOTOFF: + case elfcpp::R_E2K_64_GOTOFF_LIT: case elfcpp::R_E2K_DISP: case elfcpp::R_E2K_GOTPLT: case elfcpp::R_E2K_ISLOCAL: @@ -647,6 +661,7 @@ Target_e2k::Scan::global( break; case elfcpp::R_E2K_GOTOFF: + case elfcpp::R_E2K_64_GOTOFF_LIT: break; case elfcpp::R_E2K_DISP: @@ -781,6 +796,7 @@ Target_e2k::Relocate::relocate( break; case elfcpp::R_E2K_GOTOFF: + case elfcpp::R_E2K_64_GOTOFF_LIT: { unsigned int got_offset; got_offset = psymval->value(object, 0) - target->got_address (); diff --git a/include/elf/common.h b/include/elf/common.h index d44d2b419c..aa965889c8 100644 --- a/include/elf/common.h +++ b/include/elf/common.h @@ -716,7 +716,7 @@ /* Values of note segment descriptor types for object files on MCST systems. Note name is "MCST". */ -#define NT_MAGIC 1 +#define NT_MAGIC 1 /* Values of note segment descriptor types for object files. */ diff --git a/include/elf/e2k.h b/include/elf/e2k.h index 7c532a352c..3fcedf88e7 100644 --- a/include/elf/e2k.h +++ b/include/elf/e2k.h @@ -41,6 +41,7 @@ START_RELOC_NUMBERS (elf_e2k_reloc_type) RELOC_NUMBER (R_E2K_32_RELATIVE, 10) RELOC_NUMBER (R_E2K_32_IRELATIVE, 11) RELOC_NUMBER (R_E2K_32_SIZE, 12) + RELOC_NUMBER (R_E2K_32_DYNOPT, 13) /* 64-bit ones. */ RELOC_NUMBER (R_E2K_64_ABS, 50) @@ -61,6 +62,7 @@ START_RELOC_NUMBERS (elf_e2k_reloc_type) this will make it impossible to use these relocations in 32-bit mode, but they shouldn't be intended for that in fact . . . */ RELOC_NUMBER (R_E2K_64_GOTOFF_LIT, 256) + RELOC_NUMBER (R_E2K_64_DYNOPT, 257) /* All TLS-specific 32, 64-bit and common relocations are grouped here, which is rather inconsistent. */ @@ -100,6 +102,7 @@ END_RELOC_NUMBERS (R_E2K_max) #define EF_E2K_4MB_PAGES 8 #define EF_E2K_INCOMPAT 16 #define EF_E2K_PM 32 +#define EF_E2K_PACK_SEGMENTS 64 /* Three bit E2K machine type field. */ @@ -127,6 +130,9 @@ END_RELOC_NUMBERS (R_E2K_max) after they are eliminated from the Kernel. */ #define E_E2K_MACH_8C 19 #define E_E2K_MACH_1CPLUS 20 +#define E_E2K_MACH_12C 21 +#define E_E2K_MACH_16C 22 +#define E_E2K_MACH_2C3 23 @@ -161,4 +167,19 @@ enum DT_REAL_PLTGOT, }; +/* Object attribute tags. */ +enum +{ + /* For `vendor == OBJ_ATTR_GNU' 0-3 tags are generic. According to `gnu_obj_ + attrs_arg_type ()' even-numbered GNU tags take integers and odd-numbered + ones take strings. According to a comment in this function and as.info + `(Tag & 0x2) should be also equal to 0' for architecture dependent ones, + which is why 5 may be used for the next E2K-specific string GNU attribute + and 8 for the integer one. FIXME: alternatively `vendor == OBJ_ATTR_PROC' + attributes implying no limitations on the values of Tags could be used for + the same purpose, but they would require the implementation of an + additional E2K-specific method to retrieve the type of the attribute. */ + Tag_GNU_E2K_UCLIBC = 4 +}; + #endif /* _ELF_E2K_H */ diff --git a/include/elf/sparc.h b/include/elf/sparc.h index e3048b9944..57770c0c26 100644 --- a/include/elf/sparc.h +++ b/include/elf/sparc.h @@ -264,5 +264,7 @@ enum #define ELF_SPARC_HWCAP2_FPCMPSHL 0x00400000 /* Partition compare with shifted result */ #define ELF_SPARC_HWCAP2_RLE 0x00800000 /* Run-length encoded burst and length */ #define ELF_SPARC_HWCAP2_SHA3 0x01000000 /* SHA3 instruction */ +#define ELF_SPARC_HWCAP2_SAPPHIRE_PLUS \ + 0x02000000 /* MCST Sapphire+ inherent to R2000+ processor */ #endif /* _ELF_SPARC_H */ diff --git a/include/opcode/e2k.h b/include/opcode/e2k.h index 7490cc9d18..e004030b51 100644 --- a/include/opcode/e2k.h +++ b/include/opcode/e2k.h @@ -30,6 +30,7 @@ #define AAURR 23 #define AAURW 24 #define ALOPF17 25 +#define ALOPF19 26 #define ALF_PART \ u_int8_t alopf; \ @@ -69,6 +70,11 @@ /* ALES.opce values. */ #define NONE 0xc0 +/* See Table B.2.6 in `iset-v6.single'. */ +#define QPCHECKS 0xc0 +#define QPCHECKD 0xc1 +#define QPCHECKQ 0xc2 + /* It seems that LAS doesn't support %xr's, that's why everywhere where an x-args is supposed we @@ -372,7 +378,7 @@ int parse_setcmd_args (char **, const e2k_opcode_templ *); int parse_setsft_args (char **, const e2k_opcode_templ *); int parse_wait_args (char **, const e2k_opcode_templ *); int parse_ct_args (char **, const e2k_opcode_templ *); -int parse_hcall_args (char **, const e2k_opcode_templ *); +int parse_hicall_args (char **, const e2k_opcode_templ *); int parse_ipd_args (char **, const e2k_opcode_templ *); int parse_loop_mode_args (char **, const e2k_opcode_templ *); @@ -380,6 +386,9 @@ int parse_alc_args (char **, const e2k_opcode_templ *); int parse_abn_args (char **, const e2k_opcode_templ *); int parse_abp_args (char **, const e2k_opcode_templ *); int parse_abg_args (char **, const e2k_opcode_templ *); +int parse_srp_args (char **, const e2k_opcode_templ *); +int parse_crp_args (char **, const e2k_opcode_templ *); +int parse_slrp_args (char **, const e2k_opcode_templ *); int parse_bap_args (char **, const e2k_opcode_templ *); int parse_eap_args (char **, const e2k_opcode_templ *); @@ -388,7 +397,7 @@ int parse_pass_args (char **, const e2k_opcode_templ *); int parse_andp_args (char **, const e2k_opcode_templ *); int parse_landp_args (char **, const e2k_opcode_templ *); int parse_ibranch_args (char **, const e2k_opcode_templ *); -int parse_done_hret_glaunch_args (char **, const e2k_opcode_templ *); +int parse_done_hiret_glaunch_args (char **, const e2k_opcode_templ *); int parse_incr_args (char **, const e2k_opcode_templ *); int parse_mova_args (char **, const e2k_opcode_templ *); diff --git a/include/opcode/e2k/mu-regs.def b/include/opcode/e2k/mu-regs.def index 13d355781e..d017494011 100644 --- a/include/opcode/e2k/mu-regs.def +++ b/include/opcode/e2k/mu-regs.def @@ -13,7 +13,7 @@ ENTRY (1, "%root_ptb", 0x40, 0x8, 2, 1) ENTRY (6, "%u_pptb", 0x40, 0x8, 2, 1) ENTRY (1, "%trap_point", 0x50, 0x8, 2, 1) -ENTRY (1, "%trap_count", 0x60, 0x8, 2, 0) +ENTRY (1, "%trap_count", 0x60, 0x8, 2, 6) ENTRY (1, "%mpt_b", 0x70, 0x8, 2, 1) ENTRY (1, "%pci_l_b", 0x80, 0x8, 2, 1) ENTRY (1, "%us_cl_d", 0x90, 0x8, 2, 1) @@ -104,12 +104,12 @@ ENTRY (6, "%sh_mmu_cr", 0x4a0, 0x8, 2, 1) ENTRY (6, "%os_vab", 0x4c0, 0x8, 2, 1) ENTRY (6, "%sh_os_vab", 0x4d0, 0x8, 2, 1) -ENTRY (1, "%us_cl_b", 0x24, 0xd, 5, 0) -ENTRY (1, "%us_cl_up", 0x124, 0xd, 5, 0) -ENTRY (1, "%us_cl_m0", 0x4, 0xd, 5, 0) -ENTRY (1, "%us_cl_m1", 0x84, 0xd, 5, 0) -ENTRY (1, "%us_cl_m2", 0x104, 0xd, 5, 0) -ENTRY (1, "%us_cl_m3", 0x184, 0xd, 5, 0) +ENTRY (1, "%us_cl_b", 0x24, 0xd, 5, 6) +ENTRY (1, "%us_cl_up", 0x124, 0xd, 5, 6) +ENTRY (1, "%us_cl_m0", 0x4, 0xd, 5, 6) +ENTRY (1, "%us_cl_m1", 0x84, 0xd, 5, 6) +ENTRY (1, "%us_cl_m2", 0x104, 0xd, 5, 6) +ENTRY (1, "%us_cl_m3", 0x184, 0xd, 5, 6) ENTRY (1, "%mlta0", 0x5, 0xd, 2, 0) DIS_ENTRY (1, "%mlta0", 0x6, 0xd, 2, 0) diff --git a/include/opcode/e2k/state-regs.def.new b/include/opcode/e2k/state-regs.def.new index 9cb2aa64cf..0044bdf939 100644 --- a/include/opcode/e2k/state-regs.def.new +++ b/include/opcode/e2k/state-regs.def.new @@ -6,7 +6,7 @@ ENTRY(1, "%psr", 0x00, 1, 0) ENTRY(1, "%wd", 0x01, 0, 0) - ENTRY(1, "%core_mode", 0x04, 0, 0) + ENTRY(3, "%core_mode", 0x04, 0, 0) ENTRY(1, "%cwd", 0x06, 1, 0) ENTRY(1, "%psp.hi", 0x07, 1, 0) ENTRY(1, "%psp.lo", 0x09, 1, 0) @@ -72,6 +72,10 @@ ENTRY(1, "%dimcr", 0x41, 0, 0) ENTRY(1, "%dibsr", 0x42, 0, 0) ENTRY(1, "%dtcr", 0x43, 0, 0) + + ENTRY(6, "%dimtp.hi", 0x46, 0, 0) + ENTRY(6, "%dimtp.lo", 0x47, 0, 0) + ENTRY(1, "%dibar0", 0x48, 0, 0) ENTRY(1, "%dibar1", 0x49, 0, 0) ENTRY(1, "%dibar2", 0x4a, 0, 0) @@ -116,6 +120,8 @@ ENTRY(6, "%bu_pcsp.hi", 0x74, 0, 0) ENTRY(6, "%bu_pcsp.lo", 0x75, 0, 0) + + ENTRY(6, "%sh_wd", 0x76, 0, 0) ENTRY(2, "%cu_hw0", 0x78, 0, 0) ENTRY(5, "%cu_hw1", 0x79, 0, 0) @@ -130,7 +136,7 @@ ENTRY(1, "%ilcr", 0x87, 0, 0) ENTRY(1, "%br", 0x88, 0, 0) ENTRY(1, "%bgr", 0x89, 0, 0) - ENTRY(1, "%idr", 0x8a, 0, 0) + ENTRY(2, "%idr", 0x8a, 0, 0) ENTRY(1, "%clkr", 0x90, 0, 0) ENTRY(3, "%rndpr", 0x91, 0, 0) ENTRY(3, "%sclkr", 0x92, 0, 0) diff --git a/include/opcode/sparc.h b/include/opcode/sparc.h index dd1b85d6cb..530844058b 100644 --- a/include/opcode/sparc.h +++ b/include/opcode/sparc.h @@ -59,8 +59,10 @@ enum sparc_opcode_arch_val multiply and Fujitsu fp multiply-add. */ SPARC_OPCODE_ARCH_V9M, /* V9 with OSA2015 and M7 additions. */ SPARC_OPCODE_ARCH_M8, /* V9 with OSA2017 and M8 additions. */ - SPARC_OPCODE_ARCH_V9_MCST, /* V9B with MCST additions. */ - SPARC_OPCODE_ARCH_MAX = SPARC_OPCODE_ARCH_V9_MCST, + SPARC_OPCODE_ARCH_R1000, /* V9B with R1000 additions. */ + SPARC_OPCODE_ARCH_R2000, /* V9B with R{1,2}000 additions. */ + SPARC_OPCODE_ARCH_R2000_PLUS, /* V9B with R{1,2}000 and R2000+ additions. */ + SPARC_OPCODE_ARCH_MAX = SPARC_OPCODE_ARCH_R2000_PLUS, SPARC_OPCODE_ARCH_BAD /* Error return from sparc_opcode_lookup_arch. */ }; @@ -81,7 +83,7 @@ typedef struct sparc_opcode_arch EG: For v7 this would be (SPARC_OPCODE_ARCH_MASK (..._V6) | SPARC_OPCODE_ARCH_MASK (..._V7)). These are short's because sparc_opcode.architecture is. */ - short supported; + int supported; /* Bitmaps describing the set of hardware capabilities implemented by the opcode arch. */ int hwcaps; @@ -116,7 +118,11 @@ typedef struct sparc_opcode unsigned int flags; unsigned int hwcaps; unsigned int hwcaps2; - short architecture; /* Bitmask of sparc_opcode_arch_val's. */ + int architecture; /* Bitmask of sparc_opcode_arch_val's. FIXME: while + the original short is still wide enough for + `SPARC_OPCODE_ARCH_V9_MCST == 15'th bit to fit into + it, its signed nature breaks `(1 << arch) <= + needed_arch_mask' comparison in `sparc_ip ()'. */ } sparc_opcode; /* Struct for ASIs - to handle ASIs introduced in a specific architecture */ @@ -124,7 +130,7 @@ typedef struct { int value; const char *name; - short architecture; + int architecture; } sparc_asi; /* FIXME: Add F_ANACHRONISTIC flag for v9. */ @@ -201,6 +207,11 @@ typedef struct #define HWCAP2_SHA3 0x01000000 /* SHA3 instruction */ +/* Intended for R2000+ (Bug #117014). */ +#define HWCAP2_SAPPHIRE_PLUS \ + 0x02000000 + + /* All sparc opcodes are 32 bits, except for the `set' instruction (really a macro), which is 64 bits. It is handled as a special case. diff --git a/ld/Makefile.am b/ld/Makefile.am index 02c4fc1639..63a431876c 100644 --- a/ld/Makefile.am +++ b/ld/Makefile.am @@ -213,6 +213,9 @@ ALL_EMULATION_SOURCES = \ ed30v_o.c \ ed30velf.c \ eelf32_dlx.c \ + eelf32_e2k.c \ + eelf32_e2k_pm.c \ + eelf32_e2k_pm_uclibc.c \ eelf32_sparc.c \ eelf32_sparc_sol2.c \ eelf32_sparc_vxworks.c \ @@ -418,6 +421,10 @@ ALL_64_EMULATION_SOURCES = \ eelf32mipswindiss.c \ eelf64_aix.c \ eelf64bpf.c \ + eelf64_e2k.c \ + eelf64_e2k_pm.c \ + eelf64_e2k_kpda.c \ + eelf64_e2k_uclibc.c \ eelf64_ia64.c \ eelf64_ia64_fbsd.c \ eelf64_ia64_vms.c \ @@ -613,7 +620,7 @@ if AMDEP else GENDEPDIR= endif -GENSCRIPTS = $(SHELL) $(srcdir)/genscripts.sh "${srcdir}" "${libdir}" "${prefix}" "${exec_prefix}" @host@ @target@ @target_alias@ "$(GENDEPDIR)" "${LIB_PATH}" "@EMULATION_LIBPATH@" "@NATIVE_LIB_DIRS@" @use_sysroot@ @enable_initfini_array@ +GENSCRIPTS = $(SHELL) $(srcdir)/genscripts.sh "${srcdir}" "${libdir}" "${prefix}" "${exec_prefix}" @host@ @target@ @target_alias@ "$(GENDEPDIR)" "${LIB_PATH}" "@EMULATION_LIBPATH@" "@NATIVE_LIB_DIRS@" @use_sysroot@ @enable_initfini_array@ @enable_debian_multiarch@ GEN_DEPENDS = $(srcdir)/genscripts.sh stringify.sed @TDIRS@ @@ -937,6 +944,13 @@ $(ALL_EMULATION_SOURCES) $(ALL_64_EMULATION_SOURCES): $(GEN_DEPENDS) @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ehppa64linux.Pc@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ei386pep.Pc@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emmo.Pc@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32_e2k.Pc@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32_e2k_pm.Pc@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32_e2k_pm_uclibc.Pc@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_e2k.Pc@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_e2k_pm.Pc@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_e2k_kpda.Pc@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_e2k_uclibc.Pc@am__quote@ # We need this for automake to use YLWRAP. EXTRA_ld_new_SOURCES = deffilep.y ldlex.l @@ -985,13 +999,13 @@ development.exp: $(BFDDIR)/development.sh noinst_LTLIBRARIES = libldtestplug.la libldtestplug2.la \ libldtestplug3.la libldtestplug4.la libldtestplug_la_SOURCES = testplug.c -libldtestplug_la_CFLAGS= -g -O2 +libldtestplug_la_CFLAGS= -g -O0 libldtestplug_la_LDFLAGS = -no-undefined -rpath /nowhere libldtestplug2_la_SOURCES = testplug2.c -libldtestplug2_la_CFLAGS= -g -O2 +libldtestplug2_la_CFLAGS= -g -O0 libldtestplug2_la_LDFLAGS = -no-undefined -rpath /nowhere libldtestplug3_la_SOURCES = testplug3.c -libldtestplug3_la_CFLAGS= -g -O2 +libldtestplug3_la_CFLAGS= -g -O0 libldtestplug3_la_LDFLAGS = -no-undefined -rpath /nowhere libldtestplug4_la_SOURCES = testplug4.c libldtestplug4_la_CFLAGS= -g -O2 diff --git a/ld/Makefile.in b/ld/Makefile.in index 2fe12e14f6..d5810f70c5 100644 --- a/ld/Makefile.in +++ b/ld/Makefile.in @@ -491,6 +491,7 @@ dvidir = @dvidir@ elf_list_options = @elf_list_options@ elf_plt_unwind_list_options = @elf_plt_unwind_list_options@ elf_shlib_list_options = @elf_shlib_list_options@ +enable_debian_multiarch = @enable_debian_multiarch@ enable_initfini_array = @enable_initfini_array@ exec_prefix = @exec_prefix@ host = @host@ @@ -696,6 +697,9 @@ ALL_EMULATION_SOURCES = \ ed30v_o.c \ ed30velf.c \ eelf32_dlx.c \ + eelf32_e2k.c \ + eelf32_e2k_pm.c \ + eelf32_e2k_pm_uclibc.c \ eelf32_sparc.c \ eelf32_sparc_sol2.c \ eelf32_sparc_vxworks.c \ @@ -900,6 +904,10 @@ ALL_64_EMULATION_SOURCES = \ eelf32mipswindiss.c \ eelf64_aix.c \ eelf64bpf.c \ + eelf64_e2k.c \ + eelf64_e2k_pm.c \ + eelf64_e2k_kpda.c \ + eelf64_e2k_uclibc.c \ eelf64_ia64.c \ eelf64_ia64_fbsd.c \ eelf64_ia64_vms.c \ @@ -975,7 +983,7 @@ SRC_POTFILES = $(CFILES) $(HFILES) BLD_POTFILES = $(ALL_EMULATION_SOURCES) $(ALL_64_EMULATION_SOURCES) @AMDEP_FALSE@GENDEPDIR = @AMDEP_TRUE@GENDEPDIR = $(DEPDIR) -GENSCRIPTS = $(SHELL) $(srcdir)/genscripts.sh "${srcdir}" "${libdir}" "${prefix}" "${exec_prefix}" @host@ @target@ @target_alias@ "$(GENDEPDIR)" "${LIB_PATH}" "@EMULATION_LIBPATH@" "@NATIVE_LIB_DIRS@" @use_sysroot@ @enable_initfini_array@ +GENSCRIPTS = $(SHELL) $(srcdir)/genscripts.sh "${srcdir}" "${libdir}" "${prefix}" "${exec_prefix}" @host@ @target@ @target_alias@ "$(GENDEPDIR)" "${LIB_PATH}" "@EMULATION_LIBPATH@" "@NATIVE_LIB_DIRS@" @use_sysroot@ @enable_initfini_array@ @enable_debian_multiarch@ GEN_DEPENDS = $(srcdir)/genscripts.sh stringify.sed # We need this for automake to use YLWRAP. @@ -1001,13 +1009,13 @@ noinst_LTLIBRARIES = libldtestplug.la libldtestplug2.la \ libldtestplug3.la libldtestplug4.la libldtestplug_la_SOURCES = testplug.c -libldtestplug_la_CFLAGS = -g -O2 +libldtestplug_la_CFLAGS = -g -O0 libldtestplug_la_LDFLAGS = -no-undefined -rpath /nowhere libldtestplug2_la_SOURCES = testplug2.c -libldtestplug2_la_CFLAGS = -g -O2 +libldtestplug2_la_CFLAGS = -g -O0 libldtestplug2_la_LDFLAGS = -no-undefined -rpath /nowhere libldtestplug3_la_SOURCES = testplug3.c -libldtestplug3_la_CFLAGS = -g -O2 +libldtestplug3_la_CFLAGS = -g -O0 libldtestplug3_la_LDFLAGS = -no-undefined -rpath /nowhere libldtestplug4_la_SOURCES = testplug4.c libldtestplug4_la_CFLAGS = -g -O2 @@ -1249,6 +1257,9 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ed30v_o.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ed30velf.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32_dlx.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32_e2k.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32_e2k_pm.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32_e2k_pm_uclibc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32_sparc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32_sparc_sol2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32_sparc_vxworks.Po@am__quote@ @@ -1339,6 +1350,10 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32xtensa.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32z80.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_aix.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_e2k.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_e2k_kpda.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_e2k_pm.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_e2k_uclibc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_ia64.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_ia64_fbsd.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_ia64_vms.Po@am__quote@ @@ -2532,6 +2547,13 @@ $(ALL_EMULATION_SOURCES) $(ALL_64_EMULATION_SOURCES): $(GEN_DEPENDS) @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ehppa64linux.Pc@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ei386pep.Pc@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emmo.Pc@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32_e2k.Pc@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32_e2k_pm.Pc@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32_e2k_pm_uclibc.Pc@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_e2k.Pc@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_e2k_pm.Pc@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_e2k_kpda.Pc@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_e2k_uclibc.Pc@am__quote@ check-DEJAGNU: site.exp srcroot=`cd $(srcdir) && pwd`; export srcroot; \ diff --git a/ld/config.in b/ld/config.in index 2f4e5ea33e..b40e012b35 100644 --- a/ld/config.in +++ b/ld/config.in @@ -243,6 +243,9 @@ /* Version number of package */ #undef VERSION +/* Define to inhibit searching native /etc/ld.so.conf */ +#undef WITH_CROSS_HOST + /* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a `char[]'. */ #undef YYTEXT_POINTER diff --git a/ld/configure b/ld/configure index c3bc15dec3..c59019dd69 100755 --- a/ld/configure +++ b/ld/configure @@ -649,6 +649,7 @@ STRINGIFY zlibinc zlibdir enable_initfini_array +enable_debian_multiarch NATIVE_LIB_DIRS HDEFINES do_compare @@ -826,6 +827,7 @@ with_lib_path enable_targets enable_64_bit_bfd with_sysroot +with_cross_host enable_gold enable_got enable_compressed_debug_sections @@ -838,6 +840,7 @@ enable_libctf enable_werror enable_build_warnings enable_nls +enable_debian_multiarch enable_initfini_array with_system_zlib ' @@ -1509,6 +1512,7 @@ Optional Features: --enable-werror treat compile warnings as errors --enable-build-warnings enable build-time compiler warnings --disable-nls do not use Native Language Support + --enable-debian-multiarch use debian multiarch library search paths --disable-initfini-array do not use .init_array/.fini_array sections Optional Packages: @@ -1519,6 +1523,7 @@ Optional Packages: --with-gnu-ld assume the C compiler uses GNU ld [default=no] --with-lib-path=dir1:dir2... set default LIB_PATH --with-sysroot=DIR Search for usr/lib et al within DIR. + --with-cross-host make native ld behave as if it were cross --with-system-zlib use installed libz Some influential environment variables: @@ -12037,7 +12042,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 12040 "configure" +#line 12045 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -12143,7 +12148,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 12146 "configure" +#line 12151 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -15793,6 +15798,19 @@ fi + +# Check whether --with-cross-host was given. +if test "${with_cross_host+set}" = set; then : + withval=$with_cross_host; +fi + + +if test -n "$with_cross_host" && test x"$with_cross_host" != x"no"; then + +$as_echo "#define WITH_CROSS_HOST 1" >>confdefs.h + +fi + # Check whether --enable-gold was given. if test "${enable_gold+set}" = set; then : enableval=$enable_gold; case "${enableval}" in @@ -17315,6 +17333,18 @@ if test "$ac_res" != no; then : fi +# Check whether --enable-debian-multiarch was given. +if test "${enable_debian_multiarch+set}" = set; then : + enableval=$enable_debian_multiarch; case "${enableval}" in + yes|no) ;; + *) as_fn_error $? "invalid --enable-debian-multiarch argument" "$LINENO" 5 ;; + esac +else + enable_debian_multiarch=no +fi + + + # Check whether --enable-initfini-array was given. if test "${enable_initfini_array+set}" = set; then : enableval=$enable_initfini_array; case "${enableval}" in diff --git a/ld/configure.ac b/ld/configure.ac index 172398ff84..4c702bb87e 100644 --- a/ld/configure.ac +++ b/ld/configure.ac @@ -94,6 +94,13 @@ AC_SUBST(use_sysroot) AC_SUBST(TARGET_SYSTEM_ROOT) AC_SUBST(TARGET_SYSTEM_ROOT_DEFINE) +AC_ARG_WITH(cross-host, [ --with-cross-host make native ld behave as if it were cross]) + +if test -n "$with_cross_host" && test x"$with_cross_host" != x"no"; then + AC_DEFINE([WITH_CROSS_HOST], 1, + [Define to inhibit searching native /etc/ld.so.conf]) +fi + dnl Use --enable-gold to decide if this linker should be the default. dnl "install_as_default" is set to false if gold is the default linker. dnl "installed_linker" is the installed BFD linker name. @@ -281,6 +288,14 @@ AC_FUNC_MMAP AC_SEARCH_LIBS([dlopen], [dl]) +AC_ARG_ENABLE(debian-multiarch, +[ --enable-debian-multiarch use debian multiarch library search paths], +[case "${enableval}" in + yes|no) ;; + *) AC_MSG_ERROR([invalid --enable-debian-multiarch argument]) ;; + esac], [enable_debian_multiarch=no]) +AC_SUBST(enable_debian_multiarch) + AC_ARG_ENABLE(initfini-array, [ --disable-initfini-array do not use .init_array/.fini_array sections], [case "${enableval}" in diff --git a/ld/configure.tgt b/ld/configure.tgt index 1835a178ba..59b4623868 100644 --- a/ld/configure.tgt +++ b/ld/configure.tgt @@ -256,8 +256,11 @@ d30v-*-*) targ_emul=d30velf dlx-*-elf*) targ_emul=elf32_dlx targ_extra_ofiles=ldelfgen.o ;; -e2k-mcst-linux-gnu) targ_emul=elf64_e2k - targ_extra_emuls="elf32_e2k elf32_e2k_pm_latest" +e2k-mcst-linux-gnu) targ_emul=elf64_e2k + targ_extra_emuls="elf32_e2k elf32_e2k_pm elf64_e2k_pm" + ;; +e2k-mcst-linux-uclibc) targ_emul=elf64_e2k_uclibc + targ_extra_emuls="elf32_e2k_pm_uclibc" ;; e2k-mcst-kpda) targ_emul=elf64_e2k_kpda ;; @@ -1076,6 +1079,10 @@ alpha*-*-*) NATIVE_LIB_DIRS='/usr/local/lib /usr/ccs/lib /lib /usr/lib' ;; +e2k-mcst-kpda) + NATIVE_LIB_DIRS='/e2kle/lib /e2kle/usr/lib' + ;; + esac case "${target}" in diff --git a/ld/emulparams/elf32_e2k.sh b/ld/emulparams/elf32_e2k.sh index 9257beb1e8..e51e6fd047 100644 --- a/ld/emulparams/elf32_e2k.sh +++ b/ld/emulparams/elf32_e2k.sh @@ -11,4 +11,4 @@ OUTPUT_FORMAT="elf32-e2k" LIBPATH_SUFFIX=32 -. ${srcdir}/emulparams/elf_e2k.sh +source_sh ${srcdir}/emulparams/elf_e2k.sh diff --git a/ld/emulparams/elf32_e2k_pm.sh b/ld/emulparams/elf32_e2k_pm.sh new file mode 100644 index 0000000000..0d59f5df9b --- /dev/null +++ b/ld/emulparams/elf32_e2k_pm.sh @@ -0,0 +1,2 @@ +OUTPUT_FORMAT="elf32-e2k-pm" +source_sh ${srcdir}/emulparams/elf_e2k_pm.sh diff --git a/ld/emulparams/elf32_e2k_pm_uclibc.sh b/ld/emulparams/elf32_e2k_pm_uclibc.sh new file mode 100644 index 0000000000..b442f070ce --- /dev/null +++ b/ld/emulparams/elf32_e2k_pm_uclibc.sh @@ -0,0 +1,4 @@ +source_sh ${srcdir}/emulparams/elf32_e2k_pm.sh +E2K_UCLIBC=1 +# Override BFD target name provided by the above script. +OUTPUT_FORMAT="elf32-e2k-pm-uclibc" diff --git a/ld/emulparams/elf32_sparc.sh b/ld/emulparams/elf32_sparc.sh index 0ba6b8d86e..f88b199c41 100644 --- a/ld/emulparams/elf32_sparc.sh +++ b/ld/emulparams/elf32_sparc.sh @@ -11,8 +11,36 @@ ALIGNMENT=8 ARCH=sparc MACHINE= TEMPLATE_NAME=elf +EXTRA_EM_FILE=sparcelf DATA_PLT= GENERATE_SHLIB_SCRIPT=yes GENERATE_PIE_SCRIPT=yes NOP=0x01000000 NO_SMALL_DATA=yes + +# Configurations with `--host=sparc-linux' and `--target=sparc-linux-elf' +# (see Bug #60990 for motivations which make us configure binutils this way) +# should be considered native so that `/usr/local/lib /lib /usr/lib' can find +# their way to SEARCH_DIR (". . .") as it happens when both +# `--{host,target}=sparc-linux'. The absence of the aforementioned paths in +# SEARCH_DIR (". . .") led to Bug #65304. +# Fix this problem in the most primitive way: if the host seems to be Sparc of +# any kind, treat this configuration as native. +case "$host" in + sparc*-*) + NATIVE=yes + ;; +esac + +# Support EIR linkage. This variable is used in `ldelf.c' to emit the code +# which prevents us from customizing `__ehdr_start' when linking EIR. +SUPPORT_EIR=yes + +# On modern Sparc64 Debian sid 32-bit glibc is installed into `{,/usr}/lib32'. +# Ensure that `sparc64-linux-ld' is capable of finding it without the help of +# `-L/lib/../lib32 -L/usr/lib/../lib32' options which are explicitly passed to +# it by GCC on such systems as I'm reluctant to replicate this idiotic +# behaviour. +if [ "x${enable_debian_multiarch}" = "xyes" ]; then + LIBPATH_SUFFIX=32 +fi diff --git a/ld/emulparams/elf64_e2k.sh b/ld/emulparams/elf64_e2k.sh index 9d3792ddea..355e8d2310 100644 --- a/ld/emulparams/elf64_e2k.sh +++ b/ld/emulparams/elf64_e2k.sh @@ -11,4 +11,4 @@ OUTPUT_FORMAT="elf64-e2k" LIBPATH_SUFFIX=64 -. ${srcdir}/emulparams/elf_e2k.sh +source_sh ${srcdir}/emulparams/elf_e2k.sh diff --git a/ld/emulparams/elf64_e2k_kpda.sh b/ld/emulparams/elf64_e2k_kpda.sh index 66ae24f2ef..694453e14d 100644 --- a/ld/emulparams/elf64_e2k_kpda.sh +++ b/ld/emulparams/elf64_e2k_kpda.sh @@ -1,7 +1,7 @@ # Prevent e2k_set_output_arch () in e2kelf.em from referencing 32 and Protected # Mode target vectors which are not supported for KPDA meanwhile. KPDA=1 -. ${srcdir}/emulparams/elf64_e2k.sh +source_sh ${srcdir}/emulparams/elf64_e2k.sh # Ensure that a KPDA-specific BFD target is used. OUTPUT_FORMAT="elf64-e2k-kpda" diff --git a/ld/emulparams/elf64_e2k_pm.sh b/ld/emulparams/elf64_e2k_pm.sh new file mode 100644 index 0000000000..a10f7b87a7 --- /dev/null +++ b/ld/emulparams/elf64_e2k_pm.sh @@ -0,0 +1,2 @@ +OUTPUT_FORMAT="elf64-e2k-pm" +source_sh ${srcdir}/emulparams/elf_e2k_pm.sh diff --git a/ld/emulparams/elf64_e2k_uclibc.sh b/ld/emulparams/elf64_e2k_uclibc.sh new file mode 100644 index 0000000000..a4cfc9bdcd --- /dev/null +++ b/ld/emulparams/elf64_e2k_uclibc.sh @@ -0,0 +1,4 @@ +source_sh ${srcdir}/emulparams/elf64_e2k.sh +E2K_UCLIBC=1 +# Override BFD target name provided by the above script. +OUTPUT_FORMAT="elf64-e2k-uclibc" diff --git a/ld/emulparams/elf64_sparc.sh b/ld/emulparams/elf64_sparc.sh index 8ae29ad78c..4aeb65340d 100644 --- a/ld/emulparams/elf64_sparc.sh +++ b/ld/emulparams/elf64_sparc.sh @@ -1,6 +1,7 @@ SCRIPT_NAME=elf ELFSIZE=64 TEMPLATE_NAME=elf +EXTRA_EM_FILE=sparcelf OUTPUT_FORMAT="elf64-sparc" NO_REL_RELOCS=yes MAXPAGESIZE="CONSTANT (MAXPAGESIZE)" @@ -48,3 +49,7 @@ case "$EMULATION_NAME" in esac ;; esac + +# Support EIR linkage. This variable is used in `ldelf.c' to emit the code +# which prevents us from customizing `__ehdr_start' when linking EIR. +SUPPORT_EIR=yes diff --git a/ld/emulparams/elf_e2k.sh b/ld/emulparams/elf_e2k.sh index da26d716ae..e32e8c8889 100644 --- a/ld/emulparams/elf_e2k.sh +++ b/ld/emulparams/elf_e2k.sh @@ -5,14 +5,14 @@ MAXPAGESIZE="CONSTANT (MAXPAGESIZE)" COMMONPAGESIZE="CONSTANT (COMMONPAGESIZE)" ALIGNMENT=8 ARCH=e2k -TEMPLATE_NAME=elf32 +TEMPLATE_NAME=elf EXTRA_EM_FILE=e2kelf GENERATE_SHLIB_SCRIPT=yes GENERATE_PIE_SCRIPT=yes NO_SMALL_DATA=yes # I'd like '-rpath' option to take effect when performing the link -# (see the implementation of after_open () in elf32.em). +# (see the splitted implementation of after_open () in elf.em and ldelf.c). # Am not I going to break anything . . . ? # . . . as a consequence directories coming from the NATIVE_LIB_DIRS parameter @@ -36,8 +36,8 @@ LDEMUL_PLACE_ORPHAN=${EMULATION_NAME}_place_orphan LDEMUL_AFTER_ALLOCATION=${EMULATION_NAME}_after_allocation; -# Support EIR linkage. This variable is used in `elf32.em' to emit the code -# which prevents us from customizing `__ehdr_start' when linking EIR. +# Support EIR linkage. This variable is used in `elf.em' to enable the code +# in ldelf.c preventing us from customizing `__ehdr_start' when linking EIR. SUPPORT_EIR=yes # Delay checking ELF relocations until opening all input files diff --git a/ld/emulparams/elf_e2k_pm.sh b/ld/emulparams/elf_e2k_pm.sh new file mode 100644 index 0000000000..5ac10b2c94 --- /dev/null +++ b/ld/emulparams/elf_e2k_pm.sh @@ -0,0 +1,31 @@ +# At present I'd prefer to have `OUTPUT_ARCH(e2k:pm)' rather than just +# `OUTPUT_ARCH (e2k)' inside the corresponding LD script (see elf.sc). +MACHINE=pm +ENABLE_BUG_89922=yes + +# Avoid placing read-only data sections into the code segment in E2K +# Protected Mode this way: +SEPARATE_CODE=yes + +# Ensure that `/{,usr/,...}lib128' libraries are inserted at the start +# of SEARCH_DIRs. +LIBPATH_SUFFIX=128 + +source_sh ${srcdir}/emulparams/elf_e2k.sh + +# Unlike ordinary modes I'd prefer a shared library's text segment to start +# from a non-zero address since zero link-time relocation values are currently +# used to distinguish weak undefined symbols when generating `__selfinit ()' in +# my PM BFD backend. +SHLIB_TEXT_START_ADDR=$TEXT_START_ADDR + +# Taking into account that 'SEGMENT_SIZE == MAXPAGESIZE' by default this +# ensures that RO segment has a suitable alignment for placing ELF and Program +# Headers in the very beginning of it. Sufficient space for them is allocated +# in ld/scripttempl/elf.sc by means of SIZEOF_HEADERS. +RODATA_ADDR="ALIGN(${SEGMENT_SIZE})" +SHLIB_RODATA_ADDR=$RODATA_ADDR + +TEXT_START_SYMBOLS=" + PROVIDE_HIDDEN (__selfinit = .); + *(.text.selfinit)" diff --git a/ld/emultempl/e2kelf.em b/ld/emultempl/e2kelf.em index daa20eec78..18833a4868 100644 --- a/ld/emultempl/e2kelf.em +++ b/ld/emultempl/e2kelf.em @@ -19,14 +19,23 @@ # MA 02110-1301, USA. # -# This file is sourced from elf32.em, and defines extra e2k-elf +# This file is sourced from elf.em, and defines extra e2k-elf # specific routines. # # Define some shell vars to insert bits of code into the standard elf # parse_args and list_options functions. # + +# Create packed PM ELFs for glibc by default and never for uclibc. +if test -z "$E2K_UCLIBC"; then + PACK_CG=TRUE +else + PACK_CG=FALSE +fi + fragment <the_bfd, pure_eir_finder, NULL)) return TRUE; - /* Otherwise, the standard implementation from 'elf32.em' will do. */ - return gld${EMULATION_NAME}_load_symbols (entry); + /* Otherwise, the standard implementation from 'elf.em' will do. */ + return ldelf_load_symbols (entry); } static bfd_boolean @@ -306,7 +336,7 @@ e2k_after_open (void) _bfd_e2k_elf_after_open (e2k_ipd, e2k_is_x86app, e2k_is_4mpages, arch_set_via_cmdline, restrict_to_arch, relaxed_e2k_machine_check, output_new_e_machine, - simulate); + simulate, pack_cg); gld${EMULATION_NAME}_after_open (); } @@ -374,7 +404,7 @@ EOF if test -z "$KPDA"; then fragment <section_alignment = 17; + os->section_alignment = exp_intop (1U << 17); } lang_add_section (&os->children, s, NULL, os); @@ -465,7 +495,7 @@ ${LDEMUL_PLACE_ORPHAN} (asection *s, const char *secname, int constraint) return place_dsp_section (s, os_name); } - return gld${EMULATION_NAME}_place_orphan (s, secname, constraint); + return ldelf_place_orphan (s, secname, constraint); } EOF fi @@ -567,3 +597,4 @@ LDEMUL_ALLOW_DYNAMIC_ENTRIES_IN_RELOCATABLE_LINK=\ e2k_allow_dynamic_entries_in_relocatable_link LDEMUL_AFTER_OPEN=e2k_after_open LDEMUL_SET_OUTPUT_ARCH=e2k_set_output_arch +LDEMUL_DISABLE_STANDARD_COMPATIBILITY_TESTS=TRUE diff --git a/ld/emultempl/elf.em b/ld/emultempl/elf.em index 356f34538b..49585e3ee9 100644 --- a/ld/emultempl/elf.em +++ b/ld/emultempl/elf.em @@ -149,7 +149,19 @@ fragment <the_bfd, pure_eir_finder, NULL)) return TRUE; - /* Otherwise, the standard implementation from 'elf32.em' will do. */ - return gld${EMULATION_NAME}_load_symbols (entry); + /* Otherwise, the standard implementation from 'ldelf.c' will do. */ + return ldelf_load_symbols (entry); } static bfd_boolean diff --git a/ld/genscripts.sh b/ld/genscripts.sh index 03392d265c..afd02269b9 100755 --- a/ld/genscripts.sh +++ b/ld/genscripts.sh @@ -123,7 +123,8 @@ EMULATION_LIBPATH=$2 NATIVE_LIB_DIRS=$3 use_sysroot=$4 ENABLE_INITFINI_ARRAY=$5 -shift 5 +enable_debian_multiarch=$6 +shift 6 EMULATION_NAME=$1 TOOL_LIB=$2 @@ -157,10 +158,11 @@ fi case " $EMULATION_LIBPATH " in *" ${EMULATION_NAME} "*) - if [ "x${host}" = "x${target}" ] ; then - NATIVE=yes - USE_LIBPATH=yes - elif [ "x${use_sysroot}" = "xyes" ] ; then +# if [ "x${host}" = "x${target}" ] ; then +# NATIVE=yes +# USE_LIBPATH=yes +# el + if [ "x${use_sysroot}" = "xyes" ] ; then USE_LIBPATH=yes fi ;; @@ -235,6 +237,63 @@ append_to_lib_path() fi } +if [ "x${enable_debian_multiarch}" = "xyes" ]; then +# set the multiarch tuples +multiarch_name= +multiarch_name_32= +multiarch_name_64= + + # In the absence of DEB_TARGET_MULTIARCH* provided by debian build scripts do so + # based on the emulation name; using TOOL_LIB seems to unreliable, when + # configuring with --enable-targets=powerpc-linux-gnu,powerpc64-linux-gnu + # only the first one (?) wins. + # FIXME: should this go into ld/emulparams/*.sh ? + case "$EMULATION_NAME" in + elf32_sparc) + multiarch_name=sparc-linux-gnu + multiarch_name_64=sparc64-linux-gnu + ;; + elf64_sparc) + # The above settings for elf32_sparc have been borrowed from the original + # Debian patch intact. This one is added by me as it's incomprehensibly + # missing from that patch. Don't they want multiarch support for sparc64? + # As for "multiarch_name_64" I don't see any point in it both for "elf{32, + # 64}_sparc". See how these rather obscure settings are used to generate + # library search paths below: "multiarch_name_64" won't have any chance + # to contribute to them for "elf32_sparc" emulation. + multiarch_name=sparc64-linux-gnu + ;; + elf32_e2k) + multiarch_name=e2k32-linux-gnu + ;; + elf64_e2k) + multiarch_name=e2k-linux-gnu + ;; + elf32_e2k_pm | elf64_e2k_pm) + multiarch_name=e2k128-linux-gnu + ;; + esac + +if [ "x${LIB_PATH}" = "x" ] && [ "x${USE_LIBPATH}" = xyes ] ; then + libs=${NATIVE_LIB_DIRS} + if [ "x${NATIVE}" = "xyes" ] ; then + case " ${libs} " in + *" ${libdir} "*) ;; + *) libs="${libdir} ${libs}" ;; + esac + fi + append_to_lib_path ${libs} +fi + +case :${lib_path1}:${lib_path2}: in + *:: | ::*) LIB_PATH=${lib_path1}${lib_path2} ;; + *) LIB_PATH=${lib_path1}:${lib_path2} ;; +esac +lib_path1= +lib_path2= + +fi # enable_debian_multiarch + # Always search $(tooldir)/lib, aka /usr/local/TARGET/lib when native # except when LIBPATH=":". if [ "${LIB_PATH}" != ":" ] ; then @@ -260,6 +319,9 @@ if [ "${LIB_PATH}" != ":" ] ; then append_to_lib_path ${libs} fi +if [ "x${enable_debian_multiarch}" = "xno" ] ; then + +# Note that for multiarch case the following actions have been moved above. if [ "x${LIB_PATH}" = "x" ] && [ "x${USE_LIBPATH}" = xyes ] ; then libs=${NATIVE_LIB_DIRS} if [ "x${NATIVE}" = "xyes" ] ; then @@ -276,8 +338,99 @@ case :${lib_path1}:${lib_path2}: in *) LIB_PATH=${lib_path1}:${lib_path2} ;; esac +else # enable_debian_multiarch = yes +case :${lib_path1}:${lib_path2}: in + *:: | ::*) LIB_PATH=${LIB_PATH}:${lib_path1}${lib_path2} ;; + *) LIB_PATH=${LIB_PATH}:${lib_path1}:${lib_path2} ;; +esac + +# We use the $tool_lib variable in our multiarch mangling: +if [ "x${TOOL_LIB}" = "x" ] ; then + tool_lib=${exec_prefix}/${target_alias}/lib +else + tool_lib=${exec_prefix}/${TOOL_LIB}/lib +fi + +# FIXME: why again? These already should be in LIBPATH +if [ "x${APPEND_TOOLLIBDIR}" = "xyes" ] ; then + LIB_PATH=${LIB_PATH}:${tool_lib} + # For multilib targets, search both $tool_lib dirs + if [ "x${LIBPATH_SUFFIX}" != "x" ] ; then + LIB_PATH=${LIB_PATH}:${tool_lib}${LIBPATH_SUFFIX} + fi +fi + +fi # enable_debian_multiarch = yes + LIB_SEARCH_DIRS=`echo ${LIB_PATH} | sed -e 's/:/ /g' -e 's/\([^ ][^ ]*\)/SEARCH_DIR(\\"\1\\");/g'` +# The underlying trickery is purely multiarch-specific. +if [ "x${enable_debian_multiarch}" = "xyes" ] ; then +if [ -n "$multiarch_name" ]; then + temp_dirs=' ' + ma_dirs=' ' + for dir in `echo ${LIB_PATH} | sed -e 's/:/ /g'`; do + case "$dir" in + *${tool_lib}*|*/${target_alias}/*) + ;; + */lib) + if [ -n "$multiarch_name_32" ]; then + case $EMULATION_NAME in + elf_i386|elf32*) + ma_dirs="${ma_dirs}${dir}/$multiarch_name_32 ";; + *) + ma_dirs="${ma_dirs}${dir}/$multiarch_name " + esac + elif [ -n "$multiarch_name_64" ]; then + case $EMULATION_NAME in + elf*_64|elf64*) + ma_dirs="${ma_dirs}${dir}/$multiarch_name_64 ";; + *) + ma_dirs="${ma_dirs}${dir}/$multiarch_name " + esac + else + ma_dirs="${ma_dirs}${dir}/$multiarch_name " + fi + ;; + */lib32) + if [ -n "$multiarch_name_32" ]; then + dir2=$(echo $dir | sed "s,32$,,") + ma_dirs="${ma_dirs}${dir2}/$multiarch_name_32 " + fi + ;; + */lib64) + case "${target}" in + aarch64*-*-*|powerpc64-*-*|s390x-*-*|sparc64-*-*|x86_64-*-linux-gnu|mips64-*-gnuabi64) + #dir=$(echo $dir | sed "s,64$,,") + dir2=$(echo $dir | sed "s,64$,,") + ma_dirs="${ma_dirs}${dir2}/$multiarch_name " + ;; + *) + if [ -n "$multiarch_name_64" ]; then + dir2=$(echo $dir | sed "s,64$,,") + ma_dirs="${ma_dirs}${dir2}/$multiarch_name_64 " + fi + ;; + esac + ;; + *) + ;; + esac + temp_dirs="${temp_dirs}${dir} " + done + LIB_SEARCH_DIRS= + for dir in $ma_dirs $temp_dirs; do + if echo "$LIB_SEARCH_DIRS" | fgrep -q "\"$dir\""; then + continue + fi + LIB_SEARCH_DIRS="${LIB_SEARCH_DIRS}SEARCH_DIR(\"$dir\"); " + done +fi + +# What's this idiotism needed for ? ? ? +echo X3: $LIB_PATH +fi # enable_debian_multiarch = yes + # We need it for testsuite. set $EMULATION_LIBPATH if [ "x$1" = "x$EMULATION_NAME" ]; then diff --git a/ld/ldelf.c b/ld/ldelf.c index bada3ade2d..09a2473832 100644 --- a/ld/ldelf.c +++ b/ld/ldelf.c @@ -915,10 +915,17 @@ ldelf_check_ld_so_conf (const struct bfd_link_needed_list *l, int force, (const char *) NULL); if (!ldelf_parse_ld_so_conf (&info, tmppath)) { + /* FIXME: the original stupid logic makes the host's /etc/ld.so.conf + be parsed even when cross LD is used! I need the means to prevent + this for the sake of my isolated native e2k-linux-gcc based + distribution. This is achieved via --with-cross-host configure + option for now. */ +#ifndef WITH_CROSS_HOST free (tmppath); tmppath = concat (ld_sysroot, "/etc/ld.so.conf", (const char *) NULL); ldelf_parse_ld_so_conf (&info, tmppath); +#endif /* WITH_CROSS_HOST */ } free (tmppath); @@ -1543,7 +1550,8 @@ ldelf_append_to_separated_string (char **to, char *op_arg) void ldelf_before_allocation (char *audit, char *depaudit, - const char *default_interpreter_name) + const char *default_interpreter_name, + int link_mixed_eir) { const char *rpath; asection *sinterp; @@ -1556,7 +1564,8 @@ ldelf_before_allocation (char *audit, char *depaudit, if (is_elf_hash_table (link_info.hash)) { _bfd_elf_tls_setup (link_info.output_bfd, &link_info); - + if (link_mixed_eir == 0) + { /* Make __ehdr_start hidden if it has been referenced, to prevent the symbol from being dynamic. */ if (!bfd_link_relocatable (&link_info)) @@ -1599,6 +1608,7 @@ ldelf_before_allocation (char *audit, char *depaudit, referred to by dynamic objects. */ lang_for_each_statement (ldelf_find_statement_assignment); } + } /* Let the ELF backend work out the sizes of any sections required by dynamic linking. */ diff --git a/ld/ldelf.h b/ld/ldelf.h index 2a58a0c135..ba8cecaa9c 100644 --- a/ld/ldelf.h +++ b/ld/ldelf.h @@ -25,7 +25,7 @@ extern bfd_boolean ldelf_load_symbols (lang_input_statement_type *); extern void ldelf_after_open (int, int, int, int, int, const char *); extern bfd_boolean ldelf_setup_build_id (bfd *); extern void ldelf_append_to_separated_string (char **, char *); -extern void ldelf_before_allocation (char *, char *, const char *); +extern void ldelf_before_allocation (char *, char *, const char *, int); extern bfd_boolean ldelf_open_dynamic_archive (const char *, search_dirs_type *, lang_input_statement_type *); extern lang_output_section_statement_type *ldelf_place_orphan diff --git a/ld/ldemul.c b/ld/ldemul.c index 00a6a5ad13..0893c99e4a 100644 --- a/ld/ldemul.c +++ b/ld/ldemul.c @@ -436,3 +436,18 @@ ldemul_print_symbol (struct bfd_link_hash_entry *hash_entry, void *ptr) return ld_emulation->print_symbol (hash_entry, ptr); return print_one_symbol (hash_entry, ptr); } + +bfd_boolean +ldemul_allow_dynamic_entries_in_relocatable_link (void) +{ + if (ld_emulation->allow_dynamic_entries_in_relocatable_link) + return ld_emulation->allow_dynamic_entries_in_relocatable_link (); + + return FALSE; +} + +bfd_boolean +ldemul_disable_standard_compatibility_tests (void) +{ + return ld_emulation->disable_standard_compatibility_tests; +} diff --git a/ld/ldemul.h b/ld/ldemul.h index ca165ac957..3f5051ca5d 100644 --- a/ld/ldemul.h +++ b/ld/ldemul.h @@ -115,6 +115,11 @@ extern void ldemul_examine_strtab_for_ctf extern bfd_boolean ldemul_print_symbol (struct bfd_link_hash_entry *hash_entry, void *ptr); +extern bfd_boolean ldemul_allow_dynamic_entries_in_relocatable_link + (void); +extern bfd_boolean ldemul_disable_standard_compatibility_tests + (void); + typedef struct ld_emulation_xfer_struct { /* Run before parsing the command line and script file. Set the architecture, maybe other things. */ @@ -244,6 +249,20 @@ typedef struct ld_emulation_xfer_struct { bfd_boolean (*print_symbol) (struct bfd_link_hash_entry *hash_entry, void *ptr); + bfd_boolean (*allow_dynamic_entries_in_relocatable_link) + (void); + + /* For E2K we have got our own compatibility tests in "merge_private_bfd_data + ()" handler capable of recognizing EF_E2K_INCOMPAT in addition to `bfd_arch + _info'. Therefore, inhibit the standard compatibility tests in e2k-linux-ld + making use of `abfd->arch_info->compatible (bfd_arch_info_1, bfd_arch_info + _2)' that may result in a false success. On the other hand, if they + resulted in a true failure, their error messages would be output instead + of e2k-specific ones which would look rather inconsistent. TODO: if + EF_E2K_INCOMPAT was encoded in `bfd_arch_info.mach' the standard + compatibility tests could be revived presumably along with the removal of + the analogous ones from E2K-specific "merge_private_bfd_data ()". */ + bfd_boolean disable_standard_compatibility_tests; } ld_emulation_xfer_type; typedef enum { diff --git a/ld/ldfile.c b/ld/ldfile.c index 09be32b13f..f9b937a5c3 100644 --- a/ld/ldfile.c +++ b/ld/ldfile.c @@ -284,9 +284,16 @@ ldfile_try_open_bfd (const char *attempt, return FALSE; } + /* FIXME: the check for compatibility may be unduly skipped here for + E2K, however we have implicitly skipped it for years because of a + deficient `bfd_e2k_compatible ()' implementation. Now that the + latter is being fixed for the sake of GDB ensure that the old + behaviour is preserved for safety until `bfd_e2k_compatible ()' + becomes capable of recognizing EF_E2K_INCOMPAT at least. */ if (entry->flags.search_dirs - && !bfd_arch_get_compatible (check, link_info.output_bfd, - command_line.accept_unknown_input_arch) + && !(ldemul_disable_standard_compatibility_tests () + || bfd_arch_get_compatible (check, link_info.output_bfd, + command_line.accept_unknown_input_arch)) /* XCOFF archives can have 32 and 64 bit objects. */ && !(bfd_get_flavour (check) == bfd_target_xcoff_flavour && (bfd_get_flavour (link_info.output_bfd) diff --git a/ld/ldlang.c b/ld/ldlang.c index 9977195074..1581d9cee2 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -6952,7 +6952,11 @@ lang_check (void) relocs for other link purposes than a final link). */ if ((bfd_link_relocatable (&link_info) || link_info.emitrelocations) - && (compatible == NULL + && (/* For E2K we may have more appropriate compatibility tests in + "merge_private_bfd_data ()" along with more meaningful error + messages. */ + (! ldemul_disable_standard_compatibility_tests () + && compatible == NULL) || (bfd_get_flavour (input_bfd) != bfd_get_flavour (link_info.output_bfd))) && (bfd_get_file_flags (input_bfd) & HAS_RELOC) != 0) @@ -6964,7 +6968,11 @@ lang_check (void) /* einfo with %F exits. */ } - if (compatible == NULL) + /* For E2K we have got more appropriate compatibility tests in + "merge_private_bfd_data ()" along with more meaningful error + messages. */ + if (! ldemul_disable_standard_compatibility_tests () + && compatible == NULL) { if (command_line.warn_mismatch) einfo (_("%X%P: %s architecture of input file `%pB'" diff --git a/ld/ldmain.c b/ld/ldmain.c index 08be9030cb..f7981cf329 100644 --- a/ld/ldmain.c +++ b/ld/ldmain.c @@ -253,6 +253,14 @@ main (int argc, char **argv) bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); +#if 0 + /* FIXME: without this hack bfd.mo will be searched in `/usr/share/locale/.../ + LC_MESSAGES/' ignoring the prefix at which it's actually installed! The + same probably applies to other ld dependencies: libiberty, libopcodes, + . . . What a drawback in localization it is! */ + bindtextdomain ("bfd", LOCALEDIR); +#endif /* 0 */ + program_name = argv[0]; xmalloc_set_program_name (program_name); diff --git a/ld/lexsup.c b/ld/lexsup.c index 6cab41cf5d..e3263d5260 100644 --- a/ld/lexsup.c +++ b/ld/lexsup.c @@ -1758,7 +1758,17 @@ parse_args (unsigned argc, char **argv) /* Fall through. */ case dynamic_list: link_info.dynamic = TRUE; - opt_symbolic = symbolic_unset; + /* The unconditional reset of OPT_SYMBOLIC here that appeared as a result + of PR ld/26018 makes --dynamic-list* override both `-Bsymbolic{, + -functions}'. Whereas it probably makes sense to override the former + (prior to the fix it was -Bsymbolic that overrode --dynamic-list*), + -Bsymbolic-functions could still be successfully combined with + --dynamic-list* as it used to be. The failure to support such a + combination implying that .so-library should be bound to NONE of its + non-function symbols and the ones in the list resulted in + Bug #126194. */ + if (opt_symbolic == symbolic) + opt_symbolic = symbolic_unset; break; } diff --git a/libiberty/obstack.c b/libiberty/obstack.c index f8684d48f4..0a4e57ee4c 100644 --- a/libiberty/obstack.c +++ b/libiberty/obstack.c @@ -61,10 +61,7 @@ template struct alignof_helper { char __slot1; type __slot2; }; # endif # endif # include - -#ifdef __linux__ # include -#endif /* __linux__ */ # ifndef MAX # define MAX(a,b) ((a) > (b) ? (a) : (b)) diff --git a/missing b/missing index 5c83d52a93..f62bbae306 100755 --- a/missing +++ b/missing @@ -1,11 +1,10 @@ #! /bin/sh -# Common stub for a few missing GNU programs while installing. +# Common wrapper for a few potentially missing GNU programs. -scriptversion=2009-04-28.21; # UTC +scriptversion=2013-10-28.13; # UTC -# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006, -# 2008, 2009 Free Software Foundation, Inc. -# Originally by Fran,cois Pinard , 1996. +# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# Originally written by Fran,cois Pinard , 1996. # 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 @@ -26,69 +25,40 @@ scriptversion=2009-04-28.21; # UTC # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then - echo 1>&2 "Try \`$0 --help' for more information" + echo 1>&2 "Try '$0 --help' for more information" exit 1 fi -run=: -sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p' -sed_minuso='s/.* -o \([^ ]*\).*/\1/p' - -# In the cases where this matters, `missing' is being run in the -# srcdir already. -if test -f configure.ac; then - configure_ac=configure.ac -else - configure_ac=configure.in -fi - -msg="missing on your system" - case $1 in ---run) - # Try to run requested program, and just exit if it succeeds. - run= - shift - "$@" && exit 0 - # Exit code 63 means version mismatch. This often happens - # when the user try to use an ancient version of a tool on - # a file that requires a minimum version. In this case we - # we should proceed has if the program had been absent, or - # if --run hadn't been passed. - if test $? = 63; then - run=: - msg="probably too old" - fi - ;; + + --is-lightweight) + # Used by our autoconf macros to check whether the available missing + # script is modern enough. + exit 0 + ;; + + --run) + # Back-compat with the calling convention used by older automake. + shift + ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... -Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an -error status if there is no known handling for PROGRAM. +Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due +to PROGRAM being missing or too old. Options: -h, --help display this help and exit -v, --version output version information and exit - --run try to run the given command, and emulate it if it fails Supported PROGRAM values: - aclocal touch file \`aclocal.m4' - autoconf touch file \`configure' - autoheader touch file \`config.h.in' - autom4te touch the output file, or create a stub one - automake touch all \`Makefile.in' files - bison create \`y.tab.[ch]', if possible, from existing .[ch] - flex create \`lex.yy.c', if possible, from existing .c - help2man touch the output file - lex create \`lex.yy.c', if possible, from existing .c - makeinfo touch the output file - tar try tar, gnutar, gtar, then tar without non-portable flags - yacc create \`y.tab.[ch]', if possible, from existing .[ch] + aclocal autoconf autoheader autom4te automake makeinfo + bison yacc flex lex help2man -Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and -\`g' are ignored when checking the name. +Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and +'g' are ignored when checking the name. Send bug reports to ." exit $? @@ -100,278 +70,141 @@ Send bug reports to ." ;; -*) - echo 1>&2 "$0: Unknown \`$1' option" - echo 1>&2 "Try \`$0 --help' for more information" + echo 1>&2 "$0: unknown '$1' option" + echo 1>&2 "Try '$0 --help' for more information" exit 1 ;; esac -# normalize program name to check for. -program=`echo "$1" | sed ' - s/^gnu-//; t - s/^gnu//; t - s/^g//; t'` +# Run the given program, remember its exit status. +"$@"; st=$? -# Now exit if we have it, but it failed. Also exit now if we -# don't have it and --version was passed (most likely to detect -# the program). This is about non-GNU programs, so use $1 not -# $program. -case $1 in - lex*|yacc*) - # Not GNU programs, they don't have --version. +# If it succeeded, we are done. +test $st -eq 0 && exit 0 + +# Also exit now if we it failed (or wasn't found), and '--version' was +# passed; such an option is passed most likely to detect whether the +# program is present and works. +case $2 in --version|--help) exit $st;; esac + +# Exit code 63 means version mismatch. This often happens when the user +# tries to use an ancient version of a tool on a file that requires a +# minimum version. +if test $st -eq 63; then + msg="probably too old" +elif test $st -eq 127; then + # Program was missing. + msg="missing on your system" +else + # Program was found and executed, but failed. Give up. + exit $st +fi + +perl_URL=http://www.perl.org/ +flex_URL=http://flex.sourceforge.net/ +gnu_software_URL=http://www.gnu.org/software + +program_details () +{ + case $1 in + aclocal|automake) + echo "The '$1' program is part of the GNU Automake package:" + echo "<$gnu_software_URL/automake>" + echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/autoconf>" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + autoconf|autom4te|autoheader) + echo "The '$1' program is part of the GNU Autoconf package:" + echo "<$gnu_software_URL/autoconf/>" + echo "It also requires GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + esac +} + +give_advice () +{ + # Normalize program name to check for. + normalized_program=`echo "$1" | sed ' + s/^gnu-//; t + s/^gnu//; t + s/^g//; t'` + + printf '%s\n' "'$1' is $msg." + + configure_deps="'configure.ac' or m4 files included by 'configure.ac'" + case $normalized_program in + autoconf*) + echo "You should only need it if you modified 'configure.ac'," + echo "or m4 files included by it." + program_details 'autoconf' + ;; + autoheader*) + echo "You should only need it if you modified 'acconfig.h' or" + echo "$configure_deps." + program_details 'autoheader' + ;; + automake*) + echo "You should only need it if you modified 'Makefile.am' or" + echo "$configure_deps." + program_details 'automake' + ;; + aclocal*) + echo "You should only need it if you modified 'acinclude.m4' or" + echo "$configure_deps." + program_details 'aclocal' + ;; + autom4te*) + echo "You might have modified some maintainer files that require" + echo "the 'autom4te' program to be rebuilt." + program_details 'autom4te' + ;; + bison*|yacc*) + echo "You should only need it if you modified a '.y' file." + echo "You may want to install the GNU Bison package:" + echo "<$gnu_software_URL/bison/>" + ;; + lex*|flex*) + echo "You should only need it if you modified a '.l' file." + echo "You may want to install the Fast Lexical Analyzer package:" + echo "<$flex_URL>" + ;; + help2man*) + echo "You should only need it if you modified a dependency" \ + "of a man page." + echo "You may want to install the GNU Help2man package:" + echo "<$gnu_software_URL/help2man/>" ;; + makeinfo*) + echo "You should only need it if you modified a '.texi' file, or" + echo "any other file indirectly affecting the aspect of the manual." + echo "You might want to install the Texinfo package:" + echo "<$gnu_software_URL/texinfo/>" + echo "The spurious makeinfo call might also be the consequence of" + echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" + echo "want to install GNU make:" + echo "<$gnu_software_URL/make/>" + ;; + *) + echo "You might have modified some files without having the proper" + echo "tools for further handling them. Check the 'README' file, it" + echo "often tells you about the needed prerequisites for installing" + echo "this package. You may also peek at any GNU archive site, in" + echo "case some other package contains this missing '$1' program." + ;; + esac +} - tar*) - if test -n "$run"; then - echo 1>&2 "ERROR: \`tar' requires --run" - exit 1 - elif test "x$2" = "x--version" || test "x$2" = "x--help"; then - exit 1 - fi - ;; +give_advice "$1" | sed -e '1s/^/WARNING: /' \ + -e '2,$s/^/ /' >&2 - *) - if test -z "$run" && ($1 --version) > /dev/null 2>&1; then - # We have it, but it failed. - exit 1 - elif test "x$2" = "x--version" || test "x$2" = "x--help"; then - # Could not run --version or --help. This is probably someone - # running `$TOOL --version' or `$TOOL --help' to check whether - # $TOOL exists and not knowing $TOOL uses missing. - exit 1 - fi - ;; -esac - -# If it does not exist, or fails to run (possibly an outdated version), -# try to emulate it. -case $program in - aclocal*) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified \`acinclude.m4' or \`${configure_ac}'. You might want - to install the \`Automake' and \`Perl' packages. Grab them from - any GNU archive site." - touch aclocal.m4 - ;; - - autoconf*) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified \`${configure_ac}'. You might want to install the - \`Autoconf' and \`GNU m4' packages. Grab them from any GNU - archive site." - touch configure - ;; - - autoheader*) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified \`acconfig.h' or \`${configure_ac}'. You might want - to install the \`Autoconf' and \`GNU m4' packages. Grab them - from any GNU archive site." - files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` - test -z "$files" && files="config.h" - touch_files= - for f in $files; do - case $f in - *:*) touch_files="$touch_files "`echo "$f" | - sed -e 's/^[^:]*://' -e 's/:.*//'`;; - *) touch_files="$touch_files $f.in";; - esac - done - touch $touch_files - ;; - - automake*) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. - You might want to install the \`Automake' and \`Perl' packages. - Grab them from any GNU archive site." - find . -type f -name Makefile.am -print | - sed 's/\.am$/.in/' | - while read f; do touch "$f"; done - ;; - - autom4te*) - echo 1>&2 "\ -WARNING: \`$1' is needed, but is $msg. - You might have modified some files without having the - proper tools for further handling them. - You can get \`$1' as part of \`Autoconf' from any GNU - archive site." - - file=`echo "$*" | sed -n "$sed_output"` - test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` - if test -f "$file"; then - touch $file - else - test -z "$file" || exec >$file - echo "#! /bin/sh" - echo "# Created by GNU Automake missing as a replacement of" - echo "# $ $@" - echo "exit 0" - chmod +x $file - exit 1 - fi - ;; - - bison*|yacc*) - echo 1>&2 "\ -WARNING: \`$1' $msg. You should only need it if - you modified a \`.y' file. You may need the \`Bison' package - in order for those modifications to take effect. You can get - \`Bison' from any GNU archive site." - rm -f y.tab.c y.tab.h - if test $# -ne 1; then - eval LASTARG="\${$#}" - case $LASTARG in - *.y) - SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` - if test -f "$SRCFILE"; then - cp "$SRCFILE" y.tab.c - fi - SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` - if test -f "$SRCFILE"; then - cp "$SRCFILE" y.tab.h - fi - ;; - esac - fi - if test ! -f y.tab.h; then - echo >y.tab.h - fi - if test ! -f y.tab.c; then - echo 'main() { return 0; }' >y.tab.c - fi - ;; - - lex*|flex*) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified a \`.l' file. You may need the \`Flex' package - in order for those modifications to take effect. You can get - \`Flex' from any GNU archive site." - rm -f lex.yy.c - if test $# -ne 1; then - eval LASTARG="\${$#}" - case $LASTARG in - *.l) - SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` - if test -f "$SRCFILE"; then - cp "$SRCFILE" lex.yy.c - fi - ;; - esac - fi - if test ! -f lex.yy.c; then - echo 'main() { return 0; }' >lex.yy.c - fi - ;; - - help2man*) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified a dependency of a manual page. You may need the - \`Help2man' package in order for those modifications to take - effect. You can get \`Help2man' from any GNU archive site." - - file=`echo "$*" | sed -n "$sed_output"` - test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` - if test -f "$file"; then - touch $file - else - test -z "$file" || exec >$file - echo ".ab help2man is required to generate this page" - exit $? - fi - ;; - - makeinfo*) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified a \`.texi' or \`.texinfo' file, or any other file - indirectly affecting the aspect of the manual. The spurious - call might also be the consequence of using a buggy \`make' (AIX, - DU, IRIX). You might want to install the \`Texinfo' package or - the \`GNU make' package. Grab either from any GNU archive site." - # The file to touch is that specified with -o ... - file=`echo "$*" | sed -n "$sed_output"` - test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` - if test -z "$file"; then - # ... or it is the one specified with @setfilename ... - infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` - file=`sed -n ' - /^@setfilename/{ - s/.* \([^ ]*\) *$/\1/ - p - q - }' $infile` - # ... or it is derived from the source name (dir/f.texi becomes f.info) - test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info - fi - # If the file does not exist, the user really needs makeinfo; - # let's fail without touching anything. - - # Personally I disagree with the preceding statement. The failure to build - # `.info' files shouldn't prevent us from building everything else. This is - # especially true for Solaris where we have an ancient makeinfo. Moreover, - # I cannot understand the logic of this check. Where are we going to take - # a ready-made output `.info' file from in a build tree? - # test -f $file || exit 1 - touch $file - ;; - - tar*) - shift - - # We have already tried tar in the generic part. - # Look for gnutar/gtar before invocation to avoid ugly error - # messages. - if (gnutar --version > /dev/null 2>&1); then - gnutar "$@" && exit 0 - fi - if (gtar --version > /dev/null 2>&1); then - gtar "$@" && exit 0 - fi - firstarg="$1" - if shift; then - case $firstarg in - *o*) - firstarg=`echo "$firstarg" | sed s/o//` - tar "$firstarg" "$@" && exit 0 - ;; - esac - case $firstarg in - *h*) - firstarg=`echo "$firstarg" | sed s/h//` - tar "$firstarg" "$@" && exit 0 - ;; - esac - fi - - echo 1>&2 "\ -WARNING: I can't seem to be able to run \`tar' with the given arguments. - You may want to install GNU tar or Free paxutils, or check the - command line arguments." - exit 1 - ;; - - *) - echo 1>&2 "\ -WARNING: \`$1' is needed, and is $msg. - You might have modified some files without having the - proper tools for further handling them. Check the \`README' file, - it often tells you about the needed prerequisites for installing - this package. You may also peek at any GNU archive site, in case - some other package would contain this missing \`$1' program." - exit 1 - ;; -esac - -exit 0 +# Propagate the correct exit status (expected to be 127 for a program +# not found, 63 for a program that failed due to version mismatch). +exit $st # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) diff --git a/opcodes/Makefile.am b/opcodes/Makefile.am index 7318bf04a8..76bc9f968a 100644 --- a/opcodes/Makefile.am +++ b/opcodes/Makefile.am @@ -62,6 +62,7 @@ HFILES = \ bpf-desc.h bpf-opc.h \ epiphany-desc.h epiphany-opc.h \ fr30-desc.h fr30-opc.h \ + e2k-opc.h \ frv-desc.h frv-opc.h \ i386-init.h \ i386-opc.h \ @@ -123,6 +124,8 @@ TARGET_LIBOPCODES_CFILES = \ bpf-dis.c \ bpf-ibld.c \ bpf-opc.c \ + e2k-dis.c \ + e2k-opc.c \ epiphany-asm.c \ epiphany-desc.c \ epiphany-dis.c \ diff --git a/opcodes/Makefile.in b/opcodes/Makefile.in index ddb93464bc..78d32cbfa5 100644 --- a/opcodes/Makefile.in +++ b/opcodes/Makefile.in @@ -451,6 +451,7 @@ HFILES = \ bpf-desc.h bpf-opc.h \ epiphany-desc.h epiphany-opc.h \ fr30-desc.h fr30-opc.h \ + e2k-opc.h \ frv-desc.h frv-opc.h \ i386-init.h \ i386-opc.h \ @@ -513,6 +514,8 @@ TARGET_LIBOPCODES_CFILES = \ bpf-dis.c \ bpf-ibld.c \ bpf-opc.c \ + e2k-dis.c \ + e2k-opc.c \ epiphany-asm.c \ epiphany-desc.c \ epiphany-dis.c \ @@ -927,6 +930,8 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dis-init.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/disassemble.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dlx-dis.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/e2k-dis.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/e2k-opc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/epiphany-asm.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/epiphany-desc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/epiphany-dis.Plo@am__quote@ diff --git a/opcodes/configure b/opcodes/configure index 8d1e561c94..f898e38184 100755 --- a/opcodes/configure +++ b/opcodes/configure @@ -800,6 +800,8 @@ enable_fast_install with_gnu_ld enable_libtool_lock enable_targets +enable_e2k_opcodes +enable_e2k_encodings enable_werror enable_build_warnings enable_maintainer_mode @@ -1447,6 +1449,8 @@ Optional Features: optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) --enable-targets alternative target configurations + --enable-e2k-opcodes enable opcodes for E2K + --enable-e2k-encodings enable raw instruction encodings in disassembly for E2K --enable-werror treat compile warnings as errors --enable-build-warnings enable build-time compiler warnings --enable-maintainer-mode @@ -11439,7 +11443,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11442 "configure" +#line 11446 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -11545,7 +11549,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11548 "configure" +#line 11552 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -11794,6 +11798,37 @@ esac fi +# Check whether --enable-e2k-opcodes was given. +if test "${enable_e2k_opcodes+set}" = set; then : + enableval=$enable_e2k_opcodes; case "${enableval}" in + yes | no) enable_e2k_opcodes=$enableval ;; + *) as_fn_error $? "enable-e2k-opcodes option must specify either 'yes' or 'no'" "$LINENO" 5 + ;; +esac +else + enable_e2k_opcodes=yes +fi + + +# Check whether --enable-e2k-encodings was given. +if test "${enable_e2k_encodings+set}" = set; then : + enableval=$enable_e2k_encodings; case "${enableval}" in + yes | no) enable_e2k_encodings=$enableval ;; + *) as_fn_error $? "enable-e2k-encodings option must specify either 'yes' or 'no'" "$LINENO" 5 + ;; +esac +else + enable_e2k_encodings=no +fi + +if test $enable_e2k_encodings = yes ; then + +$as_echo "#define ENABLE_E2K_ENCODINGS 1" >>confdefs.h + +fi + + + # Set the 'development' global. . $srcdir/../bfd/development.sh @@ -12877,6 +12912,13 @@ if test x${all_targets} = xfalse ; then bfd_d10v_arch) ta="$ta d10v-dis.lo d10v-opc.lo" ;; bfd_d30v_arch) ta="$ta d30v-dis.lo d30v-opc.lo" ;; bfd_dlx_arch) ta="$ta dlx-dis.lo" ;; + bfd_e2k_arch) + if test $enable_e2k_opcodes = yes ; then + ta="$ta e2k-dis.lo e2k-opc.lo" + else + archdefs="$archdefs -UARCH_$ad" + fi + ;; bfd_fr30_arch) ta="$ta fr30-asm.lo fr30-desc.lo fr30-dis.lo fr30-ibld.lo fr30-opc.lo" using_cgen=yes ;; bfd_frv_arch) ta="$ta frv-asm.lo frv-desc.lo frv-dis.lo frv-ibld.lo frv-opc.lo" using_cgen=yes ;; bfd_ft32_arch) ta="$ta ft32-opc.lo ft32-dis.lo" ;; diff --git a/opcodes/disassemble.c b/opcodes/disassemble.c index 299c23db13..1c573ae1f2 100644 --- a/opcodes/disassemble.c +++ b/opcodes/disassemble.c @@ -38,6 +38,7 @@ #define ARCH_d30v #define ARCH_dlx #define ARCH_bpf +#define ARCH_e2k #define ARCH_epiphany #define ARCH_fr30 #define ARCH_frv @@ -205,6 +206,11 @@ disassembler (enum bfd_architecture a, disassemble = print_insn_dlx; break; #endif +#ifdef ARCH_e2k + case bfd_arch_e2k: + disassemble = print_insn_e2k; + break; +#endif #ifdef ARCH_h8300 case bfd_arch_h8300: if (mach == bfd_mach_h8300h || mach == bfd_mach_h8300hn) diff --git a/opcodes/disassemble.h b/opcodes/disassemble.h index 89db886405..0f918432fc 100644 --- a/opcodes/disassemble.h +++ b/opcodes/disassemble.h @@ -37,6 +37,8 @@ extern int print_insn_d10v (bfd_vma, disassemble_info *); extern int print_insn_d30v (bfd_vma, disassemble_info *); extern int print_insn_dlx (bfd_vma, disassemble_info *); extern int print_insn_bpf (bfd_vma, disassemble_info *); +extern int print_insn_e2k (bfd_vma, disassemble_info *); +extern int print_insn_dsp (bfd_vma, disassemble_info *); extern int print_insn_epiphany (bfd_vma, disassemble_info *); extern int print_insn_fr30 (bfd_vma, disassemble_info *); extern int print_insn_frv (bfd_vma, disassemble_info *); diff --git a/opcodes/e2k-dis.c b/opcodes/e2k-dis.c index 6bed4d4c9c..4cdde04d57 100644 --- a/opcodes/e2k-dis.c +++ b/opcodes/e2k-dis.c @@ -624,10 +624,58 @@ print_predicates (disassemble_info *info, question sign, for MRGC - a comma. */ int first_separator = 0; const struct unpacked_instr *instr = &unpacked_instr; + /* Bit numbers in `{MASK,NEG}[]'. */ + int mask_bit, neg_bit; /* Required RLP for this ALC. */ - unsigned short req_rlp = chn <= 2 ? 0 : 1; + unsigned short req_rlp; /* Required MRGC for this ALC in case ALF proves to be `merge{s,d}'. */ - unsigned short req_mrgc = chn <= 2 ? 2 : 3; + unsigned short req_mrgc; + + /* Get MASK[] and NEG[] bit numbers along with RLPx and MRGCy. When doing so + note that `CHN < 6' matches the respective ALC, whereas `CHN == {6,7}' + AM{2,5}. */ + if (chn <= 2 || chn == 6) + { + if (chn == 6) + { + mask_bit = 3; + neg_bit = 2; + } + else + mask_bit = neg_bit = chn; + + if (! mrgc) + req_rlp = 0; + } + else if ((chn >= 3 && chn <= 5) || chn == 7) + { + /* Note that chn >= 3 here. */ + if (chn <= 5) + mask_bit = neg_bit = chn - 3; + else /* chn == 7 */ + { + mask_bit = 3; + neg_bit = 2; + } + + if (! mrgc) + req_rlp = 1; + } + else + assert (0); + + if (mrgc) + { + if (chn <= 2) + req_mrgc = 2; + else if (chn <= 5) + req_mrgc = 3; + else + /* No MRGC should ever act on anything than ALCx. FIXME: `RPC == MRGC0' + acting on {S,L,C}RP is to be considered yet. */ + assert (0); + } + for (i = 0; i < 3; i++) { @@ -645,7 +693,7 @@ print_predicates (disassemble_info *info, /* Is this RLP suitable for CHN and is CHN present in its mask? */ if (((! mrgc && opc == req_rlp) || (mrgc && opc == req_mrgc)) - && (mask & (1 << (chn - 3 * req_rlp)))) + && (mask & (1 << mask_bit))) { unsigned short neg = (cds[j] & 0x0380) >> 7; unsigned short pred = cds[j] & 0x7f; @@ -662,7 +710,7 @@ print_predicates (disassemble_info *info, the same ALC are inappropriate in fact . . . */ my_printf (mrgc ? " " : ", "); - if (neg & (1 << (chn - 3 * req_rlp))) + if (neg & (1 << neg_bit)) my_printf ("~"); if ((pred & 0x60) == 0x40) @@ -676,6 +724,8 @@ print_predicates (disassemble_info *info, } } +static void print_ctcond (disassemble_info *info, unsigned int ctcond); + static void print_alf (disassemble_info *info, int chn) { @@ -775,12 +825,17 @@ print_alf (disassemble_info *info, int chn) continue; } - else if (templ->alopf == ALOPF12) + else if (templ->alopf == ALOPF12 + || templ->alopf == ALOPF12_IBRANCHD + || templ->alopf == ALOPF12_ICALLD) { const e2k_alopf12_opcode_templ *alopf12; alopf12 = (const e2k_alopf12_opcode_templ *) templ; - if ((instr->als[chn] & 0x00ff0000) != (unsigned) (alopf12->opce << 16) + if ((templ->alopf != ALOPF12_ICALLD + /* For ICALLD ALS.opce encodes WBS, therefore it shouldn't + be verified this way. */ + && (instr->als[chn] & 0x00ff0000) != (unsigned) (alopf12->opce << 16)) || instr->ales[chn] != ((alopf12->ales_opc2 << 8) | alopf12->ales_opce)) continue; @@ -854,6 +909,12 @@ print_alf (disassemble_info *info, int chn) instructions which are disassembled as ALOPF10 above. */ else if (templ->alopf == AAURW) continue; + /* This just prevents an assertion failure on recently added ALOPF19 + templates for the sake of LDAA* instructions support in GAS. TODO: + their disassembly is to be implemented yet by analogy with ALOPF10 + `STAA*'s. */ + else if (templ->alopf == ALOPF19) + continue; /* It's a 100% internal error if we turned out to be incapable of recognizing our own instruction template. It would be easier to skip it silently, of course, and not to disappoint the user, who @@ -971,10 +1032,15 @@ print_alf (disassemble_info *info, int chn) else if (match->alopf == ALOPF2 || match->alopf == ALOPF12 || match->alopf == ALOPF12_PSHUFH + || match->alopf == ALOPF12_IBRANCHD + || match->alopf == ALOPF12_ICALLD || match->alopf == ALOPF22) { const e2k_alf2_opcode_templ *alf2 = (const e2k_alf2_opcode_templ *) match; + if (match->alopf == ALOPF12_ICALLD) + my_printf ("wbs = 0x%x, ", (instr->als[chn] & 0x00ff0000) >> 16); + print_src2 (info, chn, alf2->arg_fmt[0]); my_printf (", "); @@ -983,6 +1049,10 @@ print_alf (disassemble_info *info, int chn) my_printf ("0x%x, ", (unsigned) (instr->ales[chn] & 0xff)); print_dst_in_als (info, chn, alf2->arg_fmt[1]); + + if (match->alopf == ALOPF12_IBRANCHD + || match->alopf == ALOPF12_ICALLD) + print_ctcond (info, instr->ss & 0x1ff); } else if (match->alopf == ALOPF3 || match->alopf == ALOPF13) @@ -1042,8 +1112,6 @@ print_alf (disassemble_info *info, int chn) { unsigned int opce1 = (instr->als[chn] & 0x00ffff00) >> 8; unsigned int lt = opce1 & 0x3; - unsigned int am = (opce1 & 0x4) >> 2; - unsigned int incr = (opce1 & 0x70) >> 4; unsigned int ind = (opce1 & 0x780) >> 7; unsigned int d = (opce1 & 0xf800) >> 11; @@ -1063,13 +1131,6 @@ print_alf (disassemble_info *info, int chn) } my_printf (" ]"); - - if (am) - { - indentate (); - my_printf ("incr,%d %%aaincr%d", chn, incr); - } - } if (match->need_mas @@ -1093,8 +1154,27 @@ print_alf (disassemble_info *info, int chn) || match->alopf == ALOPF21_MERGE) print_predicates (info, chn, 1); - /* Print RLP predicates. */ - print_predicates (info, chn, 0); + /* Print RLP predicates. Note that because these predicates are `alj_cond's + they are not applicable to `I{BRANCH,CALL}D'. */ + if (match->alopf != ALOPF12_IBRANCHD + && match->alopf != ALOPF12_ICALLD) + print_predicates (info, chn, 0); + + /* Disassemble the INCR part of ALOPF10. */ + if (match->alopf == ALOPF10) + { + unsigned int opce1 = (instr->als[chn] & 0x00ffff00) >> 8; + unsigned int am = (opce1 & 0x4) >> 2; + unsigned int incr = (opce1 & 0x70) >> 4; + + if (am) + { + indentate (); + my_printf ("incr,%d %%aaincr%d", chn, incr); + print_predicates (info, chn == 2 ? 6 : 7, 0); + } + } + end_syllable (); } @@ -1571,6 +1651,7 @@ print_cs0 (disassemble_info *info, bfd_vma instr_addr) PREF, PUTTSD, DONE, + IRET, HRET, GLAUNCH, DISP, @@ -1581,8 +1662,9 @@ print_cs0 (disassemble_info *info, bfd_vma instr_addr) } cs0_type; static const char *cs0_names[] = {"", "ibranch", "pref", "puttsd", - "done", "hret", "glaunch", "disp", "sdisp", - "gettsd", "ldisp", "return"}; + "done", "iret", "hret", "glaunch", + "disp", "sdisp", "gettsd", "ldisp", + "return"}; /* This is a copy of Table B.4.1 in `iset-v6.single'. */ static cs0_type cs0_ops[4][4] = { {IBRANCH, PREF, PUTTSD, DONE}, @@ -1604,7 +1686,12 @@ print_cs0 (disassemble_info *info, bfd_vma instr_addr) type = GETTSD; else if (type == DONE) { - if (param_type == 3) + /* For {H,I}RET and GLAUNCH CS0.opc is the same as that of DONE (see + Table B.4.1). Param types making these instructions different are + listed in Table B.4.1.1. */ + if (param_type == 2) + type = IRET; + else if (param_type == 3) type = HRET; else if (param_type == 4) type = GLAUNCH; @@ -1613,28 +1700,34 @@ print_cs0 (disassemble_info *info, bfd_vma instr_addr) print_syllable ("CS0", 0, instr->cs0); - if (type == IBRANCH || type == DONE || type == HRET || type == GLAUNCH) + if (type == IBRANCH + || type == DONE + || type == IRET + || type == HRET + || type == GLAUNCH) { - /* IBRANCH, DONE, HRET and GLAUNCH are special because they require SS + /* IBRANCH, DONE, {H,I}RET and GLAUNCH are special because they require SS to be properly encoded. */ if (! instr->ss_present - /* SS.ctop should be equal to zero for IBRANCH, DONE, HRET and - GLAUNCH (see C.17.1.1, note that they don't mention the latter two - instructions there which is probably an omission ). */ + /* SS.ctop should be equal to zero for IBRANCH, DONE, {I,H}RET and + GLAUNCH (see C.17.1.1, note that they don't mention the latter three + instructions there which is probably an omission; however, this is + specified in the description of each instruction ). */ || (instr->ss & 0x00000c00)) { indentate (); my_printf ("invalid %s", cs0_names[type]); } /* Don't output either of the aforementioned instructions under "never" - condition. Don't disassemble CS0 being a part of HCALL. Unlike ldis - HCALL is currently disassembled on behalf of CS1. */ + condition. Don't disassemble CS0 being a part of {H,I}CALL. Unlike + ldis {H,I}CALL are currently disassembled on behalf of CS1. */ else if (instr->ss & 0x1ff && !(instr->cs1_present /* CS1.opc == CALL */ && (instr->cs1 & 0xf0000000) >> 28 == 5 - /* CS1.param.ctopc == HCALL */ - && (instr->cs1 & 0x380) >> 7 == 2)) + /* CS1.param.ctopc == {H,I}CALL */ + && ((instr->cs1 & 0x380) >> 7 == 2 + || (instr->cs1 & 0x380) >> 7 == 1))) { indentate (); my_printf ("%s", cs0_names[type]); @@ -1884,17 +1977,25 @@ print_cs1 (disassemble_info *info) else { unsigned int cs1_ctopc = (cs1 & 0x380) >> 7; - /* CS1.param.ctpopc == HCALL. CS0 is required to encode HCALL. */ - if (cs1_ctopc == 2 && instr->cs0_present) + /* CS1.param.ctpopc == {H,I}CALL == {2,1} (see Table B.4.2.1). + CS0 is required to encode {H,I}CALL. */ + if ((cs1_ctopc == 2 || cs1_ctopc == 1) && instr->cs0_present) { unsigned int cs0 = instr->cs0; unsigned int cs0_opc = (cs0 & 0xf0000000) >> 28; - /* CS0.opc == HCALL, which means + /* CS0.opc == {H,I}CALL == 0 (see Table B.4.1), which means CS0.opc.ctpr == CS0.opc.ctp_opc == 0 */ if (cs0_opc == 0) { - unsigned int hdisp = (cs0 & 0x1e) >> 1; - my_printf ("hcall 0x%x, wbs = 0x%x", hdisp, wbs); + int is_hcall = cs1_ctopc == 2; + unsigned int disp; + + /* HCALL's hdisp is encoded in a rather weird way in + CS0.disp[4:1] unlike ICALL's disp occupying the whole + 28-bit CS0.disp. */ + disp = is_hcall ? ((cs0 & 0x1e) >> 1) : (cs0 & 0xfffffff); + my_printf ("%ccall 0x%x, wbs = 0x%x", + is_hcall ? 'h' : 'i', disp, wbs); print_ctcond (info, instr->ss & 0x1ff); } } @@ -1931,6 +2032,25 @@ print_cs1 (disassemble_info *info) indentate (); my_printf ("flushc"); } + + /* Presumably the presence of `FILL{R,C}' on `elbrus-v{X<6}' could be + silently ignored as they are not recognized by these CPUs and probably + don't result in any exceptions, however, I'd prefer to attract the + user's attention to the fact that these unimplemented instructions are + encoded in the disassembled file. */ + /* Check for `CS1.param.fillr'. */ + if (cs1 & 0x00000004) + { + indentate (); + my_printf ("%sfillr", mcpu < 6 ? "unimp " : ""); + } + + /* Check for `CS1.param.fillc'. */ + if (cs1 & 0x00000008) + { + indentate (); + my_printf ("%sfillc", mcpu < 6 ? "unimp " : ""); + } } else if (opc == BG) { @@ -2275,6 +2395,7 @@ print_insn_e2k (bfd_vma memaddr, disassemble_info *info) int status; size_t command_length; static int initialized; + bfd_vma stop_vma; /* This lets me stupidly shut Bug #88528 up for now . . . */ if (! initialized @@ -2294,14 +2415,27 @@ print_insn_e2k (bfd_vma memaddr, disassemble_info *info) initialized = 1; } + /* disassemble_bytes () sets `info->stop_vma' to zero rather than to a + meaningful value when disassembling non-code sections or when + `--disassemble-all (-D)' is in effect. Just ensure that we don't + cross the disassembled section's boundary in such a case. The + meaningful `info->stop_vma' is likely to take into account the + address of the nearest symbol assumed to lie on the boundary between + instructions. */ + if (info->stop_vma == 0 && info->section != NULL) + stop_vma = info->section->vma + info->section->size; + else + stop_vma = info->stop_vma; + /* Don't even try to disassemble if the available address range doesn't fit the most short possible instruction or is not properly aligned. */ - if (info->stop_vma - memaddr < 8 + if ((stop_vma != 0 + && stop_vma < memaddr + 8) || (memaddr & 0x7) != 0) { /* Skip remaining bytes. Hopefully, we'll resume disassembly starting from a more meaningful symbol. */ - command_length = info->stop_vma - memaddr; + command_length = stop_vma - memaddr; info->bytes_per_line = command_length; return command_length; } @@ -2330,7 +2464,8 @@ print_insn_e2k (bfd_vma memaddr, disassemble_info *info) if (/* Is there enough space in the available address range to hold a presumable synchronous instruction? */ - info->stop_vma - memaddr >= command_length + (stop_vma == 0 + || stop_vma >= memaddr + command_length) /* If so, read its remaining bytes. */ && (*info->read_memory_func) (memaddr + 1, &buffer[1], command_length - 1, info) == 0 @@ -2338,11 +2473,12 @@ print_insn_e2k (bfd_vma memaddr, disassemble_info *info) synchronous instruction. */ && unpack_instr (buffer)) print_instr (info, memaddr); - else if (info->stop_vma - memaddr < 16) + else if (stop_vma != 0 + && stop_vma < memaddr + 16) { /* There's no point in trying to interpret this bogus sequence of bytes as an APB instruction if it's not sufficiently long. */ - command_length = info->stop_vma - memaddr; + command_length = stop_vma - memaddr; info->bytes_per_line = command_length; return command_length; } diff --git a/opcodes/e2k-opc.c b/opcodes/e2k-opc.c index 7665f0aee8..23c151781c 100644 --- a/opcodes/e2k-opc.c +++ b/opcodes/e2k-opc.c @@ -5,7 +5,10 @@ #include "libiberty.h" #include "opcode/e2k.h" -int mcpu; +/* Imply `-mcpu=elbrus-v2' by default now that support for `-mcpu={generic, + elbrus-v1}' is to be removed from `e2k-linux-as' (see Bug #96498, + Comment #11). */ +int mcpu = 2; #define MAX_E2K_NUM_OPCODES 16384 struct e2k_opcode_templ *e2k_opcode_templs[MAX_E2K_NUM_OPCODES]; @@ -192,6 +195,11 @@ init_opcode_templs () COPF4_VEC_ENTRY (flushr); COPF4_VEC_ENTRY (flushc); + if (mcpu >= 6) + { + COPF4_VEC_ENTRY (fillr); + COPF4_VEC_ENTRY (fillc); + } SETCMD_VEC_ENTRY (setbn, 0); SETCMD_VEC_ENTRY (setbp, 1); @@ -208,7 +216,10 @@ init_opcode_templs () E2K_OPCODE_VEC_ENTRY (call, parse_ct_args); if (mcpu >= 6) - E2K_OPCODE_VEC_ENTRY (hcall, parse_hcall_args); + { + E2K_OPCODE_VEC_ENTRY (hcall, parse_hicall_args); + E2K_OPCODE_VEC_ENTRY (icall, parse_hicall_args); + } E2K_OPCODE_VEC_ENTRY (ipd, parse_ipd_args); @@ -217,6 +228,15 @@ init_opcode_templs () E2K_OPCODE_VEC_ENTRY (abn, parse_abn_args); E2K_OPCODE_VEC_ENTRY (abp, parse_abp_args); E2K_OPCODE_VEC_ENTRY (abg, parse_abg_args); + + E2K_OPCODE_VEC_ENTRY (srp, parse_srp_args); + + if (mcpu >= 2) + E2K_OPCODE_VEC_ENTRY (crp, parse_crp_args); + + if (mcpu >= 3) + E2K_OPCODE_VEC_ENTRY (slrp, parse_slrp_args); + E2K_OPCODE_VEC_ENTRY (bap, parse_bap_args); E2K_OPCODE_VEC_ENTRY (eap, parse_eap_args); @@ -226,12 +246,13 @@ init_opcode_templs () E2K_OPCODE_VEC_ENTRY (ibranch, parse_ibranch_args); E2K_OPCODE_VEC_ENTRY (rbranch, parse_ibranch_args); - E2K_OPCODE_VEC_ENTRY (done, parse_done_hret_glaunch_args); + E2K_OPCODE_VEC_ENTRY (done, parse_done_hiret_glaunch_args); if (mcpu >= 6) { - E2K_OPCODE_VEC_ENTRY (hret, parse_done_hret_glaunch_args); - E2K_OPCODE_VEC_ENTRY (glaunch, parse_done_hret_glaunch_args); + E2K_OPCODE_VEC_ENTRY (iret, parse_done_hiret_glaunch_args); + E2K_OPCODE_VEC_ENTRY (hret, parse_done_hiret_glaunch_args); + E2K_OPCODE_VEC_ENTRY (glaunch, parse_done_hiret_glaunch_args); } E2K_OPCODE_VEC_ENTRY (wait, parse_wait_args); diff --git a/opcodes/e2k-opc.h b/opcodes/e2k-opc.h index 5ef4c3ab38..d960b16564 100644 --- a/opcodes/e2k-opc.h +++ b/opcodes/e2k-opc.h @@ -1363,6 +1363,31 @@ {"aaurwq", parse_alf_args, NULL, AAURW, NO_MAS, 0x3f, {0, 0, 1, 0, 0, 1}, ARGS_Q}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } +{ + static e2k_alf9_opcode_templ dummy = + {"ldaab", parse_alf_args, NULL, ALOPF19, MAS, 0x5c, {0, 0, 1, 0, 0, 1}, ARGS_S}; + add_to_insn_table ((e2k_opcode_templ *) &dummy); +} +{ + static e2k_alf9_opcode_templ dummy = + {"ldaah", parse_alf_args, NULL, ALOPF19, MAS, 0x5d, {0, 0, 1, 0, 0, 1}, ARGS_S}; + add_to_insn_table ((e2k_opcode_templ *) &dummy); +} +{ + static e2k_alf9_opcode_templ dummy = + {"ldaaw", parse_alf_args, NULL, ALOPF19, MAS, 0x5e, {0, 0, 1, 0, 0, 1}, ARGS_S}; + add_to_insn_table ((e2k_opcode_templ *) &dummy); +} +{ + static e2k_alf9_opcode_templ dummy = + {"ldaad", parse_alf_args, NULL, ALOPF19, MAS, 0x5f, {0, 0, 1, 0, 0, 1}, ARGS_D}; + add_to_insn_table ((e2k_opcode_templ *) &dummy); +} +{ + static e2k_alf9_opcode_templ dummy = + {"ldaaq", parse_alf_args, NULL, ALOPF19, MAS, 0x7f, {0, 0, 1, 0, 0, 1}, ARGS_Q}; + add_to_insn_table ((e2k_opcode_templ *) &dummy); +} { static e2k_alf9_opcode_templ dummy = {"aaurr", parse_alf_args, NULL, AAURR, NO_MAS, 0x5e, {0, 0, 1, 0, 0, 1}, ARGS_S}; @@ -1425,172 +1450,172 @@ } { static e2k_alopf11_opcode_templ dummy = - {"paddb", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x8, {1, 0, 0, 1, 0, 0}, ARGS_SSS, NONE, {EXT, 0, 0, EXT, 0, 0}, 0}; + {"paddb", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x8, {1, 0, 0, 1, 0, 0}, ARGS_DDD, NONE, {EXT, 0, 0, EXT, 0, 0}, 0}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } { static e2k_alopf11_opcode_templ dummy = - {"paddh", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x9, {1, 0, 0, 1, 0, 0}, ARGS_SSS, NONE, {EXT, 0, 0, EXT, 0, 0}, 0}; + {"paddh", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x9, {1, 0, 0, 1, 0, 0}, ARGS_DDD, NONE, {EXT, 0, 0, EXT, 0, 0}, 0}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } { static e2k_alopf11_opcode_templ dummy = - {"paddw", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0xe, {1, 0, 0, 1, 0, 0}, ARGS_SSS, NONE, {EXT, 0, 0, EXT, 0, 0}, 0}; + {"paddw", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0xe, {1, 0, 0, 1, 0, 0}, ARGS_DDD, NONE, {EXT, 0, 0, EXT, 0, 0}, 0}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } { static e2k_alopf11_opcode_templ dummy = - {"paddd", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0xf, {1, 0, 0, 1, 0, 0}, ARGS_SSS, NONE, {EXT, 0, 0, EXT, 0, 0}, 0}; + {"paddd", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0xf, {1, 0, 0, 1, 0, 0}, ARGS_DDD, NONE, {EXT, 0, 0, EXT, 0, 0}, 0}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } { static e2k_alopf11_opcode_templ dummy = - {"paddsb", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0xa, {1, 0, 0, 1, 0, 0}, ARGS_SSS, NONE, {EXT, 0, 0, EXT, 0, 0}, 0}; + {"paddsb", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0xa, {1, 0, 0, 1, 0, 0}, ARGS_DDD, NONE, {EXT, 0, 0, EXT, 0, 0}, 0}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } { static e2k_alopf11_opcode_templ dummy = - {"paddsh", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0xb, {1, 0, 0, 1, 0, 0}, ARGS_SSS, NONE, {EXT, 0, 0, EXT, 0, 0}, 0}; + {"paddsh", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0xb, {1, 0, 0, 1, 0, 0}, ARGS_DDD, NONE, {EXT, 0, 0, EXT, 0, 0}, 0}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } { static e2k_alopf11_opcode_templ dummy = - {"paddusb", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0xc, {1, 0, 0, 1, 0, 0}, ARGS_SSS, NONE, {EXT, 0, 0, EXT, 0, 0}, 0}; + {"paddusb", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0xc, {1, 0, 0, 1, 0, 0}, ARGS_DDD, NONE, {EXT, 0, 0, EXT, 0, 0}, 0}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } { static e2k_alopf11_opcode_templ dummy = - {"paddush", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0xd, {1, 0, 0, 1, 0, 0}, ARGS_SSS, NONE, {EXT, 0, 0, EXT, 0, 0}, 0}; + {"paddush", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0xd, {1, 0, 0, 1, 0, 0}, ARGS_DDD, NONE, {EXT, 0, 0, EXT, 0, 0}, 0}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } { static e2k_alopf11_opcode_templ dummy = - {"psubb", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x10, {1, 0, 0, 1, 0, 0}, ARGS_SSS, NONE, {EXT, 0, 0, EXT, 0, 0}, 0}; + {"psubb", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x10, {1, 0, 0, 1, 0, 0}, ARGS_DDD, NONE, {EXT, 0, 0, EXT, 0, 0}, 0}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } { static e2k_alopf11_opcode_templ dummy = - {"psubh", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x11, {1, 0, 0, 1, 0, 0}, ARGS_SSS, NONE, {EXT, 0, 0, EXT, 0, 0}, 0}; + {"psubh", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x11, {1, 0, 0, 1, 0, 0}, ARGS_DDD, NONE, {EXT, 0, 0, EXT, 0, 0}, 0}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } { static e2k_alopf11_opcode_templ dummy = - {"psubw", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x16, {1, 0, 0, 1, 0, 0}, ARGS_SSS, NONE, {EXT, 0, 0, EXT, 0, 0}, 0}; + {"psubw", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x16, {1, 0, 0, 1, 0, 0}, ARGS_DDD, NONE, {EXT, 0, 0, EXT, 0, 0}, 0}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } { static e2k_alopf11_opcode_templ dummy = - {"psubd", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x17, {1, 0, 0, 1, 0, 0}, ARGS_SSS, NONE, {EXT, 0, 0, EXT, 0, 0}, 0}; + {"psubd", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x17, {1, 0, 0, 1, 0, 0}, ARGS_DDD, NONE, {EXT, 0, 0, EXT, 0, 0}, 0}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } { static e2k_alopf11_opcode_templ dummy = - {"psubsb", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x12, {1, 0, 0, 1, 0, 0}, ARGS_SSS, NONE, {EXT, 0, 0, EXT, 0, 0}, 0}; + {"psubsb", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x12, {1, 0, 0, 1, 0, 0}, ARGS_DDD, NONE, {EXT, 0, 0, EXT, 0, 0}, 0}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } { static e2k_alopf11_opcode_templ dummy = - {"psubsh", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x13, {1, 0, 0, 1, 0, 0}, ARGS_SSS, NONE, {EXT, 0, 0, EXT, 0, 0}, 0}; + {"psubsh", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x13, {1, 0, 0, 1, 0, 0}, ARGS_DDD, NONE, {EXT, 0, 0, EXT, 0, 0}, 0}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } { static e2k_alopf11_opcode_templ dummy = - {"psubusb", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x14, {1, 0, 0, 1, 0, 0}, ARGS_SSS, NONE, {EXT, 0, 0, EXT, 0, 0}, 0}; + {"psubusb", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x14, {1, 0, 0, 1, 0, 0}, ARGS_DDD, NONE, {EXT, 0, 0, EXT, 0, 0}, 0}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } { static e2k_alopf11_opcode_templ dummy = - {"psubush", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x15, {1, 0, 0, 1, 0, 0}, ARGS_SSS, NONE, {EXT, 0, 0, EXT, 0, 0}, 0}; + {"psubush", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x15, {1, 0, 0, 1, 0, 0}, ARGS_DDD, NONE, {EXT, 0, 0, EXT, 0, 0}, 0}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } { static e2k_alopf11_opcode_templ dummy = - {"pmaxsh", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x3, {1, 0, 0, 1, 0, 0}, ARGS_SSS, NONE, {EXT, 0, 0, EXT, 0, 0}, 0}; + {"pmaxsh", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x3, {1, 0, 0, 1, 0, 0}, ARGS_DDD, NONE, {EXT, 0, 0, EXT, 0, 0}, 0}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } { static e2k_alopf11_opcode_templ dummy = - {"pmaxub", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x2, {1, 0, 0, 1, 0, 0}, ARGS_SSS, NONE, {EXT, 0, 0, EXT, 0, 0}, 0}; + {"pmaxub", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x2, {1, 0, 0, 1, 0, 0}, ARGS_DDD, NONE, {EXT, 0, 0, EXT, 0, 0}, 0}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } { static e2k_alopf11_opcode_templ dummy = - {"pminsh", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x1, {1, 0, 0, 1, 0, 0}, ARGS_SSS, NONE, {EXT, 0, 0, EXT, 0, 0}, 0}; + {"pminsh", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x1, {1, 0, 0, 1, 0, 0}, ARGS_DDD, NONE, {EXT, 0, 0, EXT, 0, 0}, 0}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } { static e2k_alopf11_opcode_templ dummy = - {"pminub", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x0, {1, 0, 0, 1, 0, 0}, ARGS_SSS, NONE, {EXT, 0, 0, EXT, 0, 0}, 0}; + {"pminub", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x0, {1, 0, 0, 1, 0, 0}, ARGS_DDD, NONE, {EXT, 0, 0, EXT, 0, 0}, 0}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } { static e2k_alopf11_opcode_templ dummy = - {"psadbw", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x1c, {0, 1, 0, 0, 1, 0}, ARGS_SSS, NONE, {0, EXT, 0, 0, EXT, 0}, 0}; + {"psadbw", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x1c, {0, 1, 0, 0, 1, 0}, ARGS_DDD, NONE, {0, EXT, 0, 0, EXT, 0}, 0}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } { static e2k_alopf11_opcode_templ dummy = - {"pmulhuh", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x1b, {0, 1, 0, 0, 1, 0}, ARGS_SSS, NONE, {0, EXT, 0, 0, EXT, 0}, 0}; + {"pmulhuh", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x1b, {0, 1, 0, 0, 1, 0}, ARGS_DDD, NONE, {0, EXT, 0, 0, EXT, 0}, 0}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } { static e2k_alopf11_opcode_templ dummy = - {"pmulhh", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x18, {0, 1, 0, 0, 1, 0}, ARGS_SSS, NONE, {0, EXT, 0, 0, EXT, 0}, 0}; + {"pmulhh", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x18, {0, 1, 0, 0, 1, 0}, ARGS_DDD, NONE, {0, EXT, 0, 0, EXT, 0}, 0}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } { static e2k_alopf11_opcode_templ dummy = - {"pmullh", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x19, {0, 1, 0, 0, 1, 0}, ARGS_SSS, NONE, {0, EXT, 0, 0, EXT, 0}, 0}; + {"pmullh", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x19, {0, 1, 0, 0, 1, 0}, ARGS_DDD, NONE, {0, EXT, 0, 0, EXT, 0}, 0}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } { static e2k_alopf11_opcode_templ dummy = - {"pmaddh", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x1a, {0, 1, 0, 0, 1, 0}, ARGS_SSS, NONE, {0, EXT, 0, 0, EXT, 0}, 0}; + {"pmaddh", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x1a, {0, 1, 0, 0, 1, 0}, ARGS_DDD, NONE, {0, EXT, 0, 0, EXT, 0}, 0}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } { static e2k_alopf11_opcode_templ dummy = - {"pslld", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x4e, {0, 1, 0, 0, 1, 0}, ARGS_SSS, NONE, {0, EXT, 0, 0, EXT, 0}, 0}; + {"pslld", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x4e, {0, 1, 0, 0, 1, 0}, ARGS_DDD, NONE, {0, EXT, 0, 0, EXT, 0}, 0}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } { static e2k_alopf11_opcode_templ dummy = - {"psllw", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x14, {0, 1, 0, 0, 1, 0}, ARGS_SSS, NONE, {0, EXT, 0, 0, EXT, 0}, 0}; + {"psllw", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x14, {0, 1, 0, 0, 1, 0}, ARGS_DDD, NONE, {0, EXT, 0, 0, EXT, 0}, 0}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } { static e2k_alopf11_opcode_templ dummy = - {"psllh", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x15, {0, 1, 0, 0, 1, 0}, ARGS_SSS, NONE, {0, EXT, 0, 0, EXT, 0}, 0}; + {"psllh", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x15, {0, 1, 0, 0, 1, 0}, ARGS_DDD, NONE, {0, EXT, 0, 0, EXT, 0}, 0}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } { static e2k_alopf11_opcode_templ dummy = - {"psrld", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x4c, {0, 1, 0, 0, 1, 0}, ARGS_SSS, NONE, {0, EXT, 0, 0, EXT, 0}, 0}; + {"psrld", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x4c, {0, 1, 0, 0, 1, 0}, ARGS_DDD, NONE, {0, EXT, 0, 0, EXT, 0}, 0}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } { static e2k_alopf11_opcode_templ dummy = - {"psrlw", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x10, {0, 1, 0, 0, 1, 0}, ARGS_SSS, NONE, {0, EXT, 0, 0, EXT, 0}, 0}; + {"psrlw", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x10, {0, 1, 0, 0, 1, 0}, ARGS_DDD, NONE, {0, EXT, 0, 0, EXT, 0}, 0}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } { static e2k_alopf11_opcode_templ dummy = - {"psrlh", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x11, {0, 1, 0, 0, 1, 0}, ARGS_SSS, NONE, {0, EXT, 0, 0, EXT, 0}, 0}; + {"psrlh", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x11, {0, 1, 0, 0, 1, 0}, ARGS_DDD, NONE, {0, EXT, 0, 0, EXT, 0}, 0}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } { static e2k_alopf11_opcode_templ dummy = - {"psraw", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x12, {0, 1, 0, 0, 1, 0}, ARGS_SSS, NONE, {0, EXT, 0, 0, EXT, 0}, 0}; + {"psraw", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x12, {0, 1, 0, 0, 1, 0}, ARGS_DDD, NONE, {0, EXT, 0, 0, EXT, 0}, 0}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } { static e2k_alopf11_opcode_templ dummy = - {"psrah", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x13, {0, 1, 0, 0, 1, 0}, ARGS_SSS, NONE, {0, EXT, 0, 0, EXT, 0}, 0}; + {"psrah", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x13, {0, 1, 0, 0, 1, 0}, ARGS_DDD, NONE, {0, EXT, 0, 0, EXT, 0}, 0}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } { static e2k_alopf11_opcode_templ dummy = - {"pfadds", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x30, {1, 1, 0, 1, 1, 0}, ARGS_SSS, NONE, {EXT, EXT, 0, EXT, EXT, 0}, 1}; + {"pfadds", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x30, {1, 1, 0, 1, 1, 0}, ARGS_DDD, NONE, {EXT, EXT, 0, EXT, EXT, 0}, 1}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } { @@ -1600,7 +1625,7 @@ } { static e2k_alopf11_opcode_templ dummy = - {"pfsubs", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x32, {1, 1, 0, 1, 1, 0}, ARGS_SSS, NONE, {EXT, EXT, 0, EXT, EXT, 0}, 1}; + {"pfsubs", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x32, {1, 1, 0, 1, 1, 0}, ARGS_DDD, NONE, {EXT, EXT, 0, EXT, EXT, 0}, 1}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } { @@ -3102,37 +3127,37 @@ if (mcpu == 2) if (mcpu >= 3) { static e2k_alopf11_opcode_templ dummy = - {"psllw", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x14, {1, 0, 0, 1, 0, 0}, ARGS_SSS, NONE, {EXT1, 0, 0, EXT1, 0, 0}, 0}; + {"psllw", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x14, {1, 0, 0, 1, 0, 0}, ARGS_DDD, NONE, {EXT1, 0, 0, EXT1, 0, 0}, 0}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } if (mcpu >= 3) { static e2k_alopf11_opcode_templ dummy = - {"psllh", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x15, {1, 0, 0, 1, 0, 0}, ARGS_SSS, NONE, {EXT1, 0, 0, EXT1, 0, 0}, 0}; + {"psllh", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x15, {1, 0, 0, 1, 0, 0}, ARGS_DDD, NONE, {EXT1, 0, 0, EXT1, 0, 0}, 0}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } if (mcpu >= 3) { static e2k_alopf11_opcode_templ dummy = - {"psrlw", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x10, {1, 0, 0, 1, 0, 0}, ARGS_SSS, NONE, {EXT1, 0, 0, EXT1, 0, 0}, 0}; + {"psrlw", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x10, {1, 0, 0, 1, 0, 0}, ARGS_DDD, NONE, {EXT1, 0, 0, EXT1, 0, 0}, 0}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } if (mcpu >= 3) { static e2k_alopf11_opcode_templ dummy = - {"psrlh", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x11, {1, 0, 0, 1, 0, 0}, ARGS_SSS, NONE, {EXT1, 0, 0, EXT1, 0, 0}, 0}; + {"psrlh", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x11, {1, 0, 0, 1, 0, 0}, ARGS_DDD, NONE, {EXT1, 0, 0, EXT1, 0, 0}, 0}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } if (mcpu >= 3) { static e2k_alopf11_opcode_templ dummy = - {"psraw", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x12, {1, 0, 0, 1, 0, 0}, ARGS_SSS, NONE, {EXT1, 0, 0, EXT1, 0, 0}, 0}; + {"psraw", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x12, {1, 0, 0, 1, 0, 0}, ARGS_DDD, NONE, {EXT1, 0, 0, EXT1, 0, 0}, 0}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } if (mcpu >= 3) { static e2k_alopf11_opcode_templ dummy = - {"psrah", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x13, {1, 0, 0, 1, 0, 0}, ARGS_SSS, NONE, {EXT1, 0, 0, EXT1, 0, 0}, 0}; + {"psrah", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x13, {1, 0, 0, 1, 0, 0}, ARGS_DDD, NONE, {EXT1, 0, 0, EXT1, 0, 0}, 0}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } if (mcpu >= 3) @@ -3438,7 +3463,7 @@ if (mcpu >= 4) if (mcpu >= 4) { static e2k_alopf11_opcode_templ dummy = - {"pfadds", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x30, {0, 0, 1, 0, 0, 1}, ARGS_SSS, NONE, {0, 0, EXT, 0, 0, EXT}, 1}; + {"pfadds", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x30, {0, 0, 1, 0, 0, 1}, ARGS_DDD, NONE, {0, 0, EXT, 0, 0, EXT}, 1}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } if (mcpu >= 4) @@ -3450,7 +3475,7 @@ if (mcpu >= 4) if (mcpu >= 4) { static e2k_alopf11_opcode_templ dummy = - {"pfsubs", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x32, {0, 0, 1, 0, 0, 1}, ARGS_SSS, NONE, {0, 0, EXT, 0, 0, EXT}, 1}; + {"pfsubs", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x32, {0, 0, 1, 0, 0, 1}, ARGS_DDD, NONE, {0, 0, EXT, 0, 0, EXT}, 1}; add_to_insn_table ((e2k_opcode_templ *) &dummy); } if (mcpu >= 4) @@ -3538,6 +3563,12 @@ if (mcpu >= 5) add_to_insn_table ((e2k_opcode_templ *) &dummy); } if (mcpu >= 5) +{ + static e2k_alf9_opcode_templ dummy = + {"ldaaqp", parse_alf_args, NULL, ALOPF19, MAS, 0x60, {0, 0, 1, 0, 0, 1}, ARGS_P}; + add_to_insn_table ((e2k_opcode_templ *) &dummy); +} +if (mcpu >= 5) { static e2k_alopf11_opcode_templ dummy = {"qpand", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x8, {1, 1, 0, 1, 1, 0}, ARGS_PPP, NONE, {EXT1, EXT1, 0, EXT1, EXT1, 0}, 0}; @@ -4762,6 +4793,12 @@ if (mcpu >= 6) add_to_insn_table ((e2k_opcode_templ *) &dummy); } if (mcpu >= 6) +{ + static e2k_alopf11_opcode_templ dummy = + {"qpsrad", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x25, {1, 1, 0, 1, 1, 0}, ARGS_PDP, NONE, {EXT1, EXT1, 0, EXT1, EXT1, 0}, 0}; + add_to_insn_table ((e2k_opcode_templ *) &dummy); +} +if (mcpu >= 6) { static e2k_alopf11_opcode_templ dummy = {"pmrgp", parse_alf_args, merge_alopf11, ALOPF11_MERGE, NO_MAS, 0x40, {1, 1, 0, 1, 1, 0}, ARGS_DDD, NONE, {EXT, EXT, 0, EXT, EXT, 0}, 0}; @@ -4786,6 +4823,24 @@ if (mcpu >= 6) add_to_insn_table ((e2k_opcode_templ *) &dummy); } if (mcpu >= 6) +{ + static e2k_alopf11_opcode_templ dummy = + {"qpchecks", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x33, {1, 0, 0, 1, 0, 0}, ARGS_SSS, QPCHECKS, {EXT1, 0, 0, EXT1, 0, 0}, 0}; + add_to_insn_table ((e2k_opcode_templ *) &dummy); +} +if (mcpu >= 6) +{ + static e2k_alopf11_opcode_templ dummy = + {"qpcheckd", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x33, {1, 0, 0, 1, 0, 0}, ARGS_DDD, QPCHECKD, {EXT1, 0, 0, EXT1, 0, 0}, 0}; + add_to_insn_table ((e2k_opcode_templ *) &dummy); +} +if (mcpu >= 6) +{ + static e2k_alopf11_opcode_templ dummy = + {"qpcheckq", parse_alf_args, merge_alopf11, ALOPF11, NO_MAS, 0x33, {1, 0, 0, 1, 0, 0}, ARGS_PPP, QPCHECKQ, {EXT1, 0, 0, EXT1, 0, 0}, 0}; + add_to_insn_table ((e2k_opcode_templ *) &dummy); +} +if (mcpu >= 6) { static e2k_alopf12_opcode_templ dummy = {"ibranchd", parse_alf_args, NULL, ALOPF12_IBRANCHD, NO_MAS, 0x53, {1, 0, 0, 0, 0, 0}, ARGS_DD, NONE, NONE, EXT}; diff --git a/opcodes/e2k-stuff/e2k-opcode-generator.c b/opcodes/e2k-stuff/e2k-opcode-generator.c index d0a067c7ea..dc1328195a 100644 --- a/opcodes/e2k-stuff/e2k-opcode-generator.c +++ b/opcodes/e2k-stuff/e2k-opcode-generator.c @@ -1164,7 +1164,7 @@ gen_alopf10 () for (i = 0; i < sizeof (ins_name) / sizeof (ins_name[0]); i++) { - const char *instr_fmt = i < 6 ? "ALOPF10" : "AAURW"; + const char *instr_fmt = real_name[i] == NULL ? "ALOPF10" : "AAURW"; instr_cop_chn cop_chn; if (! fetch_cop_channels (i != 5 ? long_opers : long_ext1_opers, @@ -1176,8 +1176,8 @@ gen_alopf10 () print_common_part ("e2k_alf10_opcode_templ", ins_name[i], "parse_alf_args"); - print_alf_part (instr_fmt, i < 6 ? "MAS" : "NO_MAS", cop_chn.cop, - cop_chn.channels, fmt[i]); + print_alf_part (instr_fmt, real_name[i] == NULL ? "MAS" : "NO_MAS", + cop_chn.cop, cop_chn.channels, fmt[i]); print_final_part (); @@ -1191,15 +1191,22 @@ static void gen_alopf19 () { int i; - static const char *ins_name[] = {"aaurr", "aaurrd", "aaurrq"}; - static const char *real_name[] = {"ldaaw", "ldaad", "ldaaq"}; - static const char *fmt[] = {"ARGS_S", "ARGS_D", "ARGS_Q"}; + static const char *ins_name[] = {"ldaab", "ldaah", "ldaaw", + "ldaad", "ldaaq", "ldaaqp", + "aaurr", "aaurrd", "aaurrq"}; + static const char *real_name[] = {NULL, NULL, NULL, + NULL, NULL, NULL, + "ldaaw", "ldaad", "ldaaq"}; + static const char *fmt[] = {"ARGS_S", "ARGS_S", "ARGS_S", + "ARGS_D", "ARGS_Q", "ARGS_P", + "ARGS_S", "ARGS_D", "ARGS_Q"}; - for (i = 0; i < 3; i++) + for (i = 0; i < sizeof (ins_name) / sizeof (ins_name[0]); i++) { + const char *instr_fmt = real_name[i] == NULL ? "ALOPF19" : "AAURR"; instr_cop_chn cop_chn; - if (! fetch_cop_channels (long_opers, + if (! fetch_cop_channels (i != 5 ? long_opers : long_ext1_opers, (real_name[i] != NULL ? real_name[i] : ins_name[i]), @@ -1208,8 +1215,8 @@ gen_alopf19 () print_common_part ("e2k_alf9_opcode_templ", ins_name[i], "parse_alf_args"); - print_alf_part ("AAURR", "NO_MAS", cop_chn.cop, cop_chn.channels, - fmt[i]); + print_alf_part (instr_fmt, real_name[i] == NULL ? "MAS" : "NO_MAS", + cop_chn.cop, cop_chn.channels, fmt[i]); print_final_part (); @@ -1419,44 +1426,44 @@ gen_alopf11 () {"fsqrttd", "ARGS_DDD"}, {"pfmuls", "ARGS_DDD"}, {"pfmuld", "ARGS_DDD"}, - {"paddb", "ARGS_SSS"}, - {"paddh", "ARGS_SSS"}, - {"paddw", "ARGS_SSS"}, - {"paddd", "ARGS_SSS"}, - {"paddsb", "ARGS_SSS"}, - {"paddsh", "ARGS_SSS"}, - {"paddusb", "ARGS_SSS"}, - {"paddush", "ARGS_SSS"}, - {"psubb", "ARGS_SSS"}, - {"psubh", "ARGS_SSS"}, - {"psubw", "ARGS_SSS"}, - {"psubd", "ARGS_SSS"}, - {"psubsb", "ARGS_SSS"}, - {"psubsh", "ARGS_SSS"}, - {"psubusb", "ARGS_SSS"}, - {"psubush", "ARGS_SSS"}, - {"pmaxsh", "ARGS_SSS"}, - {"pmaxub", "ARGS_SSS"}, - {"pminsh", "ARGS_SSS"}, - {"pminub", "ARGS_SSS"}, - {"psadbw", "ARGS_SSS"}, - {"pmulhuh", "ARGS_SSS"}, - {"pmulhh", "ARGS_SSS"}, - {"pmullh", "ARGS_SSS"}, - {"pmaddh", "ARGS_SSS"}, + {"paddb", "ARGS_DDD"}, + {"paddh", "ARGS_DDD"}, + {"paddw", "ARGS_DDD"}, + {"paddd", "ARGS_DDD"}, + {"paddsb", "ARGS_DDD"}, + {"paddsh", "ARGS_DDD"}, + {"paddusb", "ARGS_DDD"}, + {"paddush", "ARGS_DDD"}, + {"psubb", "ARGS_DDD"}, + {"psubh", "ARGS_DDD"}, + {"psubw", "ARGS_DDD"}, + {"psubd", "ARGS_DDD"}, + {"psubsb", "ARGS_DDD"}, + {"psubsh", "ARGS_DDD"}, + {"psubusb", "ARGS_DDD"}, + {"psubush", "ARGS_DDD"}, + {"pmaxsh", "ARGS_DDD"}, + {"pmaxub", "ARGS_DDD"}, + {"pminsh", "ARGS_DDD"}, + {"pminub", "ARGS_DDD"}, + {"psadbw", "ARGS_DDD"}, + {"pmulhuh", "ARGS_DDD"}, + {"pmulhh", "ARGS_DDD"}, + {"pmullh", "ARGS_DDD"}, + {"pmaddh", "ARGS_DDD"}, - {"pslld", "ARGS_SSS"}, - {"psllw", "ARGS_SSS"}, - {"psllh", "ARGS_SSS"}, - {"psrld", "ARGS_SSS"}, - {"psrlw", "ARGS_SSS"}, - {"psrlh", "ARGS_SSS"}, - {"psraw", "ARGS_SSS"}, - {"psrah", "ARGS_SSS"}, + {"pslld", "ARGS_DDD"}, + {"psllw", "ARGS_DDD"}, + {"psllh", "ARGS_DDD"}, + {"psrld", "ARGS_DDD"}, + {"psrlw", "ARGS_DDD"}, + {"psrlh", "ARGS_DDD"}, + {"psraw", "ARGS_DDD"}, + {"psrah", "ARGS_DDD"}, - {"pfadds", "ARGS_SSS"}, + {"pfadds", "ARGS_DDD"}, {"pfaddd", "ARGS_DDD"}, - {"pfsubs", "ARGS_SSS"}, + {"pfsubs", "ARGS_DDD"}, {"pfsubd", "ARGS_DDD"}, {"aptoap", "ARGS_QSQ"}, @@ -1564,6 +1571,7 @@ gen_alopf11 () {"qpsrld", "ARGS_PDP"}, {"qpsrah", "ARGS_PDP"}, {"qpsraw", "ARGS_PDP"}, + {"qpsrad", "ARGS_PDP"}, {"pfdivs", "ARGS_SSS"}, {"pfdivd", "ARGS_DDD"}, @@ -1951,6 +1959,33 @@ gen_alopf11 () gen_alopf11_loads (); } +static void +gen_alopf11_qpcheck () +{ + instr_cop_chn cop_chn; + if (fetch_cop_channels (long_ext1_opers, "qpcheck", &cop_chn)) + { + int i; + char name[] = "qpcheck?"; + const char suff[] = {'s', 'd', 'q'}; + const char *fmt[] = {"ARGS_SSS", "ARGS_DDD", "ARGS_PPP"}; + const char *opce[] = {"QPCHECKS", "QPCHECKD", "QPCHECKQ"}; + for (i = 0; i < 3; i++) + { + name[7] = suff[i]; + print_common_part_with_merge ("e2k_alopf11_opcode_templ", + name, "parse_alf_args", + "merge_alopf11"); + print_alf_part ("ALOPF11", "NO_MAS", cop_chn.cop, cop_chn.channels, + fmt[i]); + + print_alopf11_tail (opce[i], cop_chn.channels, "EXT1", 0); + print_final_part (); + } + } +} + + static void gen_alopf11_with_flags () { @@ -3449,6 +3484,7 @@ main () gen_alopf19 (); gen_alopf11 (); gen_alopf11_with_flags (); + gen_alopf11_qpcheck (); gen_alopf12 (); gen_alopf13 (); gen_alopf15 (); diff --git a/opcodes/e2k-stuff/e2k-tables/long-ext1-v6 b/opcodes/e2k-stuff/e2k-tables/long-ext1-v6 index 88d7ec746f..455773600a 100644 --- a/opcodes/e2k-stuff/e2k-tables/long-ext1-v6 +++ b/opcodes/e2k-stuff/e2k-tables/long-ext1-v6 @@ -39,7 +39,7 @@ | 22 | PMAXUW | | STCSQP | | 62 | LDCSQP | | LDCSQP | | 23 | PMAXSW | | STDSQP | | 63 | LDDSQP | | LDDSQP | | 24 | | | STESQP | | 64 | LDESQP | | LDESQP | -| 25 | | | STFSQP | | 65 | LDFSQP | | LDFSQP | +| 25 | QPSRAD | QPSRAD | STFSQP | | 65 | LDFSQP | | LDFSQP | | 26 | QPSRCW | QPSRCW | STGSQP | | 66 | LDGSQP | | LDGSQP | | 27 | QPSRCD | QPSRCD | STSSQP | | 67 | LDSSQP | | LDSSQP | +----+----------+----------+----------+ +----+----------+----------+----------+ @@ -55,7 +55,7 @@ | 30 | PSIGNB | | FADDs | | 70 | QPFADDs | QPFADDs | QPFADDs | | 31 | PSIGNH | | FADDd | | 71 | QPFADDd | QPFADDd | QPFADDd | | 32 | PSIGNW | | FSUBs | | 72 | QPFSUBs | QPFSUBs | QPFSUBs | -| 33 | | | FSUBd | | 73 | QPFSUBd | QPFSUBd | QPFSUBd | +| 33 | QPCHECK | | FSUBd | | 73 | QPFSUBd | QPFSUBd | QPFSUBd | | 34 |QPMSK2SGNB|QPMSK2SGNB| | | 74 | QPFMINs | QPFMINs | | | 35 | QPCEXT | QPCEXT | | | 75 | QPFMINd | QPFMINd | | | 36 | | | | | 76 | QPFMAXs | QPFMAXs | | diff --git a/opcodes/e2k-stuff/e2k-tables/tables.h b/opcodes/e2k-stuff/e2k-tables/tables.h index a9da37f9cb..9b1a2adeac 100644 --- a/opcodes/e2k-stuff/e2k-tables/tables.h +++ b/opcodes/e2k-stuff/e2k-tables/tables.h @@ -559,8 +559,10 @@ e2k_oper elbrus_v5_long_ext1_opers [] = e2k_oper elbrus_v6_long_ext1_opers [] = { +{0x25, {{"QPSRAD", 0}, {"QPSRAD", 0}, {"", 0} }, 0}, {0x28, {{"PCMPP", 0}, {"", 0}, {"", 0} }, 0}, {0x2c, {{"QPCMPP", 0}, {"", 0}, {"", 0} }, 0}, +{0x33, {{"QPCHECK", 0}, {"", 0}, {"", 0} }, 0}, {0x35, {{"QPCEXT", 0}, {"QPCEXT", 0}, {"", 0} }, 0}, {0x60, {{"QPMRGP", 0}, {"QPMRGP", 0}, {"", 0} }, 0}, }; diff --git a/opcodes/po/es.po b/opcodes/po/es.po index bbb9b15a77..7f67ca0c9b 100644 --- a/opcodes/po/es.po +++ b/opcodes/po/es.po @@ -12,7 +12,6 @@ msgstr "" "Last-Translator: Francisco Javier Serrador \n" "Language-Team: Spanish \n" "Language: es\n" -"X-Bugs: Report translation errors to the Language-Team address.\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/opcodes/po/zh_CN.po b/opcodes/po/zh_CN.po index 19b796eadf..453158bb1b 100644 --- a/opcodes/po/zh_CN.po +++ b/opcodes/po/zh_CN.po @@ -14,7 +14,6 @@ msgstr "" "Last-Translator: Boyuan Yang <073plan@gmail.com>\n" "Language-Team: Chinese (simplified) \n" "Language: zh_CN\n" -"X-Bugs: Report translation errors to the Language-Team address.\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/opcodes/sparc-dis.c b/opcodes/sparc-dis.c index 39ab42206b..504d04ad99 100644 --- a/opcodes/sparc-dis.c +++ b/opcodes/sparc-dis.c @@ -266,9 +266,15 @@ compute_arch_mask (unsigned long mach) case bfd_mach_sparc_v8plusm8 : case bfd_mach_sparc_v9m8 : return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_M8); - case bfd_mach_sparc_v8plus_mcst : - case bfd_mach_sparc_v9_mcst : - return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9_MCST); + case bfd_mach_sparc_v8plus_r1000 : + case bfd_mach_sparc_v9_r1000 : + return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_R1000); + case bfd_mach_sparc_v8plus_r2000 : + case bfd_mach_sparc_v9_r2000 : + return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_R2000); + case bfd_mach_sparc_v8plus_r2000_plus : + case bfd_mach_sparc_v9_r2000_plus : + return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_R2000_PLUS); } abort (); } diff --git a/opcodes/sparc-opc.c b/opcodes/sparc-opc.c index 263ac6499a..6b6f9cafa8 100644 --- a/opcodes/sparc-opc.c +++ b/opcodes/sparc-opc.c @@ -43,7 +43,11 @@ #define MASK_V9V SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9V) #define MASK_V9M SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9M) #define MASK_M8 SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_M8) -#define MASK_V9_MCST SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9_MCST) +#define MASK_R1000 SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_R1000) +#define MASK_R2000 SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_R2000) +#define MASK_R2000_PLUS \ + SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_R2000_PLUS) + /* Bit masks of architectures supporting the insn. */ @@ -51,16 +55,16 @@ | MASK_SPARCLET | MASK_SPARCLITE \ | MASK_V9 | MASK_V9A | MASK_V9B \ | MASK_V9C | MASK_V9D | MASK_V9E | MASK_V9V | MASK_V9M \ - | MASK_M8 | MASK_V9_MCST) + | MASK_M8 | MASK_R1000 | MASK_R2000 | MASK_R2000_PLUS) /* v6 insns not supported on the sparclet. */ #define v6notlet (MASK_V6 | MASK_V7 | MASK_V8 | MASK_LEON \ | MASK_SPARCLITE | MASK_V9 | MASK_V9A | MASK_V9B \ | MASK_V9C | MASK_V9D | MASK_V9E | MASK_V9V | MASK_V9M \ - | MASK_M8 | MASK_V9_MCST) + | MASK_M8 | MASK_R1000 | MASK_R2000 | MASK_R2000_PLUS) #define v7 (MASK_V7 | MASK_V8 | MASK_LEON | MASK_SPARCLET \ | MASK_SPARCLITE | MASK_V9 | MASK_V9A | MASK_V9B \ | MASK_V9C | MASK_V9D | MASK_V9E | MASK_V9V | MASK_V9M \ - | MASK_M8 | MASK_V9_MCST) + | MASK_M8 | MASK_R1000 | MASK_R2000 | MASK_R2000_PLUS) /* Although not all insns are implemented in hardware, sparclite is defined to be a superset of v8. Unimplemented insns trap and are then theoretically implemented in software. @@ -70,7 +74,7 @@ #define v8 (MASK_V8 | MASK_LEON | MASK_SPARCLET | MASK_SPARCLITE \ | MASK_V9 | MASK_V9A | MASK_V9B \ | MASK_V9C | MASK_V9D | MASK_V9E | MASK_V9V | MASK_V9M \ - | MASK_M8 | MASK_V9_MCST) + | MASK_M8 | MASK_R1000 | MASK_R2000 | MASK_R2000_PLUS) #define sparclet (MASK_SPARCLET) #define leon (MASK_LEON) /* sparclet insns supported by leon. */ @@ -78,17 +82,17 @@ #define sparclite (MASK_SPARCLITE) #define v9 (MASK_V9 | MASK_V9A | MASK_V9B \ | MASK_V9C | MASK_V9D | MASK_V9E | MASK_V9V | MASK_V9M \ - | MASK_M8 | MASK_V9_MCST) + | MASK_M8 | MASK_R1000 | MASK_R2000 | MASK_R2000_PLUS) /* v9 insns supported by leon. */ #define v9andleon (MASK_V9 | MASK_V9A | MASK_V9B \ | MASK_V9C | MASK_V9D | MASK_V9E | MASK_V9V | MASK_V9M \ - | MASK_M8 | MASK_V9_MCST | MASK_LEON) + | MASK_M8 | MASK_R1000 | MASK_R2000 | MASK_R2000_PLUS | MASK_LEON) #define v9a (MASK_V9A | MASK_V9B \ | MASK_V9C | MASK_V9D | MASK_V9E | MASK_V9V | MASK_V9M \ - | MASK_M8 | MASK_V9_MCST) + | MASK_M8 | MASK_R1000 | MASK_R2000 | MASK_R2000_PLUS) #define v9b (MASK_V9B \ | MASK_V9C | MASK_V9D | MASK_V9E | MASK_V9V | MASK_V9M \ - | MASK_M8 | MASK_V9_MCST) + | MASK_M8 | MASK_R1000 | MASK_R2000 | MASK_R2000_PLUS) #define v9c (MASK_V9C | MASK_V9D | MASK_V9E | MASK_V9V | MASK_V9M \ | MASK_M8) #define v9d (MASK_V9D | MASK_V9E | MASK_V9V | MASK_V9M | MASK_M8) @@ -96,7 +100,10 @@ #define v9v (MASK_V9V | MASK_V9M | MASK_M8) #define v9m (MASK_V9M | MASK_M8) #define m8 (MASK_M8) -#define v9_mcst (MASK_V9_MCST) +#define r1000 (MASK_R1000 | MASK_R2000 | MASK_R2000_PLUS) +#define r2000 (MASK_R2000 | MASK_R2000_PLUS) +#define r2000_plus (MASK_R2000_PLUS) + /* v6 insns not supported by v9. */ #define v6notv9 (MASK_V6 | MASK_V7 | MASK_V8 | MASK_LEON \ @@ -113,6 +120,8 @@ #define HWS_VB HWS_VA | HWCAP_VIS2 #define HWS_R1000 HWS_VB | HWCAP_FMAF | HWCAP_R1000 #define HWS_R2000 HWS_R1000 | HWCAP_SAPPHIRE +#define HWS_R2000_PLUS HWS_R2000 +#define HWS2_R2000_PLUS HWCAP2_SAPPHIRE_PLUS #define HWS_VC HWS_VB | HWCAP_ASI_BLK_INIT #define HWS_VD HWS_VC | HWCAP_FMAF | HWCAP_VIS3 | HWCAP_HPC #define HWS_VE HWS_VD \ @@ -168,9 +177,16 @@ const struct sparc_opcode_arch sparc_opcode_archs[] = { "m8", (MASK_V6 | MASK_V7 | MASK_V8 | MASK_V9 | MASK_V9A | MASK_V9B | MASK_V9C | MASK_V9D | MASK_V9E | MASK_V9V | MASK_V9M | MASK_M8), HWS_VM8, HWS2_VM8 }, - /* v9b with MCST additions */ + /* v9b with R1000 additions */ { "r1000", (MASK_V6 | MASK_V7 | MASK_V8 | MASK_V9 | MASK_V9A | MASK_V9B - | MASK_V9_MCST), HWS_R1000, 0 }, + | MASK_R1000), HWS_R1000, 0 }, + /* v9b with R{1,2}000 additions */ + { "r2000", (MASK_V6 | MASK_V7 | MASK_V8 | MASK_V9 | MASK_V9A | MASK_V9B + | MASK_R1000 | MASK_R2000), HWS_R2000, 0 }, + /* v9b with R{1,2}000 and R2000+ additions */ + { "r2000+", (MASK_V6 | MASK_V7 | MASK_V8 | MASK_V9 | MASK_V9A | MASK_V9B + | MASK_R1000 | MASK_R2000 | MASK_R2000_PLUS), + HWS_R2000_PLUS, HWS2_R2000_PLUS }, { NULL, 0, 0, 0 } }; @@ -271,6 +287,10 @@ sparc_opcode_lookup_arch (const char *name) to the table below. */ #define __duplicate_r2000__ 1 +/* This macro controls the addition of "r2000+"-specific duplicate entries + (see Bug #117014) to the table below. */ +#define __duplicate_r2000_plus__ 1 + const struct sparc_opcode sparc_opcodes[] = { { "ld", F3(3, 0x00, 0), F3(~3, ~0x00, ~0), "[1+2],d", 0, 0, 0, v6 }, @@ -1851,11 +1871,11 @@ CONDFC ("fbule", "cb013", 0xe, F_CONDBR), { "fsubs", F3F(2, 0x34, 0x045), F3F(~2, ~0x34, ~0x045), "e,f,g", F_FLOAT, 0, 0, v6 }, /* Packed operations for MCST-4R. */ -{ "pfadds",F3F(2, 0x34, 0x040), F3F(~2, ~0x34, ~0x040), "v,B,H", F_FLOAT, HWCAP_R1000, 0, v9_mcst }, -{ "pfsubs",F3F(2, 0x34, 0x044), F3F(~2, ~0x34, ~0x044), "v,B,H", F_FLOAT, HWCAP_R1000, 0, v9_mcst }, -{ "pfnegs",F3F(2, 0x34, 0x004), F3F(~2, ~0x34, ~0x004), "B,H", F_FLOAT, HWCAP_R1000, 0, v9_mcst }, -{ "pfabss",F3F(2, 0x34, 0x008), F3F(~2, ~0x34, ~0x008), "B,H", F_FLOAT, HWCAP_R1000, 0, v9_mcst }, -{ "pfmuls",F3F(2, 0x34, 0x048), F3F(~2, ~0x34, ~0x048), "v,B,H", F_FLOAT, HWCAP_R1000, 0, v9_mcst }, +{ "pfadds",F3F(2, 0x34, 0x040), F3F(~2, ~0x34, ~0x040), "v,B,H", F_FLOAT, HWCAP_R1000, 0, r1000 }, +{ "pfsubs",F3F(2, 0x34, 0x044), F3F(~2, ~0x34, ~0x044), "v,B,H", F_FLOAT, HWCAP_R1000, 0, r1000 }, +{ "pfnegs",F3F(2, 0x34, 0x004), F3F(~2, ~0x34, ~0x004), "B,H", F_FLOAT, HWCAP_R1000, 0, r1000 }, +{ "pfabss",F3F(2, 0x34, 0x008), F3F(~2, ~0x34, ~0x008), "B,H", F_FLOAT, HWCAP_R1000, 0, r1000 }, +{ "pfmuls",F3F(2, 0x34, 0x048), F3F(~2, ~0x34, ~0x048), "v,B,H", F_FLOAT, HWCAP_R1000, 0, r1000 }, #define CMPFCC(x) (((x)&0x3)<<25) @@ -2174,44 +2194,44 @@ SLCBCC("cbnefr", 15), { "fmadds", F3(2, 0x37, 0)|OPF_LOW4(1), F3(~2, ~0x37, 0)|OPF_LOW4(~1), "e,f,4,g", F_FLOAT, HWCAP_FMAF, 0, v9d }, #if __duplicate__ -{ "fmadds", F3(2, 0x37, 0)|OPF_LOW4(1), F3(~2, ~0x37, 0)|OPF_LOW4(~1), "e,f,4,g", F_FLOAT, HWCAP_FMAF, 0, v9_mcst }, +{ "fmadds", F3(2, 0x37, 0)|OPF_LOW4(1), F3(~2, ~0x37, 0)|OPF_LOW4(~1), "e,f,4,g", F_FLOAT, HWCAP_FMAF, 0, r1000 }, #endif /* __duplicate__ */ { "fmaddd", F3(2, 0x37, 0)|OPF_LOW4(2), F3(~2, ~0x37, 0)|OPF_LOW4(~2), "v,B,5,H", F_FLOAT, HWCAP_FMAF, 0, v9d }, #if __duplicate__ -{ "fmaddd", F3(2, 0x37, 0)|OPF_LOW4(2), F3(~2, ~0x37, 0)|OPF_LOW4(~2), "v,B,5,H", F_FLOAT, HWCAP_FMAF, 0, v9_mcst }, +{ "fmaddd", F3(2, 0x37, 0)|OPF_LOW4(2), F3(~2, ~0x37, 0)|OPF_LOW4(~2), "v,B,5,H", F_FLOAT, HWCAP_FMAF, 0, r1000 }, #endif /* __duplicate__ */ { "fpmaddxhi", F3(2, 0x37, 0)|OPF_LOW4(4), F3(~2, ~0x37, 0)|OPF_LOW4(~4), "v,B,5,H", F_FLOAT, HWCAP_IMA, 0, v9v }, { "fmsubs", F3(2, 0x37, 0)|OPF_LOW4(5), F3(~2, ~0x37, 0)|OPF_LOW4(~5), "e,f,4,g", F_FLOAT, HWCAP_FMAF, 0, v9d }, #if __duplicate__ -{ "fmsubs", F3(2, 0x37, 0)|OPF_LOW4(5), F3(~2, ~0x37, 0)|OPF_LOW4(~5), "e,f,4,g", F_FLOAT, HWCAP_FMAF, 0, v9_mcst }, +{ "fmsubs", F3(2, 0x37, 0)|OPF_LOW4(5), F3(~2, ~0x37, 0)|OPF_LOW4(~5), "e,f,4,g", F_FLOAT, HWCAP_FMAF, 0, r1000 }, #endif /* __duplicate__ */ { "fmsubd", F3(2, 0x37, 0)|OPF_LOW4(6), F3(~2, ~0x37, 0)|OPF_LOW4(~6), "v,B,5,H", F_FLOAT, HWCAP_FMAF, 0, v9d }, #if __duplicate__ -{ "fmsubd", F3(2, 0x37, 0)|OPF_LOW4(6), F3(~2, ~0x37, 0)|OPF_LOW4(~6), "v,B,5,H", F_FLOAT, HWCAP_FMAF, 0, v9_mcst }, +{ "fmsubd", F3(2, 0x37, 0)|OPF_LOW4(6), F3(~2, ~0x37, 0)|OPF_LOW4(~6), "v,B,5,H", F_FLOAT, HWCAP_FMAF, 0, r1000 }, #endif /* __duplicate__ */ { "fnmsubs", F3(2, 0x37, 0)|OPF_LOW4(9), F3(~2, ~0x37, 0)|OPF_LOW4(~9), "e,f,4,g", F_FLOAT, HWCAP_FMAF, 0, v9d }, #if __duplicate__ -{ "fnmsubs", F3(2, 0x37, 0)|OPF_LOW4(9), F3(~2, ~0x37, 0)|OPF_LOW4(~9), "e,f,4,g", F_FLOAT, HWCAP_FMAF, 0, v9_mcst }, +{ "fnmsubs", F3(2, 0x37, 0)|OPF_LOW4(9), F3(~2, ~0x37, 0)|OPF_LOW4(~9), "e,f,4,g", F_FLOAT, HWCAP_FMAF, 0, r1000 }, #endif /* __duplicate__ */ { "fnmsubd", F3(2, 0x37, 0)|OPF_LOW4(10), F3(~2, ~0x37, 0)|OPF_LOW4(~10), "v,B,5,H", F_FLOAT, HWCAP_FMAF, 0, v9d }, #if __duplicate__ -{ "fnmsubd", F3(2, 0x37, 0)|OPF_LOW4(10), F3(~2, ~0x37, 0)|OPF_LOW4(~10), "v,B,5,H", F_FLOAT, HWCAP_FMAF, 0, v9_mcst }, +{ "fnmsubd", F3(2, 0x37, 0)|OPF_LOW4(10), F3(~2, ~0x37, 0)|OPF_LOW4(~10), "v,B,5,H", F_FLOAT, HWCAP_FMAF, 0, r1000 }, #endif /* __duplicate__ */ { "fnmadds", F3(2, 0x37, 0)|OPF_LOW4(13), F3(~2, ~0x37, 0)|OPF_LOW4(~13), "e,f,4,g", F_FLOAT, HWCAP_FMAF, 0, v9d }, #if __duplicate__ -{ "fnmadds", F3(2, 0x37, 0)|OPF_LOW4(13), F3(~2, ~0x37, 0)|OPF_LOW4(~13), "e,f,4,g", F_FLOAT, HWCAP_FMAF, 0, v9_mcst }, +{ "fnmadds", F3(2, 0x37, 0)|OPF_LOW4(13), F3(~2, ~0x37, 0)|OPF_LOW4(~13), "e,f,4,g", F_FLOAT, HWCAP_FMAF, 0, r1000 }, #endif /* __duplicate__ */ { "fnmaddd", F3(2, 0x37, 0)|OPF_LOW4(14), F3(~2, ~0x37, 0)|OPF_LOW4(~14), "v,B,5,H", F_FLOAT, HWCAP_FMAF, 0, v9d }, #if __duplicate__ -{ "fnmaddd", F3(2, 0x37, 0)|OPF_LOW4(14), F3(~2, ~0x37, 0)|OPF_LOW4(~14), "v,B,5,H", F_FLOAT, HWCAP_FMAF, 0, v9_mcst }, +{ "fnmaddd", F3(2, 0x37, 0)|OPF_LOW4(14), F3(~2, ~0x37, 0)|OPF_LOW4(~14), "v,B,5,H", F_FLOAT, HWCAP_FMAF, 0, r1000 }, #endif /* __duplicate__ */ { "fumadds", F3(2, 0x3f, 0)|OPF_LOW4(1), F3(~2, ~0x3f, 0)|OPF_LOW4(~1), "e,f,4,g", F_FLOAT, HWCAP_FJFMAU, 0, v9v }, @@ -2228,7 +2248,7 @@ SLCBCC("cbnefr", 15), { "lzcnt", F3F(2, 0x36, 0x017), F3F(~2, ~0x36, ~0x017), "2,d", 0, HWCAP_VIS3, 0, v9d }, #if __duplicate_r2000__ -{ "lzcnt", F3F(2, 0x36, 0x017), F3F(~2, ~0x36, ~0x017), "2,d", 0, HWCAP_SAPPHIRE, 0, v9_mcst }, +{ "lzcnt", F3F(2, 0x36, 0x017), F3F(~2, ~0x36, ~0x017), "2,d", 0, HWCAP_SAPPHIRE, 0, r2000 }, #endif /* __duplicate_r2000__ */ { "lzd", F3F(2, 0x36, 0x017), F3F(~2, ~0x36, ~0x017), "2,d", F_ALIAS, HWCAP_VIS3, 0, v9d }, @@ -2238,156 +2258,188 @@ SLCBCC("cbnefr", 15), { "fsll16", F3F(2, 0x36, 0x021), F3F(~2, ~0x36, ~0x021), "v,B,H", 0, HWCAP_VIS3, 0, v9d }, #if __duplicate_r2000__ -{ "fsll16", F3F(2, 0x36, 0x021), F3F(~2, ~0x36, ~0x021), "v,B,H", 0, HWCAP_SAPPHIRE, 0, v9_mcst }, +{ "fsll16", F3F(2, 0x36, 0x021), F3F(~2, ~0x36, ~0x021), "v,B,H", 0, HWCAP_SAPPHIRE, 0, r2000 }, #endif /* __duplicate_r2000__ */ { "fsrl16", F3F(2, 0x36, 0x023), F3F(~2, ~0x36, ~0x023), "v,B,H", 0, HWCAP_VIS3, 0, v9d }, #if __duplicate_r2000__ -{ "fsrl16", F3F(2, 0x36, 0x023), F3F(~2, ~0x36, ~0x023), "v,B,H", 0, HWCAP_SAPPHIRE, 0, v9_mcst }, +{ "fsrl16", F3F(2, 0x36, 0x023), F3F(~2, ~0x36, ~0x023), "v,B,H", 0, HWCAP_SAPPHIRE, 0, r2000 }, #endif /* __duplicate_r2000__ */ { "fsll32", F3F(2, 0x36, 0x025), F3F(~2, ~0x36, ~0x025), "v,B,H", 0, HWCAP_VIS3, 0, v9d }, #if __duplicate_r2000__ -{ "fsll32", F3F(2, 0x36, 0x025), F3F(~2, ~0x36, ~0x025), "v,B,H", 0, HWCAP_SAPPHIRE, 0, v9_mcst }, +{ "fsll32", F3F(2, 0x36, 0x025), F3F(~2, ~0x36, ~0x025), "v,B,H", 0, HWCAP_SAPPHIRE, 0, r2000 }, #endif /* __duplicate_r2000__ */ { "fsrl32", F3F(2, 0x36, 0x027), F3F(~2, ~0x36, ~0x027), "v,B,H", 0, HWCAP_VIS3, 0, v9d }, #if __duplicate_r2000__ -{ "fsrl32", F3F(2, 0x36, 0x027), F3F(~2, ~0x36, ~0x027), "v,B,H", 0, HWCAP_SAPPHIRE, 0, v9_mcst }, +{ "fsrl32", F3F(2, 0x36, 0x027), F3F(~2, ~0x36, ~0x027), "v,B,H", 0, HWCAP_SAPPHIRE, 0, r2000 }, #endif /* __duplicate_r2000__ */ { "fslas16", F3F(2, 0x36, 0x029), F3F(~2, ~0x36, ~0x029), "v,B,H", 0, HWCAP_VIS3, 0, v9d }, #if __duplicate_r2000__ -{ "fslas16", F3F(2, 0x36, 0x029), F3F(~2, ~0x36, ~0x029), "v,B,H", 0, HWCAP_SAPPHIRE, 0, v9_mcst }, +{ "fslas16", F3F(2, 0x36, 0x029), F3F(~2, ~0x36, ~0x029), "v,B,H", 0, HWCAP_SAPPHIRE, 0, r2000 }, #endif /* __duplicate_r2000__ */ { "fsra16", F3F(2, 0x36, 0x02b), F3F(~2, ~0x36, ~0x02b), "v,B,H", 0, HWCAP_VIS3, 0, v9d }, #if __duplicate_r2000__ -{ "fsra16", F3F(2, 0x36, 0x02b), F3F(~2, ~0x36, ~0x02b), "v,B,H", 0, HWCAP_SAPPHIRE, 0, v9_mcst }, +{ "fsra16", F3F(2, 0x36, 0x02b), F3F(~2, ~0x36, ~0x02b), "v,B,H", 0, HWCAP_SAPPHIRE, 0, r2000 }, #endif /* __duplicate_r2000__ */ { "fslas32", F3F(2, 0x36, 0x02d), F3F(~2, ~0x36, ~0x02d), "v,B,H", 0, HWCAP_VIS3, 0, v9d }, #if __duplicate_r2000__ -{ "fslas32", F3F(2, 0x36, 0x02d), F3F(~2, ~0x36, ~0x02d), "v,B,H", 0, HWCAP_SAPPHIRE, 0, v9_mcst }, +{ "fslas32", F3F(2, 0x36, 0x02d), F3F(~2, ~0x36, ~0x02d), "v,B,H", 0, HWCAP_SAPPHIRE, 0, r2000 }, #endif /* __duplicate_r2000__ */ { "fsra32", F3F(2, 0x36, 0x02f), F3F(~2, ~0x36, ~0x02f), "v,B,H", 0, HWCAP_VIS3, 0, v9d }, #if __duplicate_r2000__ -{ "fsra32", F3F(2, 0x36, 0x02f), F3F(~2, ~0x36, ~0x02f), "v,B,H", 0, HWCAP_SAPPHIRE, 0, v9_mcst }, +{ "fsra32", F3F(2, 0x36, 0x02f), F3F(~2, ~0x36, ~0x02f), "v,B,H", 0, HWCAP_SAPPHIRE, 0, r2000 }, #endif /* __duplicate_r2000__ */ { "pdistn", F3F(2, 0x36, 0x03f), F3F(~2, ~0x36, ~0x03f), "v,B,d", 0, HWCAP_VIS3, 0, v9d }, +#if __duplicate_r2000_plus__ +{ "pdistn", F3F(2, 0x36, 0x03f), F3F(~2, ~0x36, ~0x03f), "v,B,d", 0, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +#endif /* __duplicate_r2000_plus__ */ + { "fmean16", F3F(2, 0x36, 0x040), F3F(~2, ~0x36, ~0x040), "v,B,H", 0, HWCAP_VIS3, 0, v9d }, +#if __duplicate_r2000_plus__ +{ "fmean16", F3F(2, 0x36, 0x040), F3F(~2, ~0x36, ~0x040), "v,B,H", 0, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +#endif /* __duplicate_r2000_plus__ */ + { "fpadd64", F3F(2, 0x36, 0x042), F3F(~2, ~0x36, ~0x042), "v,B,H", 0, HWCAP_VIS3, HWCAP2_VIS3B, v9d }, +#if __duplicate_r2000_plus__ +{ "fpadd64", F3F(2, 0x36, 0x042), F3F(~2, ~0x36, ~0x042), "v,B,H", 0, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +#endif /* __duplicate_r2000_plus__ */ + { "fchksm16", F3F(2, 0x36, 0x044), F3F(~2, ~0x36, ~0x044), "v,B,H", 0, HWCAP_VIS3, 0, v9d }, +#if __duplicate_r2000_plus__ +{ "fchksm16", F3F(2, 0x36, 0x044), F3F(~2, ~0x36, ~0x044), "v,B,H", 0, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +#endif /* __duplicate_r2000_plus_ */ + { "fpsub64", F3F(2, 0x36, 0x046), F3F(~2, ~0x36, ~0x046), "v,B,H", 0, HWCAP_VIS3, HWCAP2_VIS3B, v9d }, +#if __duplicate_r2000_plus__ +{ "fpsub64", F3F(2, 0x36, 0x046), F3F(~2, ~0x36, ~0x046), "v,B,H", 0, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +#endif /* __duplicate_r2000_plus__ */ { "fpadds16", F3F(2, 0x36, 0x058), F3F(~2, ~0x36, ~0x058), "v,B,H", 0, HWCAP_VIS3, 0, v9d }, #if __duplicate_r2000__ -{ "fpadds16", F3F(2, 0x36, 0x058), F3F(~2, ~0x36, ~0x058), "v,B,H", 0, HWCAP_SAPPHIRE, 0, v9_mcst }, +{ "fpadds16", F3F(2, 0x36, 0x058), F3F(~2, ~0x36, ~0x058), "v,B,H", 0, HWCAP_SAPPHIRE, 0, r2000 }, #endif /* __duplicate_r2000__ */ { "fpadds16s", F3F(2, 0x36, 0x059), F3F(~2, ~0x36, ~0x059), "e,f,g", 0, HWCAP_VIS3, 0, v9d }, #if __duplicate_r2000__ -{ "fpadds16s", F3F(2, 0x36, 0x059), F3F(~2, ~0x36, ~0x059), "e,f,g", 0, HWCAP_SAPPHIRE, 0, v9_mcst }, +{ "fpadds16s", F3F(2, 0x36, 0x059), F3F(~2, ~0x36, ~0x059), "e,f,g", 0, HWCAP_SAPPHIRE, 0, r2000 }, #endif /* __duplicate_r2000__ */ { "fpadds32", F3F(2, 0x36, 0x05a), F3F(~2, ~0x36, ~0x05a), "v,B,H", 0, HWCAP_VIS3, 0, v9d }, #if __duplicate_r2000__ -{ "fpadds32", F3F(2, 0x36, 0x05a), F3F(~2, ~0x36, ~0x05a), "v,B,H", 0, HWCAP_SAPPHIRE, 0, v9_mcst }, +{ "fpadds32", F3F(2, 0x36, 0x05a), F3F(~2, ~0x36, ~0x05a), "v,B,H", 0, HWCAP_SAPPHIRE, 0, r2000 }, #endif /* __duplicate_r2000__ */ { "fpadds32s", F3F(2, 0x36, 0x05b), F3F(~2, ~0x36, ~0x05b), "e,f,g", 0, HWCAP_VIS3, 0, v9d }, #if __duplicate_r2000__ -{ "fpadds32s", F3F(2, 0x36, 0x05b), F3F(~2, ~0x36, ~0x05b), "e,f,g", 0, HWCAP_SAPPHIRE, 0, v9_mcst }, +{ "fpadds32s", F3F(2, 0x36, 0x05b), F3F(~2, ~0x36, ~0x05b), "e,f,g", 0, HWCAP_SAPPHIRE, 0, r2000 }, #endif /* __duplicate_r2000__ */ { "fpsubs16", F3F(2, 0x36, 0x05c), F3F(~2, ~0x36, ~0x05c), "v,B,H", 0, HWCAP_VIS3, 0, v9d }, #if __duplicate_r2000__ -{ "fpsubs16", F3F(2, 0x36, 0x05c), F3F(~2, ~0x36, ~0x05c), "v,B,H", 0, HWCAP_SAPPHIRE, 0, v9_mcst }, +{ "fpsubs16", F3F(2, 0x36, 0x05c), F3F(~2, ~0x36, ~0x05c), "v,B,H", 0, HWCAP_SAPPHIRE, 0, r2000 }, #endif /* __duplicate_r2000__ */ { "fpsubs16s", F3F(2, 0x36, 0x05d), F3F(~2, ~0x36, ~0x05d), "e,f,g", 0, HWCAP_VIS3, 0, v9d }, #if __duplicate_r2000__ -{ "fpsubs16s", F3F(2, 0x36, 0x05d), F3F(~2, ~0x36, ~0x05d), "e,f,g", 0, HWCAP_SAPPHIRE, 0, v9_mcst }, +{ "fpsubs16s", F3F(2, 0x36, 0x05d), F3F(~2, ~0x36, ~0x05d), "e,f,g", 0, HWCAP_SAPPHIRE, 0, r2000 }, #endif /* __duplicate_r2000__ */ { "fpsubs32", F3F(2, 0x36, 0x05e), F3F(~2, ~0x36, ~0x05e), "v,B,H", 0, HWCAP_VIS3, 0, v9d }, #if __duplicate_r2000__ -{ "fpsubs32", F3F(2, 0x36, 0x05e), F3F(~2, ~0x36, ~0x05e), "v,B,H", 0, HWCAP_SAPPHIRE, 0, v9_mcst }, +{ "fpsubs32", F3F(2, 0x36, 0x05e), F3F(~2, ~0x36, ~0x05e), "v,B,H", 0, HWCAP_SAPPHIRE, 0, r2000 }, #endif /* __duplicate_r2000__ */ { "fpsubs32s", F3F(2, 0x36, 0x05f), F3F(~2, ~0x36, ~0x05f), "e,f,g", 0, HWCAP_VIS3, 0, v9d }, #if __duplicate_r2000__ -{ "fpsubs32s", F3F(2, 0x36, 0x05f), F3F(~2, ~0x36, ~0x05f), "e,f,g", 0, HWCAP_SAPPHIRE, 0, v9_mcst }, +{ "fpsubs32s", F3F(2, 0x36, 0x05f), F3F(~2, ~0x36, ~0x05f), "e,f,g", 0, HWCAP_SAPPHIRE, 0, r2000 }, #endif /* __duplicate_r2000__ */ { "movdtox", F3F(2, 0x36, 0x110), F3F(~2, ~0x36, ~0x110), "B,d", F_FLOAT, HWCAP_VIS3, 0, v9d }, #if __duplicate_r2000__ -{ "movdtox", F3F(2, 0x36, 0x110), F3F(~2, ~0x36, ~0x110), "B,d", F_FLOAT, HWCAP_SAPPHIRE, 0, v9_mcst }, +{ "movdtox", F3F(2, 0x36, 0x110), F3F(~2, ~0x36, ~0x110), "B,d", F_FLOAT, HWCAP_SAPPHIRE, 0, r2000 }, #endif /* __duplicate_r2000__ */ { "movstouw", F3F(2, 0x36, 0x111), F3F(~2, ~0x36, ~0x111), "f,d", F_FLOAT, HWCAP_VIS3, 0, v9d }, #if __duplicate_r2000__ -{ "movstouw", F3F(2, 0x36, 0x111), F3F(~2, ~0x36, ~0x111), "f,d", F_FLOAT, HWCAP_SAPPHIRE, 0, v9_mcst }, +{ "movstouw", F3F(2, 0x36, 0x111), F3F(~2, ~0x36, ~0x111), "f,d", F_FLOAT, HWCAP_SAPPHIRE, 0, r2000 }, #endif /* __duplicate_r2000__ */ { "movstosw", F3F(2, 0x36, 0x113), F3F(~2, ~0x36, ~0x113), "f,d", F_FLOAT, HWCAP_VIS3, 0, v9d }, #if __duplicate_r2000__ -{ "movstosw", F3F(2, 0x36, 0x113), F3F(~2, ~0x36, ~0x113), "f,d", F_FLOAT, HWCAP_SAPPHIRE, 0, v9_mcst }, +{ "movstosw", F3F(2, 0x36, 0x113), F3F(~2, ~0x36, ~0x113), "f,d", F_FLOAT, HWCAP_SAPPHIRE, 0, r2000 }, #endif /* __duplicate_r2000__ */ { "movxtod", F3F(2, 0x36, 0x118), F3F(~2, ~0x36, ~0x118), "2,H", F_FLOAT, HWCAP_VIS3, 0, v9d }, #if __duplicate_r2000__ -{ "movxtod", F3F(2, 0x36, 0x118), F3F(~2, ~0x36, ~0x118), "2,H", F_FLOAT, HWCAP_SAPPHIRE, 0, v9_mcst }, +{ "movxtod", F3F(2, 0x36, 0x118), F3F(~2, ~0x36, ~0x118), "2,H", F_FLOAT, HWCAP_SAPPHIRE, 0, r2000 }, #endif /* __duplicate_r2000__ */ { "movwtos", F3F(2, 0x36, 0x119), F3F(~2, ~0x36, ~0x119), "2,g", F_FLOAT, HWCAP_VIS3, 0, v9d }, #if __duplicate_r2000__ -{ "movwtos", F3F(2, 0x36, 0x119), F3F(~2, ~0x36, ~0x119), "2,g", F_FLOAT, HWCAP_SAPPHIRE, 0, v9_mcst }, +{ "movwtos", F3F(2, 0x36, 0x119), F3F(~2, ~0x36, ~0x119), "2,g", F_FLOAT, HWCAP_SAPPHIRE, 0, r2000 }, #endif /* __duplicate_r2000__ */ { "xmulx", F3F(2, 0x36, 0x115), F3F(~2, ~0x36, ~0x115), "1,2,d", 0, HWCAP_VIS3, 0, v9d }, +#if __duplicate_r2000_plus__ +{ "xmulx", F3F(2, 0x36, 0x115), F3F(~2, ~0x36, ~0x115), "1,2,d", 0, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +#endif /*__duplicate_r2000_plus__ */ + { "xmulxhi", F3F(2, 0x36, 0x116), F3F(~2, ~0x36, ~0x116), "1,2,d", 0, HWCAP_VIS3, 0, v9d }, +#if __duplicate_r2000_plus__ +{ "xmulxhi", F3F(2, 0x36, 0x116), F3F(~2, ~0x36, ~0x116), "1,2,d", 0, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +#endif /*__duplicate_r2000_plus__ */ { "fpcmpule8", F3F(2, 0x36, 0x120), F3F(~2, ~0x36, ~0x120), "v,B,d", 0, HWCAP_VIS3, HWCAP2_VIS3B, v9d }, #if __duplicate_r2000__ -{ "fpcmpule8", F3F(2, 0x36, 0x120), F3F(~2, ~0x36, ~0x120), "v,B,d", 0, HWCAP_SAPPHIRE, 0, v9_mcst }, +{ "fpcmpule8", F3F(2, 0x36, 0x120), F3F(~2, ~0x36, ~0x120), "v,B,d", 0, HWCAP_SAPPHIRE, 0, r2000 }, #endif /* __duplicate_r2000__ */ { "fucmple8", F3F(2, 0x36, 0x120), F3F(~2, ~0x36, ~0x120), "v,B,d", F_ALIAS, HWCAP_VIS3, 0, v9d }, { "fpcmpune8", F3F(2, 0x36, 0x122), F3F(~2, ~0x36, ~0x122), "v,B,d", 0, HWCAP_VIS3, HWCAP2_VIS3B, v9d }, #if __duplicate_r2000__ -{ "fpcmpune8", F3F(2, 0x36, 0x122), F3F(~2, ~0x36, ~0x122), "v,B,d", 0, HWCAP_SAPPHIRE, 0, v9_mcst }, +{ "fpcmpune8", F3F(2, 0x36, 0x122), F3F(~2, ~0x36, ~0x122), "v,B,d", 0, HWCAP_SAPPHIRE, 0, r2000 }, #endif /* __duplicate_r2000__ */ { "fpcmpne8", F3F(2, 0x36, 0x122), F3F(~2, ~0x36, ~0x122), "v,B,d", F_PREF_ALIAS, HWCAP_VIS3, 0, v9d }, #if __duplicate_r2000__ -{ "fpcmpne8", F3F(2, 0x36, 0x122), F3F(~2, ~0x36, ~0x122), "v,B,d", F_PREF_ALIAS, HWCAP_SAPPHIRE, 0, v9_mcst }, +{ "fpcmpne8", F3F(2, 0x36, 0x122), F3F(~2, ~0x36, ~0x122), "v,B,d", F_PREF_ALIAS, HWCAP_SAPPHIRE, 0, r2000 }, #endif /* __duplicate_r2000__ */ { "fucmpne8", F3F(2, 0x36, 0x122), F3F(~2, ~0x36, ~0x122), "v,B,d", F_ALIAS, HWCAP_VIS3, 0, v9d }, { "fpcmpugt8", F3F(2, 0x36, 0x128), F3F(~2, ~0x36, ~0x128), "v,B,d", 0, HWCAP_VIS3, HWCAP2_VIS3B, v9d }, #if __duplicate_r2000__ -{ "fpcmpugt8", F3F(2, 0x36, 0x128), F3F(~2, ~0x36, ~0x128), "v,B,d", 0, HWCAP_SAPPHIRE, 0, v9_mcst }, +{ "fpcmpugt8", F3F(2, 0x36, 0x128), F3F(~2, ~0x36, ~0x128), "v,B,d", 0, HWCAP_SAPPHIRE, 0, r2000 }, #endif /* __duplicate_r2000__ */ { "fucmpgt8", F3F(2, 0x36, 0x128), F3F(~2, ~0x36, ~0x128), "v,B,d", F_ALIAS, HWCAP_VIS3, 0, v9d }, { "fpcmpueq8", F3F(2, 0x36, 0x12a), F3F(~2, ~0x36, ~0x12a), "v,B,d", 0, HWCAP_VIS3, HWCAP2_VIS3B, v9d }, #if __duplicate_r2000__ -{ "fpcmpueq8", F3F(2, 0x36, 0x12a), F3F(~2, ~0x36, ~0x12a), "v,B,d", 0, HWCAP_SAPPHIRE, 0, v9_mcst }, +{ "fpcmpueq8", F3F(2, 0x36, 0x12a), F3F(~2, ~0x36, ~0x12a), "v,B,d", 0, HWCAP_SAPPHIRE, 0, r2000 }, #endif /* __duplicate_r2000__ */ { "fpcmpeq8", F3F(2, 0x36, 0x12a), F3F(~2, ~0x36, ~0x12a), "v,B,d", F_PREF_ALIAS, HWCAP_VIS3, 0, v9d }, #if __duplicate_r2000__ -{ "fpcmpeq8", F3F(2, 0x36, 0x12a), F3F(~2, ~0x36, ~0x12a), "v,B,d", F_PREF_ALIAS, HWCAP_SAPPHIRE, 0, v9_mcst }, +{ "fpcmpeq8", F3F(2, 0x36, 0x12a), F3F(~2, ~0x36, ~0x12a), "v,B,d", F_PREF_ALIAS, HWCAP_SAPPHIRE, 0, r2000 }, #endif /* __duplicate_r2000__ */ +{ "fpcsl32", F3F(2, 0x36, 0x108), F3F(~2, ~0x36, ~0x108), "v,B,H", 0, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +{ "fpcsl64", F3F(2, 0x36, 0x109), F3F(~2, ~0x36, ~0x109), "v,B,H", 0, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +{ "fpcsr32", F3F(2, 0x36, 0x10a), F3F(~2, ~0x36, ~0x10a), "v,B,H", 0, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +{ "fpcsr64", F3F(2, 0x36, 0x10b), F3F(~2, ~0x36, ~0x10b), "v,B,H", 0, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, + + { "fucmpeq8", F3F(2, 0x36, 0x12a), F3F(~2, ~0x36, ~0x12a), "v,B,d", F_ALIAS, HWCAP_VIS3, 0, v9d }, {"aes_kexpand0",F3F(2, 0x36, 0x130), F3F(~2, ~0x36, ~0x130), "v,B,H", F_FLOAT, HWCAP_AES, 0, v9e }, {"aes_kexpand2",F3F(2, 0x36, 0x131), F3F(~2, ~0x36, ~0x131), "v,B,H", F_FLOAT, HWCAP_AES, 0, v9e }, @@ -2422,14 +2474,46 @@ SLCBCC("cbnefr", 15), {"kasumi_fl_xor", F3F4(2, 0x19, 10), F3F4(~2, ~0x19, ~10), "v,B,5,H", F_FLOAT, HWCAP_KASUMI, 0, v9e }, {"kasumi_fi_xor", F3F4(2, 0x19, 11), F3F4(~2, ~0x19, ~11), "v,B,5,H", F_FLOAT, HWCAP_KASUMI, 0, v9e }, {"camellia_f", F3F4(2, 0x19, 12), F3F4(~2, ~0x19, ~12), "v,B,5,H", F_FLOAT, HWCAP_CAMELLIA, 0, v9e }, + { "flcmps", CMPFCC(0)|F3F(2, 0x36, 0x151), CMPFCC(~0)|F3F(~2, ~0x36, ~0x151), "6,e,f", F_FLOAT, HWCAP_HPC, 0, v9d }, +#if __duplicate_r2000_plus__ +{ "flcmps", CMPFCC(0)|F3F(2, 0x36, 0x151), CMPFCC(~0)|F3F(~2, ~0x36, ~0x151), "6,e,f", F_FLOAT, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +#endif /* __duplicate_r2000_plus__ */ + { "flcmps", CMPFCC(1)|F3F(2, 0x36, 0x151), CMPFCC(~1)|F3F(~2, ~0x36, ~0x151), "7,e,f", F_FLOAT, HWCAP_HPC, 0, v9d }, +#if __duplicate_r2000_plus__ +{ "flcmps", CMPFCC(1)|F3F(2, 0x36, 0x151), CMPFCC(~1)|F3F(~2, ~0x36, ~0x151), "7,e,f", F_FLOAT, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +#endif /* __duplicate_r2000_plus__ */ + { "flcmps", CMPFCC(2)|F3F(2, 0x36, 0x151), CMPFCC(~2)|F3F(~2, ~0x36, ~0x151), "8,e,f", F_FLOAT, HWCAP_HPC, 0, v9d }, +#if __duplicate_r2000_plus__ +{ "flcmps", CMPFCC(2)|F3F(2, 0x36, 0x151), CMPFCC(~2)|F3F(~2, ~0x36, ~0x151), "8,e,f", F_FLOAT, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +#endif /* __duplicate_r2000_plus__ */ + { "flcmps", CMPFCC(3)|F3F(2, 0x36, 0x151), CMPFCC(~3)|F3F(~2, ~0x36, ~0x151), "9,e,f", F_FLOAT, HWCAP_HPC, 0, v9d }, +#if __duplicate_r2000_plus__ +{ "flcmps", CMPFCC(3)|F3F(2, 0x36, 0x151), CMPFCC(~3)|F3F(~2, ~0x36, ~0x151), "9,e,f", F_FLOAT, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +#endif /* __duplicate_r2000_plus__ */ + { "flcmpd", CMPFCC(0)|F3F(2, 0x36, 0x152), CMPFCC(~0)|F3F(~2, ~0x36, ~0x152), "6,v,B", F_FLOAT, HWCAP_HPC, 0, v9d }, +#if __duplicate_r2000_plus__ +{ "flcmpd", CMPFCC(0)|F3F(2, 0x36, 0x152), CMPFCC(~0)|F3F(~2, ~0x36, ~0x152), "6,v,B", F_FLOAT, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +#endif /* __duplicate_r2000_plus__ */ + { "flcmpd", CMPFCC(1)|F3F(2, 0x36, 0x152), CMPFCC(~1)|F3F(~2, ~0x36, ~0x152), "7,v,B", F_FLOAT, HWCAP_HPC, 0, v9d }, +#if __duplicate_r2000_plus__ +{ "flcmpd", CMPFCC(1)|F3F(2, 0x36, 0x152), CMPFCC(~1)|F3F(~2, ~0x36, ~0x152), "7,v,B", F_FLOAT, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +#endif /* __duplicate_r2000_plus__ */ + { "flcmpd", CMPFCC(2)|F3F(2, 0x36, 0x152), CMPFCC(~2)|F3F(~2, ~0x36, ~0x152), "8,v,B", F_FLOAT, HWCAP_HPC, 0, v9d }, +#if __duplicate_r2000_plus__ +{ "flcmpd", CMPFCC(2)|F3F(2, 0x36, 0x152), CMPFCC(~2)|F3F(~2, ~0x36, ~0x152), "8,v,B", F_FLOAT, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +#endif /* __duplicate_r2000_plus__ */ + { "flcmpd", CMPFCC(3)|F3F(2, 0x36, 0x152), CMPFCC(~3)|F3F(~2, ~0x36, ~0x152), "9,v,B", F_FLOAT, HWCAP_HPC, 0, v9d }, +#if __duplicate_r2000_plus__ +{ "flcmpd", CMPFCC(3)|F3F(2, 0x36, 0x152), CMPFCC(~3)|F3F(~2, ~0x36, ~0x152), "9,v,B", F_FLOAT, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +#endif /* __duplicate_r2000_plus__ */ { "mwait", F3(2, 0x30, 0)|RD(28), F3(~2, ~0x30, ~0)|RD(~28)|RS1_G0|ASI(~0), "2", 0, 0, HWCAP2_MWAIT, v9m }, /* mwait r */ { "mwait", F3(2, 0x30, 1)|RD(28), F3(~2, ~0x30, ~1)|RD(~28)|RS1_G0, "i", 0, 0, HWCAP2_MWAIT, v9m }, /* mwait imm */ @@ -2440,31 +2524,136 @@ SLCBCC("cbnefr", 15), { "subxccc", F3(2, 0x36, 0)|OPF(0x43), F3(~2, ~0x36, ~0)|OPF(~0x43), "1,2,d", 0, 0, HWCAP2_SPARC5, v9m }, { "fpadd8", F3F(2, 0x36, 0x124), F3F(~2, ~0x36, ~0x124), "v,B,H", 0, 0, HWCAP2_SPARC5, v9m }, +#if __duplicate_r2000_plus__ +{ "fpadd8", F3F(2, 0x36, 0x124), F3F(~2, ~0x36, ~0x124), "v,B,H", 0, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +#endif /* __duplicate_r2000_plus__ */ + { "fpadds8", F3F(2, 0x36, 0x126), F3F(~2, ~0x36, ~0x126), "v,B,H", 0, 0, HWCAP2_SPARC5, v9m }, +#if __duplicate_r2000_plus__ +{ "fpadds8", F3F(2, 0x36, 0x126), F3F(~2, ~0x36, ~0x126), "v,B,H", 0, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +#endif /* __duplicate_r2000_plus__ */ + { "fpaddus8", F3F(2, 0x36, 0x127), F3F(~2, ~0x36, ~0x127), "v,B,H", 0, 0, HWCAP2_SPARC5, v9m }, +#if __duplicate_r2000_plus__ +{ "fpaddus8", F3F(2, 0x36, 0x127), F3F(~2, ~0x36, ~0x127), "v,B,H", 0, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +#endif /* __duplicate_r2000_plus__ */ + { "fpaddus16", F3F(2, 0x36, 0x123), F3F(~2, ~0x36, ~0x123), "v,B,H", 0, 0, HWCAP2_SPARC5, v9m }, +#if __duplicate_r2000_plus__ +{ "fpaddus16", F3F(2, 0x36, 0x123), F3F(~2, ~0x36, ~0x123), "v,B,H", 0, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +#endif /* __duplicate_r2000_plus__ */ + { "fpcmple8", F3F(2, 0x36, 0x034), F3F(~2, ~0x36, ~0x034), "v,B,d", 0, 0, HWCAP2_SPARC5, v9m }, +#if __duplicate_r2000_plus__ +{ "fpcmple8", F3F(2, 0x36, 0x034), F3F(~2, ~0x36, ~0x034), "v,B,d", 0, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +#endif /* __duplicate_r2000_plus__ */ + { "fpcmpgt8", F3F(2, 0x36, 0x03c), F3F(~2, ~0x36, ~0x03c), "v,B,d", 0, 0, HWCAP2_SPARC5, v9m }, +#if __duplicate_r2000_plus__ +{ "fpcmpgt8", F3F(2, 0x36, 0x03c), F3F(~2, ~0x36, ~0x03c), "v,B,d", 0, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +#endif /* __duplicate_r2000_plus__ */ + { "fpcmpule16", F3F(2, 0x36, 0x12e), F3F(~2, ~0x36, ~0x12e), "v,B,d", 0, 0, HWCAP2_SPARC5, v9m }, +#if __duplicate_r2000_plus__ +{ "fpcmpule16", F3F(2, 0x36, 0x12e), F3F(~2, ~0x36, ~0x12e), "v,B,d", 0, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +#endif /* __duplicate_r2000_plus__ */ + { "fpcmpugt16", F3F(2, 0x36, 0x12b), F3F(~2, ~0x36, ~0x12b), "v,B,d", 0, 0, HWCAP2_SPARC5, v9m }, +#if __duplicate_r2000_plus__ +{ "fpcmpugt16", F3F(2, 0x36, 0x12b), F3F(~2, ~0x36, ~0x12b), "v,B,d", 0, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +#endif /* __duplicate_r2000_plus__ */ + { "fpcmpule32", F3F(2, 0x36, 0x12f), F3F(~2, ~0x36, ~0x12f), "v,B,d", 0, 0, HWCAP2_SPARC5, v9m }, +#if __duplicate_r2000_plus__ +{ "fpcmpule32", F3F(2, 0x36, 0x12f), F3F(~2, ~0x36, ~0x12f), "v,B,d", 0, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +#endif /* __duplicate_r2000_plus__ */ + { "fpcmpugt32", F3F(2, 0x36, 0x12c), F3F(~2, ~0x36, ~0x12c), "v,B,d", 0, 0, HWCAP2_SPARC5, v9m }, +#if __duplicate_r2000_plus__ +{ "fpcmpugt32", F3F(2, 0x36, 0x12c), F3F(~2, ~0x36, ~0x12c), "v,B,d", 0, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +#endif /* __duplicate_r2000_plus__ */ + { "fpmax8", F3F(2, 0x36, 0x11d), F3F(~2, ~0x36, ~0x11d), "v,B,H", 0, 0, HWCAP2_SPARC5, v9m }, +#if __duplicate_r2000_plus__ +{ "fpmax8", F3F(2, 0x36, 0x11d), F3F(~2, ~0x36, ~0x11d), "v,B,H", 0, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +#endif /* __duplicate_r2000_plus__ */ + { "fpmax16", F3F(2, 0x36, 0x11e), F3F(~2, ~0x36, ~0x11e), "v,B,H", 0, 0, HWCAP2_SPARC5, v9m }, +#if __duplicate_r2000_plus__ +{ "fpmax16", F3F(2, 0x36, 0x11e), F3F(~2, ~0x36, ~0x11e), "v,B,H", 0, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +#endif /* __duplicate_r2000_plus__ */ + { "fpmax32", F3F(2, 0x36, 0x11f), F3F(~2, ~0x36, ~0x11f), "v,B,H", 0, 0, HWCAP2_SPARC5, v9m }, +#if __duplicate_r2000_plus__ +{ "fpmax32", F3F(2, 0x36, 0x11f), F3F(~2, ~0x36, ~0x11f), "v,B,H", 0, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +#endif /* __duplicate_r2000_plus__ */ + { "fpmaxu8", F3F(2, 0x36, 0x15d), F3F(~2, ~0x36, ~0x15d), "v,B,H", 0, 0, HWCAP2_SPARC5, v9m }, +#if __duplicate_r2000_plus__ +{ "fpmaxu8", F3F(2, 0x36, 0x15d), F3F(~2, ~0x36, ~0x15d), "v,B,H", 0, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +#endif /* __duplicate_r2000_plus__ */ + { "fpmaxu16", F3F(2, 0x36, 0x15e), F3F(~2, ~0x36, ~0x15e), "v,B,H", 0, 0, HWCAP2_SPARC5, v9m }, +#if __duplicate_r2000_plus__ +{ "fpmaxu16", F3F(2, 0x36, 0x15e), F3F(~2, ~0x36, ~0x15e), "v,B,H", 0, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +#endif /* __duplicate_r2000_plus__ */ + { "fpmaxu32", F3F(2, 0x36, 0x15f), F3F(~2, ~0x36, ~0x15f), "v,B,H", 0, 0, HWCAP2_SPARC5, v9m }, +#if __duplicate_r2000_plus__ +{ "fpmaxu32", F3F(2, 0x36, 0x15f), F3F(~2, ~0x36, ~0x15f), "v,B,H", 0, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +#endif /* __duplicate_r2000_plus__ */ + { "fpmin8", F3F(2, 0x36, 0x11a), F3F(~2, ~0x36, ~0x11a), "v,B,H", 0, 0, HWCAP2_SPARC5, v9m }, +#if __duplicate_r2000_plus__ +{ "fpmin8", F3F(2, 0x36, 0x11a), F3F(~2, ~0x36, ~0x11a), "v,B,H", 0, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +#endif /* __duplicate_r2000_plus__ */ + { "fpmin16", F3F(2, 0x36, 0x11b), F3F(~2, ~0x36, ~0x11b), "v,B,H", 0, 0, HWCAP2_SPARC5, v9m }, +#if __duplicate_r2000_plus__ +{ "fpmin16", F3F(2, 0x36, 0x11b), F3F(~2, ~0x36, ~0x11b), "v,B,H", 0, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +#endif /* __duplicate_r2000_plus__ */ + { "fpmin32", F3F(2, 0x36, 0x11c), F3F(~2, ~0x36, ~0x11c), "v,B,H", 0, 0, HWCAP2_SPARC5, v9m }, +#if __duplicate_r2000_plus__ +{ "fpmin32", F3F(2, 0x36, 0x11c), F3F(~2, ~0x36, ~0x11c), "v,B,H", 0, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +#endif /* __duplicate_r2000_plus__ */ + { "fpminu8", F3F(2, 0x36, 0x15a), F3F(~2, ~0x36, ~0x15a), "v,B,H", 0, 0, HWCAP2_SPARC5, v9m }, +#if __duplicate_r2000_plus__ +{ "fpminu8", F3F(2, 0x36, 0x15a), F3F(~2, ~0x36, ~0x15a), "v,B,H", 0, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +#endif /* __duplicate_r2000_plus__ */ + { "fpminu16", F3F(2, 0x36, 0x15b), F3F(~2, ~0x36, ~0x15b), "v,B,H", 0, 0, HWCAP2_SPARC5, v9m }, +#if __duplicate_r2000_plus__ +{ "fpminu16", F3F(2, 0x36, 0x15b), F3F(~2, ~0x36, ~0x15b), "v,B,H", 0, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +#endif /* __duplicate_r2000_plus__ */ + { "fpminu32", F3F(2, 0x36, 0x15c), F3F(~2, ~0x36, ~0x15c), "v,B,H", 0, 0, HWCAP2_SPARC5, v9m }, +#if __duplicate_r2000_plus__ +{ "fpminu32", F3F(2, 0x36, 0x15c), F3F(~2, ~0x36, ~0x15c), "v,B,H", 0, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +#endif /* __duplicate_r2000_plus__ */ + + { "fpsub8", F3F(2, 0x36, 0x154), F3F(~2, ~0x36, ~0x154), "v,B,H", 0, 0, HWCAP2_SPARC5, v9m }, +#if __duplicate_r2000_plus__ +{ "fpsub8", F3F(2, 0x36, 0x154), F3F(~2, ~0x36, ~0x154), "v,B,H", 0, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +#endif /* __duplicate_r2000_plus__ */ + { "fpsubs8", F3F(2, 0x36, 0x156), F3F(~2, ~0x36, ~0x156), "v,B,H", 0, 0, HWCAP2_SPARC5, v9m }, +#if __duplicate_r2000_plus__ +{ "fpsubs8", F3F(2, 0x36, 0x156), F3F(~2, ~0x36, ~0x156), "v,B,H", 0, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +#endif /* __duplicate_r2000_plus__ */ + + { "fpsubus8", F3F(2, 0x36, 0x157), F3F(~2, ~0x36, ~0x157), "v,B,H", 0, 0, HWCAP2_SPARC5, v9m }, +#if __duplicate_r2000_plus__ +{ "fpsubus8", F3F(2, 0x36, 0x157), F3F(~2, ~0x36, ~0x157), "v,B,H", 0, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +#endif /* __duplicate_r2000_plus__ */ + { "fpsubus16", F3F(2, 0x36, 0x153), F3F(~2, ~0x36, ~0x153), "v,B,H", 0, 0, HWCAP2_SPARC5, v9m }, +#if __duplicate_r2000_plus__ +{ "fpsubus16", F3F(2, 0x36, 0x153), F3F(~2, ~0x36, ~0x153), "v,B,H", 0, HWCAP_SAPPHIRE, HWCAP2_SAPPHIRE_PLUS, r2000_plus }, +#endif /* __duplicate_r2000_plus__ */ /* Other OSA2017 and M8 instructions. */ @@ -2647,17 +2836,17 @@ IMPDEP ("impdep2", 0x37), #define F5(op, op3, var, size) (OP (op) | OP3(op3) | VAR(var) | SIZE(size)) /* Packed operations for MCST-4R. */ -{ "pfmadds", F5(2, 0x37, 0, 0), F5(~2, ~0x37, ~0, ~0), "v,B,5,H", 0, HWCAP_R1000, 0, v9_mcst}, -{ "pfmsubs", F5(2, 0x37, 1, 0), F5(~2, ~0x37, ~1, ~0), "v,B,5,H", 0, HWCAP_R1000, 0, v9_mcst}, -{ "pfnmadds", F5(2, 0x37, 3, 0), F5(~2, ~0x37, ~3, ~0), "v,B,5,H", 0, HWCAP_R1000, 0, v9_mcst}, -{ "pfnmsubs", F5(2, 0x37, 2, 0), F5(~2, ~0x37, ~2, ~0), "v,B,5,H", 0, HWCAP_R1000, 0, v9_mcst}, +{ "pfmadds", F5(2, 0x37, 0, 0), F5(~2, ~0x37, ~0, ~0), "v,B,5,H", 0, HWCAP_R1000, 0, r1000}, +{ "pfmsubs", F5(2, 0x37, 1, 0), F5(~2, ~0x37, ~1, ~0), "v,B,5,H", 0, HWCAP_R1000, 0, r1000}, +{ "pfnmadds", F5(2, 0x37, 3, 0), F5(~2, ~0x37, ~3, ~0), "v,B,5,H", 0, HWCAP_R1000, 0, r1000}, +{ "pfnmsubs", F5(2, 0x37, 2, 0), F5(~2, ~0x37, ~2, ~0), "v,B,5,H", 0, HWCAP_R1000, 0, r1000}, #undef F5 #undef SIZE #undef VAR /* A single original R2000 instruction developed at MCST. */ -{ "fmerge32", F3F(2, 0x34, 0x6a), F3F(~2, ~0x34, ~0x6a), "e,f,H", F_FLOAT, HWCAP_SAPPHIRE, 0, v9_mcst }, +{ "fmerge32", F3F(2, 0x34, 0x6a), F3F(~2, ~0x34, ~0x6a), "e,f,H", F_FLOAT, HWCAP_SAPPHIRE, 0, r1000 }, };