OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [binutils-2.18.50/] [bfd/] [coff-w65.c] - Blame information for rev 856

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 38 julius
/* BFD back-end for WDC 65816 COFF binaries.
2
   Copyright 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
3
   2006, 2007 Free Software Foundation, Inc.
4
   Written by Steve Chamberlain, <sac@cygnus.com>.
5
 
6
   This file is part of BFD, the Binary File Descriptor library.
7
 
8
   This program is free software; you can redistribute it and/or modify
9
   it under the terms of the GNU General Public License as published by
10
   the Free Software Foundation; either version 3 of the License, or
11
   (at your option) any later version.
12
 
13
   This program is distributed in the hope that it will be useful,
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
   GNU General Public License for more details.
17
 
18
   You should have received a copy of the GNU General Public License
19
   along with this program; if not, write to the Free Software
20
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21
   MA 02110-1301, USA.  */
22
 
23
#include "sysdep.h"
24
#include "bfd.h"
25
#include "libbfd.h"
26
#include "bfdlink.h"
27
#include "coff/w65.h"
28
#include "coff/internal.h"
29
#include "libcoff.h"
30
 
31
static int  select_reloc              PARAMS ((reloc_howto_type *));
32
static void rtype2howto               PARAMS ((arelent *, struct internal_reloc *));
33
static void reloc_processing          PARAMS ((arelent *, struct internal_reloc *, asymbol **, bfd *, asection *));
34
static int  w65_reloc16_estimate    PARAMS ((bfd *, asection *, arelent *, unsigned int, struct bfd_link_info *));
35
static void w65_reloc16_extra_cases PARAMS ((bfd *,struct bfd_link_info *, struct bfd_link_order *, arelent *, bfd_byte *, unsigned int *, unsigned int *));
36
 
37
#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (1)
38
static reloc_howto_type howto_table[] =
39
  {
40
    HOWTO (R_W65_ABS8,    0,  0, 8,  FALSE, 0, complain_overflow_bitfield, 0, "abs8", TRUE, 0x000000ff, 0x000000ff, FALSE),
41
    HOWTO (R_W65_ABS16,   1,  0, 16, FALSE, 0, complain_overflow_bitfield, 0, "abs16", TRUE, 0x0000ffff, 0x0000ffff, FALSE),
42
    HOWTO (R_W65_ABS24,   0,  2, 32, FALSE, 0, complain_overflow_bitfield, 0, "abs24", TRUE, 0x00ffffff, 0x00ffffff, FALSE),
43
    HOWTO (R_W65_ABS8S8,  0,  0, 8,  FALSE, 0, complain_overflow_bitfield, 0, ">abs8", TRUE, 0x000000ff, 0x000000ff, FALSE),
44
    HOWTO (R_W65_ABS8S16, 0,  0, 8,  FALSE, 0, complain_overflow_bitfield, 0, "^abs8", TRUE, 0x000000ff, 0x000000ff, FALSE),
45
    HOWTO (R_W65_ABS16S8, 1,  0, 16, FALSE, 0, complain_overflow_bitfield, 0, ">abs16", TRUE, 0x0000ffff, 0x0000ffff, FALSE),
46
    HOWTO (R_W65_ABS16S16,1,  0, 16, FALSE, 0, complain_overflow_bitfield, 0, "^abs16", TRUE, 0x0000ffff, 0x0000ffff, FALSE),
47
    HOWTO (R_W65_PCR8,    0,  0, 8,  FALSE, 0, complain_overflow_bitfield, 0, "pcrel8", TRUE, 0x000000ff, 0x000000ff, TRUE),
48
    HOWTO (R_W65_PCR16,   1,  0, 16, FALSE, 0, complain_overflow_bitfield, 0, "pcrel16", TRUE, 0x0000ffff, 0x0000ffff, TRUE),
49
    HOWTO (R_W65_DP,      0,  0, 8,  FALSE, 0, complain_overflow_bitfield, 0, "dp", TRUE, 0x000000ff, 0x000000ff, FALSE),
50
  };
51
 
52
/* Turn a howto into a reloc number.  */
53
 
