aboutsummaryrefslogtreecommitdiff
path: root/ld/emultempl/z80elf.em
blob: 4b03e798d1b37d3ab16e031ab65658d9b379da6a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# 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 <<EOF
/* --- \begin{z80.em} */

#include "elf/z80.h"

static void
gld${EMULATION_NAME}_after_open (void);

static int result_mach_type;

/* Set the machine type of the output file based on result_mach_type.  */
static void
z80_elf_after_open (void)
{
  unsigned int mach = 0;
  bfd *abfd;

  /* 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)
    {
      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