From 9fc0b501af78bc4a92f53ec712e1aaa123e0224c Mon Sep 17 00:00:00 2001 From: Sergey Belyashov Date: Fri, 7 Feb 2020 14:53:46 +0000 Subject: Add support for the GBZ80 and Z80N variants of the Z80 architecture, and add DWARF debug info support to the Z80 assembler. PR 25469 bfd * archures.c: Add GBZ80 and Z80N machine values. * reloc.c: Add BFD_RELOC_Z80_16_BE. * coff-z80.c: Add support for new reloc. * coffcode.h: Add support for new machine values. * cpu-z80.c: Add support for new machine names. * elf32-z80.c: Add support for new reloc. * bfd-in2.h: Regenerate. * libbfd.h: Regenerate. binutils* readelf.c (get_machine_flags): Add support for Z80N machine number. gas * config/tc-z80.c: Add -gbz80 command line option to generate code for the GameBoy Z80. Add support for generating DWARF. * config/tc-z80.h: Add support for DWARF debug information generation. * doc/c-z80.texi: Document new command line option. * testsuite/gas/z80/gbz80_all.d: New file. * testsuite/gas/z80/gbz80_all.s: New file. * testsuite/gas/z80/z80.exp: Run the new tests. * testsuite/gas/z80/z80n_all.d: New file. * testsuite/gas/z80/z80n_all.s: New file. * testsuite/gas/z80/z80n_reloc.d: New file. include * coff/internal.h (R_IMM16BE): Define. * elf/z80.h (EF_Z80_MACH_Z80N): Define. (R_Z80_16_BE): New reloc. ld * emulparams/elf32z80.sh: Use z80 emulation. * emultempl/z80.em: Make generic to both COFF and ELF Z80 emulations. * emultempl/z80elf.em: Delete. * testsuite/ld-elf/pr22450.d: Expect to fail for the Z80. * testsuite/ld-elf/sec64k.exp: Fix Z80 assembly. * testsuite/ld-unique/pr21529.s: Avoid register name conflict. * testsuite/ld-unique/unique.s: Likewise. * testsuite/ld-unique/unique_empty.s: Likewise. * testsuite/ld-unique/unique_shared.s: Likewise. * testsuite/ld-unique/unique.d: Updated expected output. * testsuite/ld-z80/arch_z80n.d: New file. * testsuite/ld-z80/comb_arch_z80_z80n.d: New file. * testsuite/ld-z80/labels.s: Add more labels. * testsuite/ld-z80/relocs.s: Add more reloc tests. * testsuite/ld-z80/relocs_f_z80n.d: New file opcodes * z80-dis.c: Add support for GBZ80 opcodes. --- ld/emultempl/z80.em | 215 +++++++++++++++++++++++++------------------------ ld/emultempl/z80elf.em | 133 ------------------------------ 2 files changed, 111 insertions(+), 237 deletions(-) delete mode 100644 ld/emultempl/z80elf.em (limited to 'ld/emultempl') diff --git a/ld/emultempl/z80.em b/ld/emultempl/z80.em index 4c36cd8..81385e7 100644 --- a/ld/emultempl/z80.em +++ b/ld/emultempl/z80.em @@ -19,129 +19,136 @@ # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, # MA 02110-1301, USA. -LDEMUL_BEFORE_PARSE=gldz80_before_parse -LDEMUL_RECOGNIZED_FILE=gldz80_recognized_file -LDEMUL_AFTER_OPEN=gldz80_after_open - fragment <the_bfd); - switch (mach_type) - { - case bfd_mach_z80strict: - result_mach_type |= M_Z80STRICT; - break; - case bfd_mach_z80: - result_mach_type |= M_Z80; - break; - case bfd_mach_z80full: - result_mach_type |= M_Z80FULL; - break; - case bfd_mach_r800: - result_mach_type |= M_R800; - break; - case bfd_mach_gbz80: - result_mach_type |= M_GBZ80; - break; - case bfd_mach_z180: - result_mach_type |= M_Z180; - break; - case bfd_mach_ez80_z80: - result_mach_type |= M_EZ80_Z80; - break; - case bfd_mach_ez80_adl: - result_mach_type |= M_EZ80_ADL; - break; - default: - einfo (_("%P: warning: unknown machine type %u"), (unsigned)mach_type); - result_mach_type |= M_Z80ANY; - } - return FALSE; + eflags &= EF_Z80_MACH_MSK; + p = &z80_mach_info[0]; + e = &z80_mach_info[sizeof(z80_mach_info)/sizeof(*z80_mach_info)]; + for (; p != e; ++p) + if (eflags == p->eflags) + return p; + return NULL; +}*/ + +static const struct z80_mach_info * +z80_mach_info_by_mach (unsigned int bfd_mach) +{ + const struct z80_mach_info *p; + const struct z80_mach_info *e; + + p = &z80_mach_info[0]; + e = &z80_mach_info[sizeof(z80_mach_info)/sizeof(*z80_mach_info)]; + for (; p != e; ++p) + if (bfd_mach == p->bfd_mach) + return p; + return NULL; +} + +static const struct z80_mach_info * +z80_combine_mach (const struct z80_mach_info *m1, + const struct z80_mach_info *m2) +{ + int i; + int mach; + if (m1->compat != NULL) + for (i = 0; (mach = m1->compat[i]) >= 0; ++i) + if ((unsigned)mach == m2->bfd_mach) + return m1; + if (m2->compat != NULL) + for (i = 0; (mach = m2->compat[i]) >= 0; ++i) + if ((unsigned)mach == m1->bfd_mach) + return m2; + /* incompatible mach */ + return NULL; } /* Set the machine type of the output file based on result_mach_type. */ static void -gldz80_after_open (void) +z80_after_open (void) { - unsigned long mach_type; + const struct z80_mach_info *mach = NULL; + bfd *abfd; - after_open_default (); - - switch (result_mach_type & M_ARCH_MASK) + /* For now, make sure all object files are of the same architecture. + We may try to merge object files with different architecture together. */ + for (abfd = link_info.input_bfds; abfd != NULL; abfd = abfd->link.next) { - case M_Z80 & M_ARCH_MASK: - case M_R800: - case M_Z180: - case M_GBZ80: - case M_EZ80_Z80: - case M_EZ80_ADL: - case M_EZ80_Z80 | M_Z180: - /* valid combination */ - break; - case M_EZ80_Z80 | M_EZ80_ADL: - case M_EZ80_Z80 | M_EZ80_ADL | M_Z180: - case M_EZ80_ADL | M_Z180: - /* combination may cause invalid objdump output */ - /* but it is possible for mixed ADL/Z80 code */ - einfo (_("%P: warning: mixing ADL and Z80 mode binaries, objdump may generate invalid output")); - break; - default: - /* invalid combination: for example Z180 + R800 */ - einfo (_("%P: warning: incompatible object files linked, result code might not work")); + const struct z80_mach_info *new_mach; + /*new_mach = z80_mach_info_by_eflags (elf_elfheader (abfd)->e_flags);*/ + new_mach = z80_mach_info_by_mach(bfd_get_mach (abfd)); + if (mach == NULL) + mach = new_mach; + else if (mach != new_mach) + mach = z80_combine_mach (mach, new_mach); + if (mach == NULL) + einfo (_("%F%P: %pB: Instruction sets of object files incompatible\n"), + abfd); + } + if (mach != NULL) + { + bfd_set_arch_mach (link_info.output_bfd, bfd_arch_z80, mach->bfd_mach); + result_mach_type = mach->bfd_mach; } - - if ((result_mach_type & M_EZ80_ADL) == M_EZ80_ADL) - mach_type = bfd_mach_ez80_adl; - else if ((result_mach_type & M_EZ80_Z80) == M_EZ80_Z80) - mach_type = bfd_mach_ez80_z80; - else if ((result_mach_type & M_Z180) == M_Z180) - mach_type = bfd_mach_z180; - else if ((result_mach_type & M_R800) == M_R800) - mach_type = bfd_mach_r800; - else if ((result_mach_type & M_GBZ80) == M_GBZ80) - mach_type = bfd_mach_gbz80; - else if ((result_mach_type & M_Z80FULL) == M_Z80FULL) - mach_type = bfd_mach_z80full; /* TODO: remove it */ - else if ((result_mach_type & M_Z80) == M_Z80) - mach_type = bfd_mach_z80; - else if ((result_mach_type & M_Z80STRICT) == M_Z80STRICT) - mach_type = bfd_mach_z80strict; /* TODO: remove this */ else - mach_type = bfd_arch_unknown; + einfo (_("%F%P: %pB: Unknown machine type\n"), + abfd); - bfd_set_arch_mach (link_info.output_bfd, bfd_arch_z80, mach_type); + /* Call the standard elf routine. */ + gld${EMULATION_NAME}_after_open (); } + +#ifndef TARGET_IS_elf32z80 +static void +gld${EMULATION_NAME}_after_open (void) +{ +} +#endif + /* --- \end{z80.em} */ EOF + +LDEMUL_AFTER_OPEN=z80_after_open diff --git a/ld/emultempl/z80elf.em b/ld/emultempl/z80elf.em deleted file mode 100644 index 4b03e79..0000000 --- a/ld/emultempl/z80elf.em +++ /dev/null @@ -1,133 +0,0 @@ -# This shell script emits C code -*- C -*- -# to keep track of the machine type of Z80 object files -# It does some substitutions. -# Copyright (C) 2005-2019 Free Software Foundation, Inc. -# This file is part of the GNU Binutils. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, -# MA 02110-1301, USA. - -fragment <link.next) - { - unsigned long new_mach; - new_mach = elf_elfheader (abfd)->e_flags & 0xff; - if (!mach) - mach = new_mach; - else if (mach != new_mach) - { - if ((new_mach == EF_Z80_MACH_R800 || mach == EF_Z80_MACH_R800) || - (new_mach == EF_Z80_MACH_GBZ80 || mach == EF_Z80_MACH_GBZ80)) - einfo (_("%F%P: %pB: Instruction set of object files mismatched\n"), - abfd); - else if (mach < new_mach) - mach = new_mach; - } - } - switch (mach & 0xff) - { - case EF_Z80_MACH_Z80: - mach = bfd_mach_z80; - break; - case EF_Z80_MACH_Z180: - mach = bfd_mach_z180; - break; - case EF_Z80_MACH_R800: - mach = bfd_mach_r800; - break; - case EF_Z80_MACH_EZ80_Z80: - mach = bfd_mach_ez80_z80; - break; - case EF_Z80_MACH_EZ80_ADL: - mach = bfd_mach_ez80_adl; - break; - case EF_Z80_MACH_GBZ80: - mach = bfd_mach_gbz80; - break; - default: - mach = (unsigned)-1; - } - - bfd_set_arch_mach (link_info.output_bfd, bfd_arch_z80, mach); - result_mach_type = mach; - - /* Call the standard elf routine. */ - gld${EMULATION_NAME}_after_open (); -} - -static void -z80_elf_finish (void) -{ - bfd *abfd; - - abfd = link_info.output_bfd; - - if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) - { - unsigned e_flags; - switch (result_mach_type) - { - case bfd_mach_z80strict: - case bfd_mach_z80: - case bfd_mach_z80full: - e_flags = EF_Z80_MACH_Z80; - break; - case bfd_mach_r800: - e_flags = EF_Z80_MACH_R800; - break; - case bfd_mach_gbz80: - e_flags = EF_Z80_MACH_GBZ80; - break; - case bfd_mach_z180: - e_flags = EF_Z80_MACH_Z180; - break; - case bfd_mach_ez80_z80: - e_flags = EF_Z80_MACH_EZ80_Z80; - break; - case bfd_mach_ez80_adl: - e_flags = EF_Z80_MACH_EZ80_ADL; - break; - default: - e_flags = ~0; - } - elf_elfheader (abfd)->e_flags = (elf_elfheader (abfd)->e_flags & ~0xff) | e_flags; - } - - finish_default (); -} - -/* --- \end{z80.em} */ -EOF - -LDEMUL_AFTER_OPEN=z80_elf_after_open -LDEMUL_FINISH=z80_elf_finish -- cgit v1.1