54
#define SELECT_RELOC(x,howto) \
55
  { x.r_type = select_reloc(howto); }
56
 
57
#define BADMAG(x) (W65BADMAG(x))
58
#define W65 1                   /* Customize coffcode.h */
59
#define __A_MAGIC_SET__
60
 
61
/* Code to swap in the reloc */
62
#define SWAP_IN_RELOC_OFFSET    H_GET_32
63
#define SWAP_OUT_RELOC_OFFSET   H_PUT_32
64
#define SWAP_OUT_RELOC_EXTRA(abfd, src, dst) \
65
  dst->r_stuff[0] = 'S'; \
66
  dst->r_stuff[1] = 'C';
67
 
68
static int
69
select_reloc (howto)
70
     reloc_howto_type *howto;
71
{
72
  return howto->type ;
73
}
74
 
75
/* Code to turn a r_type into a howto ptr, uses the above howto table.  */
76
 
77
static void
78
rtype2howto (internal, dst)
79
     arelent *internal;
80
     struct internal_reloc *dst;
81
{
82
  internal->howto = howto_table + dst->r_type - 1;
83
}
84
 
85
#define RTYPE2HOWTO(internal, relocentry) rtype2howto(internal,relocentry)
86
 
87
/* Perform any necessary magic to the addend in a reloc entry.  */
88
 
89
#define CALC_ADDEND(abfd, symbol, ext_reloc, cache_ptr) \
90
 cache_ptr->addend =  ext_reloc.r_offset;
91
 
92
#define RELOC_PROCESSING(relent,reloc,symbols,abfd,section) \
93
 reloc_processing(relent, reloc, symbols, abfd, section)
94
 
95
static void
96
reloc_processing (relent, reloc, symbols, abfd, section)
97
     arelent * relent;
98
     struct internal_reloc *reloc;
99
     asymbol ** symbols;
100
     bfd * abfd;
101
     asection * section;
102
{
103
  relent->address = reloc->r_vaddr;
104
  rtype2howto (relent, reloc);
105
 
106
  if (((int) reloc->r_symndx) > 0)
107
    relent->sym_ptr_ptr = symbols + obj_convert (abfd)[reloc->r_symndx];
108
  else
109
    relent->sym_ptr_ptr = (asymbol **) bfd_abs_section_ptr->symbol_ptr_ptr;
110
 
111
  relent->addend = reloc->r_offset;
112
 
113
  relent->address -= section->vma;
114
  /*  relent->section = 0;*/
115
}
116
 
117
static int
118
w65_reloc16_estimate (abfd, input_section, reloc, shrink, link_info)
119
     bfd *abfd;
120
     asection *input_section;
121
     arelent *reloc;
122
     unsigned int shrink;
123
     struct bfd_link_info *link_info;
