xref: /openbsd-src/gnu/usr.bin/binutils-2.17/bfd/coff-maxq.c (revision 3d8817e467ea46cf4772788d6804dd293abfb01a)
1*3d8817e4Smiod /* BFD back-end for MAXQ COFF binaries.
2*3d8817e4Smiod    Copyright 2004    Free Software Foundation, Inc.
3*3d8817e4Smiod 
4*3d8817e4Smiod    Contributed by Vineet Sharma (vineets@noida.hcltech.com) Inderpreet S.
5*3d8817e4Smiod    (inderpreetb@noida.hcltech.com)
6*3d8817e4Smiod 
7*3d8817e4Smiod    HCL Technologies Ltd.
8*3d8817e4Smiod 
9*3d8817e4Smiod    This file is part of BFD, the Binary File Descriptor library.
10*3d8817e4Smiod 
11*3d8817e4Smiod    This program is free software; you can redistribute it and/or modify it
12*3d8817e4Smiod    under the terms of the GNU General Public License as published by the Free
13*3d8817e4Smiod    Software Foundation; either version 2 of the License, or (at your option)
14*3d8817e4Smiod    any later version.
15*3d8817e4Smiod 
16*3d8817e4Smiod    This program is distributed in the hope that it will be useful, but
17*3d8817e4Smiod    WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18*3d8817e4Smiod    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
19*3d8817e4Smiod    for more details.
20*3d8817e4Smiod 
21*3d8817e4Smiod    You should have received a copy of the GNU General Public License along
22*3d8817e4Smiod    with this program; if not, write to the Free Software Foundation, Inc.,
23*3d8817e4Smiod    51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
24*3d8817e4Smiod 
25*3d8817e4Smiod #include "bfd.h"
26*3d8817e4Smiod #include "sysdep.h"
27*3d8817e4Smiod #include "libbfd.h"
28*3d8817e4Smiod #include "coff/maxq.h"
29*3d8817e4Smiod #include "coff/internal.h"
30*3d8817e4Smiod #include "libcoff.h"
31*3d8817e4Smiod #include "libiberty.h"
32*3d8817e4Smiod 
33*3d8817e4Smiod #ifndef MAXQ20
34*3d8817e4Smiod #define MAXQ20 1
35*3d8817e4Smiod #endif
36*3d8817e4Smiod 
37*3d8817e4Smiod #define RTYPE2HOWTO(cache_ptr, dst)                                     \
38*3d8817e4Smiod   ((cache_ptr)->howto =                                                 \
39*3d8817e4Smiod    ((dst)->r_type < 48 							\
40*3d8817e4Smiod     ? howto_table + (((dst)->r_type==47) ? 6: ((dst)->r_type))		\
41*3d8817e4Smiod     : NULL))
42*3d8817e4Smiod 
43*3d8817e4Smiod #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
44*3d8817e4Smiod 
45*3d8817e4Smiod /* Code to swap in the reloc offset.  */
46*3d8817e4Smiod #define SWAP_IN_RELOC_OFFSET    H_GET_16
47*3d8817e4Smiod #define SWAP_OUT_RELOC_OFFSET   H_PUT_16
48*3d8817e4Smiod 
49*3d8817e4Smiod #define SHORT_JUMP 	        BFD_RELOC_16_PCREL_S2
50*3d8817e4Smiod #define LONG_JUMP 	        BFD_RELOC_14
51*3d8817e4Smiod #define ABSOLUTE_ADDR_FOR_DATA  BFD_RELOC_24
52*3d8817e4Smiod 
53*3d8817e4Smiod /* checks the range of short jump -127 to 128 */
54*3d8817e4Smiod #define IS_SJUMP_RANGE(x) ((x > -128) && (x < 129))
55*3d8817e4Smiod #define HIGH_WORD_MASK    0xff00
56*3d8817e4Smiod #define LOW_WORD_MASK     0x00ff
57*3d8817e4Smiod 
58*3d8817e4Smiod static long
get_symbol_value(asymbol * symbol)59*3d8817e4Smiod get_symbol_value (asymbol *symbol)
60*3d8817e4Smiod {
61*3d8817e4Smiod   long relocation = 0;
62*3d8817e4Smiod 
63*3d8817e4Smiod   if (bfd_is_com_section (symbol->section))
64*3d8817e4Smiod     relocation = 0;
65*3d8817e4Smiod   else
66*3d8817e4Smiod     relocation = symbol->value +
67*3d8817e4Smiod       symbol->section->output_section->vma + symbol->section->output_offset;
68*3d8817e4Smiod 
69*3d8817e4Smiod   return relocation;
70*3d8817e4Smiod }
71*3d8817e4Smiod 
72*3d8817e4Smiod /* This function performs all the maxq relocations.
73*3d8817e4Smiod    FIXME:  The handling of the addend in the 'BFD_*'
74*3d8817e4Smiod    relocations types.  */
75*3d8817e4Smiod 
76*3d8817e4Smiod static bfd_reloc_status_type
coff_maxq20_reloc(bfd * abfd,arelent * reloc_entry,asymbol * symbol_in,void * data,asection * input_section ATTRIBUTE_UNUSED,bfd * output_bfd ATTRIBUTE_UNUSED,char ** error_message ATTRIBUTE_UNUSED)77*3d8817e4Smiod coff_maxq20_reloc (bfd *      abfd,
78*3d8817e4Smiod 		   arelent *  reloc_entry,
79*3d8817e4Smiod 		   asymbol *  symbol_in,
80*3d8817e4Smiod 		   void *     data,
81*3d8817e4Smiod 		   asection * input_section ATTRIBUTE_UNUSED,
82*3d8817e4Smiod 		   bfd *      output_bfd    ATTRIBUTE_UNUSED,
83*3d8817e4Smiod 		   char **    error_message ATTRIBUTE_UNUSED)
84*3d8817e4Smiod {
85*3d8817e4Smiod   reloc_howto_type *howto = NULL;
86*3d8817e4Smiod   unsigned char *addr = NULL;
87*3d8817e4Smiod   unsigned long x = 0;
88*3d8817e4Smiod   long call_addr = 0;
89*3d8817e4Smiod   short addend = 0;
90*3d8817e4Smiod   long diff = 0;
91*3d8817e4Smiod 
92*3d8817e4Smiod   /* If this is an undefined symbol, return error.  */
93*3d8817e4Smiod   if (symbol_in->section == &bfd_und_section
94*3d8817e4Smiod       && (symbol_in->flags & BSF_WEAK) == 0)
95*3d8817e4Smiod     return bfd_reloc_continue;
96*3d8817e4Smiod 
97*3d8817e4Smiod   if (data && reloc_entry)
98*3d8817e4Smiod     {
99*3d8817e4Smiod       howto = reloc_entry->howto;
100*3d8817e4Smiod       addr = (unsigned char *) data + reloc_entry->address;
101*3d8817e4Smiod       call_addr = call_addr - call_addr;
102*3d8817e4Smiod       call_addr = get_symbol_value (symbol_in);
103*3d8817e4Smiod 
104*3d8817e4Smiod       /* Over here the value val stores the 8 bit/16 bit value. We will put a
105*3d8817e4Smiod          check if we are moving a 16 bit immediate value into an 8 bit
106*3d8817e4Smiod          register. In that case we will generate a Upper bytes into PFX[0]
107*3d8817e4Smiod          and move the lower 8 bits as SRC.  */
108*3d8817e4Smiod 
109*3d8817e4Smiod       switch (reloc_entry->howto->type)
110*3d8817e4Smiod 	{
111*3d8817e4Smiod 	  /* BFD_RELOC_16_PCREL_S2 47 Handles all the relative jumps and
112*3d8817e4Smiod 	     calls Note: Every relative jump or call is in words.  */
113*3d8817e4Smiod 	case SHORT_JUMP:
114*3d8817e4Smiod 	  /* Handle any addend.  */
115*3d8817e4Smiod 	  addend = reloc_entry->addend;
116*3d8817e4Smiod 
117*3d8817e4Smiod 	  if (addend > call_addr || addend > 0)
118*3d8817e4Smiod 	    call_addr = symbol_in->section->output_section->vma + addend;
119*3d8817e4Smiod 	  else if (addend < call_addr && addend > 0)
120*3d8817e4Smiod 	    call_addr = call_addr + addend;
121*3d8817e4Smiod 	  else if (addend < 0)
122*3d8817e4Smiod 	    call_addr = call_addr + addend;
123*3d8817e4Smiod 
124*3d8817e4Smiod 	  diff = ((call_addr << 1) - (reloc_entry->address << 1));
125*3d8817e4Smiod 
126*3d8817e4Smiod 	  if (!IS_SJUMP_RANGE (diff))
127*3d8817e4Smiod 	    {
128*3d8817e4Smiod 	      bfd_perror (_("Can't Make it a Short Jump"));
129*3d8817e4Smiod 	      return bfd_reloc_outofrange;
130*3d8817e4Smiod 	    }
131*3d8817e4Smiod 
132*3d8817e4Smiod 	  x = bfd_get_16 (abfd, addr);
133*3d8817e4Smiod 
134*3d8817e4Smiod 	  x = x & LOW_WORD_MASK;
135*3d8817e4Smiod 	  x = x | (diff << 8);
136*3d8817e4Smiod 	  bfd_put_16 (abfd, (bfd_vma) x, addr);
137*3d8817e4Smiod 
138*3d8817e4Smiod 	  return bfd_reloc_ok;
139*3d8817e4Smiod 
140*3d8817e4Smiod 	case ABSOLUTE_ADDR_FOR_DATA:
141*3d8817e4Smiod 	case LONG_JUMP:
142*3d8817e4Smiod 	  /* BFD_RELOC_14 Handles intersegment or long jumps which might be
143*3d8817e4Smiod 	     from code to code or code to data segment jumps. Note: When this
144*3d8817e4Smiod 	     fucntion is called by gas the section flags somehow do not
145*3d8817e4Smiod 	     contain the info about the section type(CODE or DATA). Thus the
146*3d8817e4Smiod 	     user needs to evoke the linker after assembling the files
147*3d8817e4Smiod 	     because the Code-Code relocs are word aligned but code-data are
148*3d8817e4Smiod 	     byte aligned.  */
149*3d8817e4Smiod 	  addend = (reloc_entry->addend - reloc_entry->addend);
150*3d8817e4Smiod 
151*3d8817e4Smiod 	  /* Handle any addend.  */
152*3d8817e4Smiod 	  addend = reloc_entry->addend;
153*3d8817e4Smiod 
154*3d8817e4Smiod 	  /* For relocation involving multiple file added becomes zero thus
155*3d8817e4Smiod 	     this fails - check for zero added. In another case when we try
156*3d8817e4Smiod 	     to add a stub to a file the addend shows the offset from the
157*3d8817e4Smiod 	     start od this file.  */
158*3d8817e4Smiod 	  addend = 0;
159*3d8817e4Smiod 
160*3d8817e4Smiod 	  if (!bfd_is_com_section (symbol_in->section) &&
161*3d8817e4Smiod 	      ((symbol_in->flags & BSF_OLD_COMMON) == 0))
162*3d8817e4Smiod 	    {
163*3d8817e4Smiod 	      if (reloc_entry->addend > symbol_in->value)
164*3d8817e4Smiod 		addend = reloc_entry->addend - symbol_in->value;
165*3d8817e4Smiod 
166*3d8817e4Smiod 	      if ((reloc_entry->addend < symbol_in->value)
167*3d8817e4Smiod 		  && (reloc_entry->addend != 0))
168*3d8817e4Smiod 		addend = reloc_entry->addend - symbol_in->value;
169*3d8817e4Smiod 
170*3d8817e4Smiod 	      if (reloc_entry->addend == symbol_in->value)
171*3d8817e4Smiod 		addend = 0;
172*3d8817e4Smiod 	    }
173*3d8817e4Smiod 
174*3d8817e4Smiod 	  if (bfd_is_com_section (symbol_in->section) ||
175*3d8817e4Smiod 	      ((symbol_in->flags & BSF_OLD_COMMON) != 0))
176*3d8817e4Smiod 	    addend = reloc_entry->addend;
177*3d8817e4Smiod 
178*3d8817e4Smiod 	  if (addend < 0
179*3d8817e4Smiod 	      &&  (call_addr < (long) (addend * (-1))))
180*3d8817e4Smiod 	    addend = 0;
181*3d8817e4Smiod 
182*3d8817e4Smiod 	  call_addr += addend;
183*3d8817e4Smiod 
184*3d8817e4Smiod 	  /* FIXME: This check does not work well with the assembler,
185*3d8817e4Smiod 	     linker needs to be run always.  */
186*3d8817e4Smiod 	  if ((symbol_in->section->flags & SEC_CODE) == SEC_CODE)
187*3d8817e4Smiod 	    {
188*3d8817e4Smiod 	      /* Convert it into words.  */
189*3d8817e4Smiod 	      call_addr = call_addr >> 1;
190*3d8817e4Smiod 
191*3d8817e4Smiod 	      if (call_addr > 0xFFFF)	/* Intersegment Jump.  */
192*3d8817e4Smiod 		{
193*3d8817e4Smiod 		  bfd_perror (_("Exceeds Long Jump Range"));
194*3d8817e4Smiod 		  return bfd_reloc_outofrange;
195*3d8817e4Smiod 		}
196*3d8817e4Smiod 	    }
197*3d8817e4Smiod 	  else
198*3d8817e4Smiod 	    {
199*3d8817e4Smiod 	      /* case ABSOLUTE_ADDR_FOR_DATA : Resolves any code-data
200*3d8817e4Smiod 		 segemnt relocs. These are NOT word aligned.  */
201*3d8817e4Smiod 
202*3d8817e4Smiod 	      if (call_addr > 0xFFFF)	/* Intersegment Jump.  */
203*3d8817e4Smiod 		{
204*3d8817e4Smiod 		  bfd_perror (_("Absolute address Exceeds 16 bit Range"));
205*3d8817e4Smiod 		  return bfd_reloc_outofrange;
206*3d8817e4Smiod 		}
207*3d8817e4Smiod 	    }
208*3d8817e4Smiod 
209*3d8817e4Smiod 	  x = bfd_get_32 (abfd, addr);
210*3d8817e4Smiod 
211*3d8817e4Smiod 	  x = (x & 0xFF00FF00);
212*3d8817e4Smiod 	  x = (x | ((call_addr & HIGH_WORD_MASK) >> 8));
213*3d8817e4Smiod 	  x = (x | (call_addr & LOW_WORD_MASK) << 16);
214*3d8817e4Smiod 
215*3d8817e4Smiod 	  bfd_put_32 (abfd, (bfd_vma) x, addr);
216*3d8817e4Smiod 	  return bfd_reloc_ok;
217*3d8817e4Smiod 
218*3d8817e4Smiod 	case BFD_RELOC_8:
219*3d8817e4Smiod 	  addend = (reloc_entry->addend - reloc_entry->addend);
220*3d8817e4Smiod 
221*3d8817e4Smiod 	  if (!bfd_is_com_section (symbol_in->section) &&
222*3d8817e4Smiod 	      ((symbol_in->flags & BSF_OLD_COMMON) == 0))
223*3d8817e4Smiod 	    {
224*3d8817e4Smiod 	      if (reloc_entry->addend > symbol_in->value)
225*3d8817e4Smiod 		addend = reloc_entry->addend - symbol_in->value;
226*3d8817e4Smiod 	      if (reloc_entry->addend < symbol_in->value)
227*3d8817e4Smiod 		addend = reloc_entry->addend - symbol_in->value;
228*3d8817e4Smiod 	      if (reloc_entry->addend == symbol_in->value)
229*3d8817e4Smiod 		addend = 0;
230*3d8817e4Smiod 	    }
231*3d8817e4Smiod 
232*3d8817e4Smiod 	  if (bfd_is_com_section (symbol_in->section) ||
233*3d8817e4Smiod 	      ((symbol_in->flags & BSF_OLD_COMMON) != 0))
234*3d8817e4Smiod 	    addend = reloc_entry->addend;
235*3d8817e4Smiod 
236*3d8817e4Smiod 	  if (addend < 0
237*3d8817e4Smiod 	      && (call_addr < (long) (addend * (-1))))
238*3d8817e4Smiod 	    addend = 0;
239*3d8817e4Smiod 
240*3d8817e4Smiod 	  if (call_addr + addend > 0xFF)
241*3d8817e4Smiod 	    {
242*3d8817e4Smiod 	      bfd_perror (_("Absolute address Exceeds 8 bit Range"));
243*3d8817e4Smiod 	      return bfd_reloc_outofrange;
244*3d8817e4Smiod 	    }
245*3d8817e4Smiod 
246*3d8817e4Smiod 	  x = bfd_get_8 (abfd, addr);
247*3d8817e4Smiod 	  x = x & 0x00;
248*3d8817e4Smiod 	  x = x | (call_addr + addend);
249*3d8817e4Smiod 
250*3d8817e4Smiod 	  bfd_put_8 (abfd, (bfd_vma) x, addr);
251*3d8817e4Smiod 	  return bfd_reloc_ok;
252*3d8817e4Smiod 
253*3d8817e4Smiod 	case BFD_RELOC_16:
254*3d8817e4Smiod 	  addend = (reloc_entry->addend - reloc_entry->addend);
255*3d8817e4Smiod 	  if (!bfd_is_com_section (symbol_in->section) &&
256*3d8817e4Smiod 	      ((symbol_in->flags & BSF_OLD_COMMON) == 0))
257*3d8817e4Smiod 	    {
258*3d8817e4Smiod 	      if (reloc_entry->addend > symbol_in->value)
259*3d8817e4Smiod 		addend = reloc_entry->addend - symbol_in->value;
260*3d8817e4Smiod 
261*3d8817e4Smiod 	      if (reloc_entry->addend < symbol_in->value)
262*3d8817e4Smiod 		addend = reloc_entry->addend - symbol_in->value;
263*3d8817e4Smiod 
264*3d8817e4Smiod 	      if (reloc_entry->addend == symbol_in->value)
265*3d8817e4Smiod 		addend = 0;
266*3d8817e4Smiod 	    }
267*3d8817e4Smiod 
268*3d8817e4Smiod 	  if (bfd_is_com_section (symbol_in->section) ||
269*3d8817e4Smiod 	      ((symbol_in->flags & BSF_OLD_COMMON) != 0))
270*3d8817e4Smiod 	    addend = reloc_entry->addend;
271*3d8817e4Smiod 
272*3d8817e4Smiod 	  if (addend < 0
273*3d8817e4Smiod 	      && (call_addr < (long) (addend * (-1))))
274*3d8817e4Smiod 	    addend = 0;
275*3d8817e4Smiod 
276*3d8817e4Smiod 	  if ((call_addr + addend) > 0xFFFF)
277*3d8817e4Smiod 	    {
278*3d8817e4Smiod 	      bfd_perror (_("Absolute address Exceeds 16 bit Range"));
279*3d8817e4Smiod 	      return bfd_reloc_outofrange;
280*3d8817e4Smiod 	    }
281*3d8817e4Smiod 	  else
282*3d8817e4Smiod 	    {
283*3d8817e4Smiod 	      unsigned short val = (call_addr + addend);
284*3d8817e4Smiod 
285*3d8817e4Smiod 	      x = bfd_get_16 (abfd, addr);
286*3d8817e4Smiod 
287*3d8817e4Smiod 	      /* LE */
288*3d8817e4Smiod 	      x = (x & 0x0000);	/* Flush garbage value.  */
289*3d8817e4Smiod 	      x = val;
290*3d8817e4Smiod 	      if ((symbol_in->section->flags & SEC_CODE) == SEC_CODE)
291*3d8817e4Smiod 		x = x >> 1;	/* Convert it into words.  */
292*3d8817e4Smiod 	    }
293*3d8817e4Smiod 
294*3d8817e4Smiod 	  bfd_put_16 (abfd, (bfd_vma) x, addr);
295*3d8817e4Smiod 	  return bfd_reloc_ok;
296*3d8817e4Smiod 
297*3d8817e4Smiod 	case BFD_RELOC_32:
298*3d8817e4Smiod 	  addend = (reloc_entry->addend - reloc_entry->addend);
299*3d8817e4Smiod 
300*3d8817e4Smiod 	  if (!bfd_is_com_section (symbol_in->section) &&
301*3d8817e4Smiod 	      ((symbol_in->flags & BSF_OLD_COMMON) == 0))
302*3d8817e4Smiod 	    {
303*3d8817e4Smiod 	      if (reloc_entry->addend > symbol_in->value)
304*3d8817e4Smiod 		addend = reloc_entry->addend - symbol_in->value;
305*3d8817e4Smiod 	      if (reloc_entry->addend < symbol_in->value)
306*3d8817e4Smiod 		addend = reloc_entry->addend - symbol_in->value;
307*3d8817e4Smiod 	      if (reloc_entry->addend == symbol_in->value)
308*3d8817e4Smiod 		addend = 0;
309*3d8817e4Smiod 	    }
310*3d8817e4Smiod 
311*3d8817e4Smiod 	  if (bfd_is_com_section (symbol_in->section) ||
312*3d8817e4Smiod 	      ((symbol_in->flags & BSF_OLD_COMMON) != 0))
313*3d8817e4Smiod 	    addend = reloc_entry->addend;
314*3d8817e4Smiod 
315*3d8817e4Smiod 	  if (addend < 0
316*3d8817e4Smiod 	      && (call_addr < (long) (addend * (-1))))
317*3d8817e4Smiod 	    addend = 0;
318*3d8817e4Smiod 
319*3d8817e4Smiod 	  if ((call_addr + addend) < 0)
320*3d8817e4Smiod 	    {
321*3d8817e4Smiod 	      bfd_perror ("Absolute address Exceeds 32 bit Range");
322*3d8817e4Smiod 	      return bfd_reloc_outofrange;
323*3d8817e4Smiod 	    }
324*3d8817e4Smiod 
325*3d8817e4Smiod 	  x = bfd_get_32 (abfd, addr);
326*3d8817e4Smiod 	  x = (x & 0x0000);	/* Flush garbage value.  */
327*3d8817e4Smiod 	  x = call_addr + addend;
328*3d8817e4Smiod 	  if ((symbol_in->section->flags & SEC_CODE) == SEC_CODE)
329*3d8817e4Smiod 	    x = x >> 1;	/* Convert it into words.  */
330*3d8817e4Smiod 
331*3d8817e4Smiod 	  bfd_put_32 (abfd, (bfd_vma) x, addr);
332*3d8817e4Smiod 	  return bfd_reloc_ok;
333*3d8817e4Smiod 
334*3d8817e4Smiod 	default:
335*3d8817e4Smiod 	  bfd_perror (_("Unrecognized Reloc Type"));
336*3d8817e4Smiod 	  return bfd_reloc_notsupported;
337*3d8817e4Smiod 	}
338*3d8817e4Smiod     }
339*3d8817e4Smiod 
340*3d8817e4Smiod   return bfd_reloc_notsupported;
341*3d8817e4Smiod }
342*3d8817e4Smiod 
343*3d8817e4Smiod static reloc_howto_type howto_table[] =
344*3d8817e4Smiod {
345*3d8817e4Smiod   EMPTY_HOWTO (0),
346*3d8817e4Smiod   EMPTY_HOWTO (1),
347*3d8817e4Smiod   {
348*3d8817e4Smiod    BFD_RELOC_32, 0, 1, 8, FALSE, 0, complain_overflow_bitfield,
349*3d8817e4Smiod    coff_maxq20_reloc, "32Bit", TRUE, 0x000000ff, 0x000000ff, TRUE
350*3d8817e4Smiod   },
351*3d8817e4Smiod   {
352*3d8817e4Smiod    SHORT_JUMP, 0, 1, 8, FALSE, 0, complain_overflow_bitfield,
353*3d8817e4Smiod    coff_maxq20_reloc, "SHORT_JMP", TRUE, 0x000000ff, 0x000000ff, TRUE
354*3d8817e4Smiod   },
355*3d8817e4Smiod   {
356*3d8817e4Smiod    ABSOLUTE_ADDR_FOR_DATA, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
357*3d8817e4Smiod    coff_maxq20_reloc, "INTERSEGMENT_RELOC", TRUE, 0x00000000, 0x00000000,
358*3d8817e4Smiod    FALSE
359*3d8817e4Smiod   },
360*3d8817e4Smiod   {
361*3d8817e4Smiod    BFD_RELOC_16, 0, 1, 8, FALSE, 0, complain_overflow_bitfield,
362*3d8817e4Smiod    coff_maxq20_reloc, "16Bit", TRUE, 0x000000ff, 0x000000ff, TRUE
363*3d8817e4Smiod   },
364*3d8817e4Smiod   {
365*3d8817e4Smiod    LONG_JUMP, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
366*3d8817e4Smiod    coff_maxq20_reloc, "LONG_JUMP", TRUE, 0x00000000, 0x00000000, FALSE
367*3d8817e4Smiod   },
368*3d8817e4Smiod   {
369*3d8817e4Smiod    BFD_RELOC_8, 0, 1, 8, FALSE, 0, complain_overflow_bitfield,
370*3d8817e4Smiod    coff_maxq20_reloc, "8bit", TRUE, 0x000000ff, 0x000000ff, TRUE
371*3d8817e4Smiod   },
372*3d8817e4Smiod   EMPTY_HOWTO (8),
373*3d8817e4Smiod   EMPTY_HOWTO (9),
374*3d8817e4Smiod   EMPTY_HOWTO (10),
375*3d8817e4Smiod };
376*3d8817e4Smiod 
377*3d8817e4Smiod /* Map BFD reloc types to MAXQ COFF reloc types.  */
378*3d8817e4Smiod 
379*3d8817e4Smiod typedef struct maxq_reloc_map
380*3d8817e4Smiod {
381*3d8817e4Smiod   bfd_reloc_code_real_type  bfd_reloc_val;
382*3d8817e4Smiod   unsigned int              maxq_reloc_val;
383*3d8817e4Smiod   reloc_howto_type *        table;
384*3d8817e4Smiod }
385*3d8817e4Smiod reloc_map;
386*3d8817e4Smiod 
387*3d8817e4Smiod static const reloc_map maxq_reloc_map[] =
388*3d8817e4Smiod {
389*3d8817e4Smiod   {BFD_RELOC_16_PCREL_S2, SHORT_JUMP, howto_table},
390*3d8817e4Smiod   {BFD_RELOC_16,          LONG_JUMP,  howto_table},
391*3d8817e4Smiod };
392*3d8817e4Smiod 
393*3d8817e4Smiod static reloc_howto_type *
maxq_reloc_type_lookup(bfd * abfd ATTRIBUTE_UNUSED,bfd_reloc_code_real_type code)394*3d8817e4Smiod maxq_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
395*3d8817e4Smiod 			bfd_reloc_code_real_type code)
396*3d8817e4Smiod {
397*3d8817e4Smiod   unsigned int i;
398*3d8817e4Smiod 
399*3d8817e4Smiod   for (i = 0; i < ARRAY_SIZE (maxq_reloc_map); i++)
400*3d8817e4Smiod     {
401*3d8817e4Smiod       const reloc_map *entry;
402*3d8817e4Smiod 
403*3d8817e4Smiod       entry = maxq_reloc_map + i;
404*3d8817e4Smiod 
405*3d8817e4Smiod       switch (code)
406*3d8817e4Smiod 	{
407*3d8817e4Smiod 	  /* SHORT JUMP */
408*3d8817e4Smiod 	case BFD_RELOC_16_PCREL_S2:
409*3d8817e4Smiod 	  return howto_table + 3;
410*3d8817e4Smiod 
411*3d8817e4Smiod 	  /* INTERSEGMENT JUMP */
412*3d8817e4Smiod 	case BFD_RELOC_24:
413*3d8817e4Smiod 	  return howto_table + 4;
414*3d8817e4Smiod 
415*3d8817e4Smiod 	  /* BYTE RELOC */
416*3d8817e4Smiod 	case BFD_RELOC_8:
417*3d8817e4Smiod 	  return howto_table + 7;
418*3d8817e4Smiod 
419*3d8817e4Smiod 	  /* WORD RELOC */
420*3d8817e4Smiod 	case BFD_RELOC_16:
421*3d8817e4Smiod 	  return howto_table + 5;
422*3d8817e4Smiod 
423*3d8817e4Smiod 	  /* LONG RELOC */
424*3d8817e4Smiod 	case BFD_RELOC_32:
425*3d8817e4Smiod 	  return howto_table + 2;
426*3d8817e4Smiod 
427*3d8817e4Smiod 	  /* LONG JUMP */
428*3d8817e4Smiod 	case BFD_RELOC_14:
429*3d8817e4Smiod 	  return howto_table + 6;
430*3d8817e4Smiod 
431*3d8817e4Smiod 	default:
432*3d8817e4Smiod 	  return NULL;
433*3d8817e4Smiod 	}
434*3d8817e4Smiod     }
435*3d8817e4Smiod 
436*3d8817e4Smiod   return NULL;
437*3d8817e4Smiod }
438*3d8817e4Smiod 
439*3d8817e4Smiod #define coff_bfd_reloc_type_lookup maxq_reloc_type_lookup
440*3d8817e4Smiod 
441*3d8817e4Smiod /* Perform any necessary magic to the addend in a reloc entry.  */
442*3d8817e4Smiod #define CALC_ADDEND(abfd, symbol, ext_reloc, cache_ptr) \
443*3d8817e4Smiod  cache_ptr->addend =  ext_reloc.r_offset;
444*3d8817e4Smiod 
445*3d8817e4Smiod #include "coffcode.h"
446*3d8817e4Smiod 
447*3d8817e4Smiod #ifndef TARGET_UNDERSCORE
448*3d8817e4Smiod #define TARGET_UNDERSCORE 1
449*3d8817e4Smiod #endif
450*3d8817e4Smiod 
451*3d8817e4Smiod #ifndef EXTRA_S_FLAGS
452*3d8817e4Smiod #define EXTRA_S_FLAGS 0
453*3d8817e4Smiod #endif
454*3d8817e4Smiod 
455*3d8817e4Smiod /* Forward declaration for use initialising alternative_target field.  */
456*3d8817e4Smiod CREATE_LITTLE_COFF_TARGET_VEC (maxqcoff_vec, "coff-maxq", 0, EXTRA_S_FLAGS,
457*3d8817e4Smiod 			       TARGET_UNDERSCORE, NULL, COFF_SWAP_TABLE);
458*3d8817e4Smiod 
459