]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - ld/emultempl/z80.em
Add support for the GBZ80 and Z80N variants of the Z80 architecture, and add DWARF...
[thirdparty/binutils-gdb.git] / ld / emultempl / z80.em
index 4c36cd8465ebd46faaef06c53619de8c703788d6..81385e7433fc57c2ba24796aebb0edfa803352db 100644 (file)
 # 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 <<EOF
 /* --- \begin{z80.em} */
-/* Codes for machine types, bitwise or gives the code to use for the
-   output.  */
-#define M_Z80STRICT 0x01
-#define M_Z80       0x03
-#define M_Z80FULL   0x07
-#define M_R800      0x10
-#define M_Z80ANY    0x0f
-#define M_GBZ80     0x20
-#define M_Z180      0x40
-#define M_EZ80_Z80  0x80
-#define M_EZ80_ADL  0x100
-#define M_ARCH_MASK 0xFF0
-
-/* Bitwise or of the machine types seen so far.  */
-static int result_mach_type;
+
+#include "elf/z80.h"
 
 static void
-${LDEMUL_BEFORE_PARSE} (void)
+gld${EMULATION_NAME}_after_open (void);
+
+static int result_mach_type;
+
+struct z80_mach_info
 {
-#ifndef TARGET_                        /* I.e., if not generic.  */
-  ldfile_set_output_arch ("`echo ${ARCH}`", bfd_arch_unknown);
-#endif /* not TARGET_ */
-  result_mach_type = 0;
-}
+  unsigned eflags;
+  unsigned bfd_mach;
+  const int *compat; /* back compatible machines */
+};
 
+static const int
+back_compat_z80[] = {bfd_mach_z80, -1};
 
-/* Update result_mach_type.  */
-static bfd_boolean
-${LDEMUL_RECOGNIZED_FILE} (lang_input_statement_type *entry)
+static const int
+back_compat_z180[] = {bfd_mach_z180, bfd_mach_z80, -1};
+
+static const int
+back_compat_ez80[] = {bfd_mach_ez80_z80, bfd_mach_z180, bfd_mach_z80, -1};
+
+static const struct z80_mach_info
+z80_mach_info[] =
 {
-  unsigned long mach_type;
+  { EF_Z80_MACH_Z80,      bfd_mach_z80,       NULL },
+  { EF_Z80_MACH_Z80,      bfd_mach_z80strict, back_compat_z80 },
+  { EF_Z80_MACH_Z80,      bfd_mach_z80full,   back_compat_z80 },
+  { EF_Z80_MACH_Z180,     bfd_mach_z180,      back_compat_z80 },
+  { EF_Z80_MACH_EZ80_Z80, bfd_mach_ez80_z80,  back_compat_z180 },
+  { EF_Z80_MACH_EZ80_ADL, bfd_mach_ez80_adl,  back_compat_ez80 },
+  { EF_Z80_MACH_Z80N,     bfd_mach_z80n,      back_compat_z80 },
+  { EF_Z80_MACH_GBZ80,    bfd_mach_gbz80,     NULL },
+  { EF_Z80_MACH_R800,     bfd_mach_r800,      back_compat_z80 }
+};
+/*
+static const struct z80_mach_info *
+z80_mach_info_by_eflags (unsigned int eflags)
+{
+  const struct z80_mach_info *p;
+  const struct z80_mach_info *e;
 
-  mach_type = bfd_get_mach (entry->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