124
{
125
  bfd_vma value;
126
  bfd_vma dot;
127
  bfd_vma gap;
128
 
129
  /* The address of the thing to be relocated will have moved back by
130
   the size of the shrink  - but we don't change reloc->address here,
131
   since we need it to know where the relocation lives in the source
132
   uncooked section.  */
133
 
134
  /*  reloc->address -= shrink;   conceptual */
135
 
136
  bfd_vma address = reloc->address - shrink;
137
 
138
  switch (reloc->howto->type)
139
    {
140
    case R_MOV16B2:
141
    case R_JMP2:
142
      shrink+=2;
143
      break;
144
 
145
      /* Thing is a move one byte.  */
146
    case R_MOV16B1:
147
      value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
148
 
149
      if (value >= 0xff00)
150
        {
151
          /* Change the reloc type from 16bit, possible 8 to 8bit
152
             possible 16.  */
153
          reloc->howto = reloc->howto + 1;
154
          /* The place to relc moves back by one.  */
155
          /* This will be two bytes smaller in the long run.  */
156
          shrink += 2;
157
          bfd_perform_slip (abfd, 2, input_section, address);
158
        }
159
 
160
      break;
161
      /* This is the 24 bit branch which could become an 8 bitter,
162
         the relocation points to the first byte of the insn, not the
163
         actual data.  */
164
 
165
    case R_JMPL1:
166
      value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
167
 
168
      dot = input_section->output_section->vma +
169
        input_section->output_offset + address;
170
 
171
      /* See if the address we're looking at within 127 bytes of where
172
         we are, if so then we can use a small branch rather than the
173
         jump we were going to.  */
174
      gap = value - dot;
175
 
176
      if (-120 < (long) gap && (long) gap < 120)
177
        {
178
          /* Change the reloc type from 24bit, possible 8 to 8bit
179
             possible 32.  */
180
          reloc->howto = reloc->howto + 1;
181
          /* This will be two bytes smaller in the long run.  */
182
          shrink += 2;
183
          bfd_perform_slip (abfd, 2, input_section, address);
184
        }
185
      break;
186
 
187
    case R_JMP1:
188
      value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
189
 
190
      dot = input_section->output_section->vma +
191
        input_section->output_offset + address;
192
 
193
      /* See if the address we're looking at within 127 bytes of where
194
         we are, if so then we can use a small branch rather than the
195
         jump we were going to.  */
196
      gap = value - (dot - shrink);
197
 
198
      if (-120 < (long) gap && (long) gap < 120)
199
        {
200
          /* Change the reloc type from 16bit, possible 8 to 8bit
201
             possible 16.  */
202
          reloc->howto = reloc->howto + 1;
203
          /* The place to relc moves back by one.  */
204
 
205
          /* This will be two bytes smaller in the long run.  */
206
          shrink += 2;
207
          bfd_perform_slip (abfd, 2, input_section, address);
208
        }
209
      break;
210
    }
211
 
212
  return shrink;
213
}
214
 
215
/* First phase of a relaxing link.  */
216
 
217
/* Reloc types
218
   large                small
219
   R_MOV16B1            R_MOV16B2       mov.b with 16bit or 8 bit address
220
   R_JMP1               R_JMP2          jmp or pcrel branch
221
   R_JMPL1              R_JMPL_B8       24jmp or pcrel branch
222
   R_MOV24B1            R_MOV24B2       24 or 8 bit reloc for mov.b  */
223
 
224
static void
225
w65_reloc16_extra_cases (abfd, link_info, link_order, reloc, data, src_ptr,
226
                           dst_ptr)
227
     bfd *abfd;
228
     struct bfd_link_info *link_info;
229
     struct bfd_link_order *link_order;
230
     arelent *reloc;
231
     bfd_byte *data;
232
     unsigned int *src_ptr;
233
     unsigned int *dst_ptr;
