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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [binutils-2.20.1/] [bfd/] [coff-maxq.c] - Blame information for rev 297

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

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

powered by: WebSVN 2.1.0

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