234
{
235
  unsigned int src_address = *src_ptr;
236
  unsigned int dst_address = *dst_ptr;
237
  asection *input_section = link_order->u.indirect.section;
238
 
239
  switch (reloc->howto->type)
240
    {
241
    case R_W65_ABS8:
242
    case R_W65_DP:
243
      {
244
        unsigned int gap = bfd_coff_reloc16_get_value (reloc, link_info,
245
                                                       input_section);
246
        bfd_put_8 (abfd, gap, data + dst_address);
247
        dst_address += 1;
248
        src_address += 1;
249
      }
250
      break;
251
 
252
    case R_W65_ABS8S8:
253
      {
254
        unsigned int gap = bfd_coff_reloc16_get_value (reloc, link_info,
255
                                                       input_section);
256
        gap >>= 8;
257
        bfd_put_8 (abfd, gap, data + dst_address);
258
        dst_address += 1;
259
        src_address += 1;
260
      }
261
      break;
262
 
263
    case R_W65_ABS8S16:
264
      {
265
        unsigned int gap = bfd_coff_reloc16_get_value (reloc, link_info,
266
                                                       input_section);
267
        gap >>= 16;
268
        bfd_put_8 (abfd, gap, data + dst_address);
269
        dst_address += 1;
270
        src_address += 1;
271
      }
272
      break;
273
 
274
    case R_W65_ABS16:
275
      {
276
        unsigned int gap = bfd_coff_reloc16_get_value (reloc, link_info,
277
                                                       input_section);
278
 
279
        bfd_put_16 (abfd, (bfd_vma) gap, data + dst_address);
280
        dst_address += 2;
281
        src_address += 2;
282
      }
283
      break;
284
    case R_W65_ABS16S8:
285
      {
286
        unsigned int gap = bfd_coff_reloc16_get_value (reloc, link_info,
287
                                                       input_section);
288
        gap >>= 8;
289
        bfd_put_16 (abfd, (bfd_vma) gap, data + dst_address);
290
        dst_address += 2;
291
        src_address += 2;
292
      }
293
      break;
294
    case R_W65_ABS16S16:
295
      {
296
        unsigned int gap = bfd_coff_reloc16_get_value (reloc, link_info,
297
                                                       input_section);
298
        gap >>= 16;
299
        bfd_put_16 (abfd, (bfd_vma) gap, data + dst_address);
300
        dst_address += 2;
301
        src_address += 2;
302
      }
303
      break;
304
 
305
    case R_W65_ABS24:
306
      {
307
        unsigned int gap = bfd_coff_reloc16_get_value (reloc, link_info,
308
                                                       input_section);
309
        bfd_put_16 (abfd, (bfd_vma) gap, data + dst_address);
310
        bfd_put_8 (abfd, gap >> 16, data+dst_address + 2);
311
        dst_address += 3;
312
        src_address += 3;
313
      }
314
      break;
315
 
316
    case R_W65_PCR8:
317
      {
318
        int gap = bfd_coff_reloc16_get_value (reloc, link_info,
319
                                              input_section);
320
        bfd_vma dot = (dst_address
321
                       + input_section->output_offset
322
                       + input_section->output_section->vma);
323
 
324
        gap -= dot + 1;
325
        if (gap < -128 || gap > 127)
326
          {
327
            if (! ((*link_info->callbacks->reloc_overflow)
328
                   (link_info, NULL,
329
                    bfd_asymbol_name (*reloc->sym_ptr_ptr),
330
                    reloc->howto->name, reloc->addend, input_section->owner,
331
                    input_section, reloc->address)))
332
              abort ();
333
          }
334
        bfd_put_8 (abfd, gap, data + dst_address);
335
        dst_address += 1;
336
        src_address += 1;
337
      }
338
      break;
339
 
340
    case R_W65_PCR16:
341
      {
342
        bfd_vma gap = bfd_coff_reloc16_get_value (reloc, link_info,
343
                                                  input_section);
344
        bfd_vma dot = (dst_address
345
                       + input_section->output_offset
346
                       + input_section->output_section->vma);
347
 
348
        /* This wraps within the page, so ignore the relativeness, look at the
349
           high part.  */
350
        if ((gap & 0xf0000) != (dot & 0xf0000))
351
          {
352
            if (! ((*link_info->callbacks->reloc_overflow)
353
                   (link_info, NULL,
354
                    bfd_asymbol_name (*reloc->sym_ptr_ptr),
355
                    reloc->howto->name, reloc->addend, input_section->owner,
356
                    input_section, reloc->address)))
357
              abort ();
358
          }
359
 
360
        gap -= dot + 2;
361
        bfd_put_16 (abfd, gap, data + dst_address);
362
        dst_address += 2;
363
        src_address += 2;
364
      }
365
      break;
366
    default:
367
      printf (_("ignoring reloc %s\n"), reloc->howto->name);
368
      break;
369
 
370
    }
371
  *src_ptr = src_address;
372
  *dst_ptr = dst_address;
373
}
374
 
375
#define coff_reloc16_extra_cases w65_reloc16_extra_cases
376
#define coff_reloc16_estimate w65_reloc16_estimate
377
 
378
#include "coffcode.h"
379
 
380
#undef coff_bfd_get_relocated_section_contents
381
#undef coff_bfd_relax_section
382
#define coff_bfd_get_relocated_section_contents \
383
  bfd_coff_reloc16_get_relocated_section_contents
384
#define coff_bfd_relax_section bfd_coff_reloc16_relax_section
385
 
386
CREATE_LITTLE_COFF_TARGET_VEC (w65_vec, "coff-w65", BFD_IS_RELAXABLE, 0, '_', NULL, COFF_SWAP_TABLE)

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.