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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-7.2/] [bfd/] [elf32-cr16c.c] - Blame information for rev 438

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

Line No. Rev Author Line
1 330 jeremybenn
/* BFD back-end for National Semiconductor's CR16C ELF
2
   Copyright 2004, 2005, 2006, 2007, 2009, 2010
3
   Free Software Foundation, Inc.
4
 
5
   This file is part of BFD, the Binary File Descriptor library.
6
 
7
   This program is free software; you can redistribute it and/or modify
8
   it under the terms of the GNU General Public License as published by
9
   the Free Software Foundation; either version 3 of the License, or
10
   (at your option) any later version.
11
 
12
   This program is distributed in the hope that it will be useful,
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
   GNU General Public License for more details.
16
 
17
   You should have received a copy of the GNU General Public License
18
   along with this program; if not, write to the Free Software
19
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20
   MA 02110-1301, USA.  */
21
 
22
#include "sysdep.h"
23
#include "bfd.h"
24
#include "libbfd.h"
25
#include "bfdlink.h"
26
#include "elf/cr16c.h"
27
#include "elf-bfd.h"
28
 
29
 
30
#define USE_REL 1       /* CR16C uses REL relocations instead of RELA.  */
31
 
32
/* The following definition is based on EMPTY_HOWTO macro,
33
   but also initiates the "name" field in HOWTO struct.  */
34
#define ONLY_NAME_HOWTO(C) \
35
  HOWTO ((C), 0, 0, 0, FALSE, 0, complain_overflow_dont, NULL, \
36
          STRINGX(C), FALSE, 0, 0, FALSE)
37
 
38
/* reloc_map_index array maps CRASM relocation type into a BFD
39
   relocation enum. The array's indices are synchronized with
40
   RINDEX_16C_* indices, created in include/elf/cr16c.h.
41
   The array is used in:
42
   1. elf32-cr16c.c : elf_cr16c_reloc_type_lookup().
43
   2. asreloc.c : find_reloc_type(). */
44
 
45
RELOC_MAP reloc_map_index[RINDEX_16C_MAX] =
46
{
47
  {R_16C_NUM08,     BFD_RELOC_16C_NUM08},
48
  {R_16C_NUM08_C,   BFD_RELOC_16C_NUM08_C},
49
  {R_16C_NUM16,     BFD_RELOC_16C_NUM16},
50
  {R_16C_NUM16_C,   BFD_RELOC_16C_NUM16_C},
51
  {R_16C_NUM32,     BFD_RELOC_16C_NUM32},
52
  {R_16C_NUM32_C,   BFD_RELOC_16C_NUM32_C},
53
  {R_16C_DISP04,    BFD_RELOC_16C_DISP04},
54
  {R_16C_DISP04_C,  BFD_RELOC_16C_DISP04_C},
55
  {R_16C_DISP08,    BFD_RELOC_16C_DISP08},
56
  {R_16C_DISP08_C,  BFD_RELOC_16C_DISP08_C},
57
  {R_16C_DISP16,    BFD_RELOC_16C_DISP16},
58
  {R_16C_DISP16_C,  BFD_RELOC_16C_DISP16_C},
59
  {R_16C_DISP24,    BFD_RELOC_16C_DISP24},
60
  {R_16C_DISP24_C,  BFD_RELOC_16C_DISP24_C},
61
  {R_16C_DISP24a,   BFD_RELOC_16C_DISP24a},
62
  {R_16C_DISP24a_C, BFD_RELOC_16C_DISP24a_C},
63
  {R_16C_REG04,     BFD_RELOC_16C_REG04},
64
  {R_16C_REG04_C,   BFD_RELOC_16C_REG04_C},
65
  {R_16C_REG04a,    BFD_RELOC_16C_REG04a},
66
  {R_16C_REG04a_C,  BFD_RELOC_16C_REG04a_C},
67
  {R_16C_REG14,     BFD_RELOC_16C_REG14},
68
  {R_16C_REG14_C,   BFD_RELOC_16C_REG14_C},
69
  {R_16C_REG16,     BFD_RELOC_16C_REG16},
70
  {R_16C_REG16_C,   BFD_RELOC_16C_REG16_C},
71
  {R_16C_REG20,     BFD_RELOC_16C_REG20},
72
  {R_16C_REG20_C,   BFD_RELOC_16C_REG20_C},
73
  {R_16C_ABS20,     BFD_RELOC_16C_ABS20},
74
  {R_16C_ABS20_C,   BFD_RELOC_16C_ABS20_C},
75
  {R_16C_ABS24,     BFD_RELOC_16C_ABS24},
76
  {R_16C_ABS24_C,   BFD_RELOC_16C_ABS24_C},
77
  {R_16C_IMM04,     BFD_RELOC_16C_IMM04},
78
  {R_16C_IMM04_C,   BFD_RELOC_16C_IMM04_C},
79
  {R_16C_IMM16,     BFD_RELOC_16C_IMM16},
80
  {R_16C_IMM16_C,   BFD_RELOC_16C_IMM16_C},
81
  {R_16C_IMM20,     BFD_RELOC_16C_IMM20},
82
  {R_16C_IMM20_C,   BFD_RELOC_16C_IMM20_C},
83
  {R_16C_IMM24,     BFD_RELOC_16C_IMM24},
84
  {R_16C_IMM24_C,   BFD_RELOC_16C_IMM24_C},
85
  {R_16C_IMM32,     BFD_RELOC_16C_IMM32},
86
  {R_16C_IMM32_C,   BFD_RELOC_16C_IMM32_C}
87
};
88
 
89
static reloc_howto_type elf_howto_table[] =
90
{
91
  /* 00 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM08),
92
  /* 01 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM08_C),
93
  /* 02 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM16),
94
  /* 03 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM16_C),
95
  /* 04 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM32),
96
  /* 05 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM32_C),
97
  /* 06 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP04),
98
  /* 07 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP04_C),
99
  /* 08 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP08),
100
  /* 09 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP08_C),
101
  /* 10 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP16),
102
  /* 11 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP16_C),
103
  /* 12 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP24),
104
  /* 13 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP24_C),
105
  /* 14 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP24a),
106
  /* 15 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP24a_C),
107
  /* 16 */ ONLY_NAME_HOWTO (RINDEX_16C_REG04),
108
  /* 17 */ ONLY_NAME_HOWTO (RINDEX_16C_REG04_C),
109
  /* 18 */ ONLY_NAME_HOWTO (RINDEX_16C_REG04a),
110
  /* 19 */ ONLY_NAME_HOWTO (RINDEX_16C_REG04a_C),
111
  /* 20 */ ONLY_NAME_HOWTO (RINDEX_16C_REG14),
112
  /* 21 */ ONLY_NAME_HOWTO (RINDEX_16C_REG14_C),
113
  /* 22 */ ONLY_NAME_HOWTO (RINDEX_16C_REG16),
114
  /* 23 */ ONLY_NAME_HOWTO (RINDEX_16C_REG16_C),
115
  /* 24 */ ONLY_NAME_HOWTO (RINDEX_16C_REG20),
116
  /* 25 */ ONLY_NAME_HOWTO (RINDEX_16C_REG20_C),
117
  /* 26 */ ONLY_NAME_HOWTO (RINDEX_16C_ABS20),
118
  /* 27 */ ONLY_NAME_HOWTO (RINDEX_16C_ABS20_C),
119
  /* 28 */ ONLY_NAME_HOWTO (RINDEX_16C_ABS24),
120
  /* 29 */ ONLY_NAME_HOWTO (RINDEX_16C_ABS24_C),
121
  /* 30 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM04),
122
  /* 31 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM04_C),
123
  /* 32 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM16),
124
  /* 33 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM16_C),
125
  /* 34 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM20),
126
  /* 35 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM20_C),
127
  /* 36 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM24),
128
  /* 37 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM24_C),
129
  /* 38 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM32),
130
  /* 39 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM32_C)
131
};
132
 
133
 
134
/* Code to turn a code_type into a howto ptr, uses the above howto table.  */
135
 
136
static reloc_howto_type *
137
elf_cr16c_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
138
                             bfd_reloc_code_real_type code)
139
{
140
  unsigned int i;
141
 
142
  for (i = 0; i < RINDEX_16C_MAX; i++)
143
    {
144
      if (code == reloc_map_index[i].bfd_reloc_enum)
145
        {
146
          /* printf ("CR16C Relocation Type is - %x\n", code); */
147
          return & elf_howto_table[i];
148
        }
149
    }
150
 
151
  /* printf ("This relocation Type is not supported - %x\n", code); */
152
  return 0;
153
}
154
 
155
static reloc_howto_type *
156
elf_cr16c_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
157
                             const char *r_name)
158
{
159
  unsigned int i;
160
 
161
  for (i = 0; i < sizeof (elf_howto_table) / sizeof (elf_howto_table[0]); i++)
162
    if (elf_howto_table[i].name != NULL
163
        && strcasecmp (elf_howto_table[i].name, r_name) == 0)
164
      return &elf_howto_table[i];
165
 
166
  return NULL;
167
}
168
 
169
static void
170
elf_cr16c_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
171
                         arelent *cache_ptr ATTRIBUTE_UNUSED,
172
                         Elf_Internal_Rela *dst ATTRIBUTE_UNUSED)
173
{
174
  abort ();
175
}
176
 
177
static void
178
elf_cr16c_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
179
                             arelent *cache_ptr,
180
                             Elf_Internal_Rela *dst)
181
{
182
  unsigned int r_type = ELF32_R_TYPE (dst->r_info);
183
 
184
  BFD_ASSERT (r_type < (unsigned int) RINDEX_16C_MAX);
185
  cache_ptr->howto = &elf_howto_table[r_type];
186
}
187
 
188
/* Perform a relocation as part of a final link.  */
189
 
190
static bfd_reloc_status_type
191
cr16c_elf_final_link_relocate (reloc_howto_type *howto,
192
                               bfd *abfd,
193
                               bfd *output_bfd ATTRIBUTE_UNUSED,
194
                               asection *input_section,
195
                               bfd_byte *data,
196
                               bfd_vma octets,
197
                               bfd_vma Rvalue,
198
                               bfd_vma addend ATTRIBUTE_UNUSED,
199
                               struct bfd_link_info *info ATTRIBUTE_UNUSED,
200
                               asection *sym_sec ATTRIBUTE_UNUSED,
201
                               int is_local ATTRIBUTE_UNUSED)
202
{
203
  long value;
204
  short sword;                  /* Extracted from the hole and put back.  */
205
  unsigned long format, addr_type, code_factor;
206
  unsigned short size;
207
  unsigned short r_type;
208
 
209
  unsigned long disp20_opcod;
210
  char neg = 0;
211
  char neg2pos = 0;
212
 
213
  long left_val = 0;
214
  long plus_factor = 0;          /* To be added to the hole.  */
215
 
216
#define MIN_BYTE        ((int) 0xFFFFFF80)
217
#define MIN_WORD        ((int) 0xFFFF8000)
218
#define MAX_UWORD       ((unsigned) 0x0000FFFF)
219
#define MAX_UBYTE       ((unsigned) 0x000000FF)
220
 
221
  r_type = reloc_map_index[howto->type].cr_reloc_type;
222
  format = r_type & R_FORMAT;
223
  size = r_type & R_SIZESP;
224
  addr_type = r_type & R_ADDRTYPE;
225
  code_factor = ((addr_type == R_CODE_ADDR) ? 1 : 0);
226
 
227
  switch (format)
228
    {
229
    case R_NUMBER:
230
      switch (size)
231
        {
232
        case R_S_16C_08:        /* One byte.  */
233
          value = bfd_get_8 (abfd, (char *) data + octets);
234
          break;
235
        case R_S_16C_16:        /* Two bytes. */
236
          sword = bfd_get_16 (abfd, (bfd_byte *) data + octets);
237
          value = sword;
238
          break;
239
        case R_S_16C_32:        /* Four bytes.  */
240
          value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
241
          break;
242
        default:
243
          return bfd_reloc_notsupported;
244
        }
245
      break;
246
 
247
    case R_16C_DISPL:
248
      switch (size)
249
        {
250
        case R_S_16C_04:    /* word1(4-7).  */
251
          value = bfd_get_8 (abfd, (char *) data + octets);
252
          left_val = value & 0xF;
253
          value = (value & 0xF0) >> 4;
254
          value++;
255
          value <<= 1;
256
          break;
257
        case R_S_16C_08:    /* word1(0-3,8-11).  */
258
          sword = bfd_get_16 (abfd, (char *) data + octets);
259
          value = sword & 0x000F;
260
          value |= ((sword & 0x0F00) >> 4);
261
          left_val = sword & 0xF0F0;
262
          value <<= 1;
263
          if (value & 0x100)
264
            value |= 0xFFFFFF00;
265
          break;
266
        case R_S_16C_16:    /* word2.  */
267
          sword = bfd_get_16 (abfd, (bfd_byte *) data + octets);
268
          value = sword;
269
          value = ((value & 0xFFFE) >> 1) | ((value & 0x1) << 15);
270
          value <<= 1;
271
          if (value & 0x10000)
272
            value |= 0xFFFF0000;
273
          break;
274
        case R_S_16C_24_a:      /* word1(0-7),word2.  */
275
          value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
276
          left_val = value & 0x0000FF00;
277
          value = ((value & 0xFFFE0000) >> 17) |
278
            ((value & 0x00010000) << 7) | ((value & 0x000000FF) << 15);
279
          value <<= 1;
280
          if (value & 0x1000000)
281
            value |= 0xFE000000;
282
          break;
283
        case R_S_16C_24:    /* word2(0-3,8-11),word3.  */
284
          value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
285
          left_val = value & 0x0000F0F0;
286
          value = ((value >> 16) & 0x0000FFFF) |
287
            ((value & 0x00000F00) << 8) | ((value & 0x0000000F) << 20);
288
 
289
          value = ((value & 0x00FFFFFE) >> 1) | ((value & 0x00000001) << 23);
290
 
291
          value <<= 1;
292
          if (value & 0x1000000)
293
            value |= 0xFE000000;
294
          break;
295
        default:
296
          return bfd_reloc_notsupported;
297
        }
298
      break;
299
 
300
    case R_16C_REGREL:
301
      switch (size)
302
        {
303
        case R_S_16C_04:    /* word1(12-15) not scaled.  */
304
          value = bfd_get_8 (abfd, (char *) data + octets);
305
          left_val = value & 0xF0;
306
          value = value & 0xF;
307
          break;
308
        case R_S_16C_04_a:      /* word1(12-15) scaled by 2.  */
309
          value = bfd_get_8 (abfd, (char *) data + octets);
310
          left_val = value & 0xF0;
311
          value = value & 0xF;
312
          value <<= 1;
313
          break;
314
        case R_S_16C_14:    /* word1(4-5),word2(0-3,8-15).  */
315
          value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
316
          left_val = value & 0x00F0FFCF;
317
          value = ((value & 0xc0000000) >> 24) |
318
            ((value & 0x3F000000) >> 16) |
319
            ((value & 0x000F0000) >> 16) | (value & 0x00000030);
320
          break;
321
        case R_S_16C_16:    /* word2.  */
322
          sword = bfd_get_16 (abfd, (bfd_byte *) data + octets);
323
          value = sword;
324
          break;
325
        case R_S_16C_20:    /* word2(8-11),word3.  */
326
          value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
327
          left_val = value & 0xF0;
328
          value = (value & 0xF) << 16;
329
          sword = bfd_get_16 (abfd, (bfd_byte *) data + octets + 1);
330
          value = value | (unsigned short) sword;
331
          disp20_opcod = bfd_get_32 (abfd, (bfd_byte *) data + octets - 3);
332
          disp20_opcod |= 0x0FFF0000;
333
          if ((disp20_opcod == 0x4FFF0018) ||   /* loadb -disp20(reg) */
334
              (disp20_opcod == 0x5FFF0018) ||   /* loadb -disp20(rp)  */
335
              (disp20_opcod == 0x8FFF0018) ||   /* loadd -disp20(reg) */
336
              (disp20_opcod == 0x9FFF0018) ||   /* loadd -disp20(rp)  */
337
              (disp20_opcod == 0xCFFF0018) ||   /* loadw -disp20(reg) */
338
              (disp20_opcod == 0xDFFF0018) ||   /* loadw -disp20(rp)  */
339
              (disp20_opcod == 0x4FFF0019) ||   /* storb -disp20(reg) */
340
              (disp20_opcod == 0x5FFF0019) ||   /* storb -disp20(rp)  */
341
              (disp20_opcod == 0x8FFF0019) ||   /* stord -disp20(reg) */
342
              (disp20_opcod == 0x9FFF0019) ||   /* stord -disp20(rp)  */
343
              (disp20_opcod == 0xCFFF0019) ||   /* storw -disp20(reg) */
344
              (disp20_opcod == 0xDFFF0019))
345
            {   /* storw -disp20(rp).  */
346
              neg = 1;
347
              value |= 0xFFF00000;
348
            }
349
 
350
          break;
351
        default:
352
          return bfd_reloc_notsupported;
353
        }
354
      break;
355
 
356
    case R_16C_ABS:
357
      switch (size)
358
        {
359
        case R_S_16C_20:    /* word1(0-3),word2.  */
360
          value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
361
          left_val = value & 0x0000FFF0;
362
          value = ((value & 0xFFFF0000) >> 16) |
363
            ((value & 0x0000000F) << 16);
364
          break;
365
        case R_S_16C_24:   /* word2(0-3,8-11),word3.  */
366
          value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
367
          left_val = value & 0x0000F0F0;
368
          value = ((value & 0xFFFF0000) >> 16) |
369
            ((value & 0x00000F00) << 8) | ((value & 0x0000000F) << 20);
370
          break;
371
        default:
372
          return bfd_reloc_notsupported;
373
        }
374
      break;
375
 
376
    case R_16C_IMMED:
377
      switch (size)
378
        {
379
        case R_S_16C_04:    /* word1/2(4-7).  */
380
          value = bfd_get_8 (abfd, (char *) data + octets);
381
          left_val = value & 0xF;
382
          value = (value & 0xF0) >> 4;
383
          break;
384
        case R_S_16C_16:    /* word2.  */
385
          sword = bfd_get_16 (abfd, (bfd_byte *) data + octets);
386
          value = sword;
387
          break;
388
        case R_S_16C_20:    /* word1(0-3),word2.  */
389
          value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
390
          left_val = value & 0x0000FFF0;
391
          value = ((value & 0xFFFF0000) >> 16) |
392
            ((value & 0x0000000F) << 16);
393
          break;
394
        case R_S_16C_32:    /* word2, word3.  */
395
          value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
396
          value = ((value & 0x0000FFFF) << 16) |
397
            ((value & 0xFFFF0000) >> 16);
398
          break;
399
        default:
400
          return bfd_reloc_notsupported;
401
        }
402
      break;
403
    default:
404
      return bfd_reloc_notsupported;
405
    }
406
 
407
  switch ((r_type & R_RELTO) >> 4)
408
    {
409
 
410
    case 0:      /* R_ABS.  */
411
      plus_factor = Rvalue;
412
      break;
413
    case 1:     /* R_PCREL.  */
414
      plus_factor = Rvalue -
415
        (input_section->output_section->vma + input_section->output_offset);
416
      break;
417
    default:
418
      return bfd_reloc_notsupported;
419
    }
420
 
421
  if (neg)
422
    {
423
      if (plus_factor >= -value)
424
        neg2pos = 1;
425
      /* We need to change load/stor with negative
426
         displ opcode to positive disp opcode (CR16C).  */
427
    }
428
 
429
  value = value + (plus_factor >> code_factor);
430
 
431
  switch (format)
432
    {
433
    case R_NUMBER:
434
      switch (size)
435
        {
436
        case R_S_16C_08:        /* One byte.  */
437
          if (value > (int) MAX_UBYTE || value < MIN_BYTE)
438
            return bfd_reloc_overflow;
439
          value &= 0xFF;
440
          bfd_put_8 (abfd, (bfd_vma) value, (unsigned char *) data + octets);
441
          break;
442
 
443
        case R_S_16C_16:        /* Two bytes.  */
444
          if (value > (int) MAX_UWORD || value < MIN_WORD)
445
            return bfd_reloc_overflow;
446
          value &= 0xFFFF;
447
          sword = value;
448
          bfd_put_16 (abfd, (bfd_vma) sword,
449
                      (unsigned char *) data + octets);
450
          break;
451
 
452
        case R_S_16C_32:        /* Four bytes.  */
453
          value &= 0xFFFFFFFF;
454
          bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
455
          break;
456
 
457
        default:
458
          return bfd_reloc_notsupported;
459
        }
460
      break;
461
 
462
    case R_16C_DISPL:
463
      switch (size)
464
        {
465
        case R_S_16C_04:        /* word1(4-7).  */
466
          if ((value - 32) > 32 || value < 2)
467
            return bfd_reloc_overflow;
468
          value >>= 1;
469
          value--;
470
          value &= 0xF;
471
          value <<= 4;
472
          value |= left_val;
473
          bfd_put_8 (abfd, (bfd_vma) value, (unsigned char *) data + octets);
474
          break;
475
 
476
        case R_S_16C_08:    /* word1(0-3,8-11).  */
477
          if (value > 255 || value < -256 || value == 0x80)
478
            return bfd_reloc_overflow;
479
          value &= 0x1FF;
480
          value >>= 1;
481
          sword = value & 0x000F;
482
          sword |= (value & 0x00F0) << 4;
483
          sword |= left_val;
484
          bfd_put_16 (abfd, (bfd_vma) sword,
485
                      (unsigned char *) data + octets);
486
          break;
487
 
488
        case R_S_16C_16:    /* word2.  */
489
          if (value > 65535 || value < -65536)
490
            return bfd_reloc_overflow;
491
          value >>= 1;
492
          value &= 0xFFFF;
493
          value = ((value & 0x8000) >> 15) | ((value & 0x7FFF) << 1);
494
          sword = value;
495
          bfd_put_16 (abfd, (bfd_vma) sword,
496
                      (unsigned char *) data + octets);
497
          break;
498
 
499
        case R_S_16C_24_a:      /* word1(0-7),word2.  */
500
          if (value > 16777215 || value < -16777216)
501
            return bfd_reloc_overflow;
502
          value &= 0x1FFFFFF;
503
          value >>= 1;
504
          value = ((value & 0x00007FFF) << 17) |
505
            ((value & 0x00800000) >> 7) | ((value & 0x007F8000) >> 15);
506
          value |= left_val;
507
          bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
508
          break;
509
 
510
        case R_S_16C_24:    /* word2(0-3,8-11),word3.  */
511
          if (value > 16777215 || value < -16777216)
512
            return bfd_reloc_overflow;
513
          value &= 0x1FFFFFF;
514
          value >>= 1;
515
 
516
          value = ((value & 0x007FFFFF) << 1) | ((value & 0x00800000) >> 23);
517
 
518
          value = ((value & 0x0000FFFF) << 16) |
519
            ((value & 0x000F0000) >> 8) | ((value & 0x00F00000) >> 20);
520
          value |= left_val;
521
          bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
522
          break;
523
 
524
        default:
525
          return bfd_reloc_notsupported;
526
        }
527
      break;
528
 
529
    case R_16C_REGREL:
530
      switch (size)
531
        {
532
        case R_S_16C_04:        /* word1(12-15) not scaled.  */
533
          if (value > 13 || value < 0)
534
            return bfd_reloc_overflow;
535
          value &= 0xF;
536
          value |= left_val;
537
          bfd_put_8 (abfd, (bfd_vma) value, (unsigned char *) data + octets);
538
          break;
539
 
540
        case R_S_16C_04_a:      /* word1(12-15) not scaled.  */
541
          if (value > 26 || value < 0)
542
            return bfd_reloc_overflow;
543
          value &= 0x1F;
544
          value >>= 1;
545
          value |= left_val;
546
          bfd_put_8 (abfd, (bfd_vma) value, (unsigned char *) data + octets);
547
          break;
548
 
549
        case R_S_16C_14:        /* word1(4-5),word2(0-3,8-15).  */
550
          if (value < 0 || value > 16383)
551
            return bfd_reloc_overflow;
552
          value &= 0x3FFF;
553
          value = ((value & 0x000000c0) << 24) |
554
            ((value & 0x00003F00) << 16) |
555
            ((value & 0x0000000F) << 16) | (value & 0x00000030);
556
          value |= left_val;
557
          bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
558
          break;
559
 
560
        case R_S_16C_16:        /* word2.  */
561
          if (value > 65535 || value < 0)
562
            return bfd_reloc_overflow;
563
          value &= 0xFFFF;
564
          sword = value;
565
          bfd_put_16 (abfd, (bfd_vma) sword,
566
                      (unsigned char *) data + octets);
567
          break;
568
 
569
        case R_S_16C_20:        /* word2(8-11),word3.  */
570
          /* if (value > 1048575 || value < 0) RELOC_ERROR(1); */
571
          value &= 0xFFFFF;
572
          sword = value & 0x0000FFFF;
573
          value = (value & 0x000F0000) >> 16;
574
          value |= left_val;
575
          bfd_put_8 (abfd, (bfd_vma) value, (unsigned char *) data + octets);
576
          bfd_put_16 (abfd, (bfd_vma) sword,
577
                      (unsigned char *) data + octets + 1);
578
          if (neg2pos)
579
            {
580
              /* Change load/stor negative displ opcode
581
                 to load/stor positive displ opcode.  */
582
              value = bfd_get_8 (abfd, (char *) data + octets - 3);
583
              value &= 0xF7;
584
              value |= 0x2;
585
              bfd_put_8 (abfd, (bfd_vma) value,
586
                         (unsigned char *) data + octets - 3);
587
            }
588
          break;
589
 
590
        default:
591
          return bfd_reloc_notsupported;
592
        }
593
      break;
594
 
595
    case R_16C_ABS:
596
      switch (size)
597
        {
598
        case R_S_16C_20:        /* word1(0-3),word2.  */
599
          if (value > 1048575 || value < 0)
600
            return bfd_reloc_overflow;
601
          value &= 0xFFFFF;
602
          value = ((value & 0x0000FFFF) << 16) |
603
            ((value & 0x000F0000) >> 16);
604
          value |= left_val;
605
          bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
606
          break;
607
 
608
        case R_S_16C_24:        /* word2(0-3,8-11),word3.  */
609
          /* if (value > 16777215 || value < 0) RELOC_ERROR(1); */
610
          value &= 0xFFFFFF;
611
          value = ((value & 0x0000FFFF) << 16) |
612
            ((value & 0x000F0000) >> 8) | ((value & 0x00F00000) >> 20);
613
          value |= left_val;
614
          bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
615
          break;
616
 
617
        default:
618
          return bfd_reloc_notsupported;
619
        }
620
      break;
621
 
622
    case R_16C_IMMED:
623
      switch (size)
624
        {
625
        case R_S_16C_04:        /* word1/2(4-7).  */
626
          if (value > 15 || value < -1)
627
            return bfd_reloc_overflow;
628
          value &= 0xF;
629
          value <<= 4;
630
          value |= left_val;
631
          bfd_put_8 (abfd, (bfd_vma) value, (unsigned char *) data + octets);
632
          break;
633
 
634
        case R_S_16C_16:        /* word2.  */
635
          if (value > 32767 || value < -32768)
636
            return bfd_reloc_overflow;
637
          value &= 0xFFFF;
638
          sword = value;
639
          bfd_put_16 (abfd, (bfd_vma) sword,
640
                      (unsigned char *) data + octets);
641
          break;
642
 
643
        case R_S_16C_20:        /* word1(0-3),word2.  */
644
          if (value > 1048575 || value < 0)
645
            return bfd_reloc_overflow;
646
          value &= 0xFFFFF;
647
          value = ((value & 0x0000FFFF) << 16) |
648
            ((value & 0x000F0000) >> 16);
649
          value |= left_val;
650
          bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
651
          break;
652
 
653
        case R_S_16C_32:        /* word2, word3.  */
654
          value &= 0xFFFFFFFF;
655
          value = ((value & 0x0000FFFF) << 16) |
656
            ((value & 0xFFFF0000) >> 16);
657
          bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
658
          break;
659
 
660
        default:
661
          return bfd_reloc_notsupported;
662
        }
663
      break;
664
    default:
665
      return bfd_reloc_notsupported;
666
    }
667
 
668
  return bfd_reloc_ok;
669
}
670
 
671
/* Relocate a CR16C ELF section.  */
672
 
673
static bfd_boolean
674
elf32_cr16c_relocate_section (bfd *output_bfd,
675
                              struct bfd_link_info *info,
676
                              bfd *input_bfd,
677
                              asection *input_section,
678
                              bfd_byte *contents,
679
                              Elf_Internal_Rela *relocs,
680
                              Elf_Internal_Sym *local_syms,
681
                              asection **local_sections)
682
{
683
  Elf_Internal_Shdr *symtab_hdr;
684
  struct elf_link_hash_entry **sym_hashes;
685
  Elf_Internal_Rela *rel, *relend;
686
 
687
  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
688
  sym_hashes = elf_sym_hashes (input_bfd);
689
 
690
  rel = relocs;
691
  relend = relocs + input_section->reloc_count;
692
  for (; rel < relend; rel++)
693
    {
694
      int r_type;
695
      reloc_howto_type *howto;
696
      unsigned long r_symndx;
697
      Elf_Internal_Sym *sym;
698
      asection *sec;
699
      struct elf_link_hash_entry *h;
700
      bfd_vma relocation;
701
      bfd_reloc_status_type r;
702
 
703
      r_symndx = ELF32_R_SYM (rel->r_info);
704
      r_type = ELF32_R_TYPE (rel->r_info);
705
      howto = elf_howto_table + r_type;
706
 
707
      h = NULL;
708
      sym = NULL;
709
      sec = NULL;
710
      if (r_symndx < symtab_hdr->sh_info)
711
        {
712
          sym = local_syms + r_symndx;
713
          sec = local_sections[r_symndx];
714
          relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
715
        }
716
      else
717
        {
718
          bfd_boolean unresolved_reloc, warned;
719
 
720
          RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
721
                                   r_symndx, symtab_hdr, sym_hashes,
722
                                   h, sec, relocation,
723
                                   unresolved_reloc, warned);
724
        }
725
 
726
      if (sec != NULL && elf_discarded_section (sec))
727
        {
728
          /* For relocs against symbols from removed linkonce sections,
729
             or sections discarded by a linker script, we just want the
730
             section contents zeroed.  Avoid any special processing.  */
731
          _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
732
          rel->r_info = 0;
733
          rel->r_addend = 0;
734
          continue;
735
        }
736
 
737
      if (info->relocatable)
738
        {
739
          /* This is a relocatable link.  We don't have to change
740
             anything, unless the reloc is against a section symbol,
741
             in which case we have to adjust according to where the
742
             section symbol winds up in the output section.  */
743
          if (sym != NULL && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
744
            rel->r_addend += sec->output_offset;
745
          continue;
746
        }
747
 
748
      r = cr16c_elf_final_link_relocate (howto, input_bfd, output_bfd,
749
                                         input_section,
750
                                         contents, rel->r_offset,
751
                                         relocation, rel->r_addend,
752
                                         info, sec, h == NULL);
753
 
754
      if (r != bfd_reloc_ok)
755
        {
756
          const char *name;
757
          const char *msg = (const char *) 0;
758
 
759
          if (h != NULL)
760
            name = h->root.root.string;
761
          else
762
            {
763
              name = (bfd_elf_string_from_elf_section
764
                      (input_bfd, symtab_hdr->sh_link, sym->st_name));
765
              if (name == NULL || *name == '\0')
766
                name = bfd_section_name (input_bfd, sec);
767
            }
768
 
769
          switch (r)
770
            {
771
            case bfd_reloc_overflow:
772
              if (!((*info->callbacks->reloc_overflow)
773
                    (info, (h ? &h->root : NULL), name, howto->name,
774
                     (bfd_vma) 0, input_bfd, input_section,
775
                     rel->r_offset)))
776
                return FALSE;
777
              break;
778
 
779
            case bfd_reloc_undefined:
780
              if (!((*info->callbacks->undefined_symbol)
781
                    (info, name, input_bfd, input_section,
782
                     rel->r_offset, TRUE)))
783
                return FALSE;
784
              break;
785
 
786
            case bfd_reloc_outofrange:
787
              msg = _("internal error: out of range error");
788
              goto common_error;
789
 
790
            case bfd_reloc_notsupported:
791
              msg = _("internal error: unsupported relocation error");
792
              goto common_error;
793
 
794
            case bfd_reloc_dangerous:
795
              msg = _("internal error: dangerous error");
796
              goto common_error;
797
 
798
            default:
799
              msg = _("internal error: unknown error");
800
              /* fall through */
801
 
802
            common_error:
803
              if (!((*info->callbacks->warning)
804
                    (info, msg, name, input_bfd, input_section,
805
                     rel->r_offset)))
806
                return FALSE;
807
              break;
808
            }
809
        }
810
    }
811
 
812
  return TRUE;
813
}
814
 
815
/* CR16C ELF uses three common sections:
816
   One is for default common symbols (placed in usual common section).
817
   Second is for near common symbols (placed in "ncommon" section).
818
   Third is for far common symbols (placed in "fcommon" section).
819
   The following implementation is based on elf32-mips architecture */
820
 
821
static asection  cr16c_elf_fcom_section;
822
static asymbol   cr16c_elf_fcom_symbol;
823
static asymbol * cr16c_elf_fcom_symbol_ptr;
824
static asection  cr16c_elf_ncom_section;
825
static asymbol   cr16c_elf_ncom_symbol;
826
static asymbol * cr16c_elf_ncom_symbol_ptr;
827
 
828
/* Given a BFD section, try to locate the
829
   corresponding ELF section index.  */
830
 
831
static bfd_boolean
832
elf32_cr16c_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED,
833
                                      asection *sec,
834
                                      int *retval)
835
{
836
  if (strcmp (bfd_get_section_name (abfd, sec), ".fcommon") == 0)
837
    *retval = SHN_CR16C_FCOMMON;
838
  else if (strcmp (bfd_get_section_name (abfd, sec), ".ncommon") == 0)
839
    *retval = SHN_CR16C_NCOMMON;
840
  else
841
    return FALSE;
842
 
843
  return TRUE;
844
}
845
 
846
/* Handle the special CR16C section numbers that a symbol may use.  */
847
 
848
static void
849
elf32_cr16c_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED,
850
                               asymbol *asym)
851
{
852
  elf_symbol_type *elfsym = (elf_symbol_type *) asym;
853
  unsigned int indx;
854
 
855
  indx = elfsym->internal_elf_sym.st_shndx;
856
 
857
  switch (indx)
858
    {
859
    case SHN_CR16C_FCOMMON:
860
      if (cr16c_elf_fcom_section.name == NULL)
861
        {
862
          /* Initialize the far common section.  */
863
          cr16c_elf_fcom_section.name = ".fcommon";
864
          cr16c_elf_fcom_section.flags = SEC_IS_COMMON | SEC_ALLOC;
865
          cr16c_elf_fcom_section.output_section = &cr16c_elf_fcom_section;
866
          cr16c_elf_fcom_section.symbol = &cr16c_elf_fcom_symbol;
867
          cr16c_elf_fcom_section.symbol_ptr_ptr = &cr16c_elf_fcom_symbol_ptr;
868
          cr16c_elf_fcom_symbol.name = ".fcommon";
869
          cr16c_elf_fcom_symbol.flags = BSF_SECTION_SYM;
870
          cr16c_elf_fcom_symbol.section = &cr16c_elf_fcom_section;
871
          cr16c_elf_fcom_symbol_ptr = &cr16c_elf_fcom_symbol;
872
        }
873
      asym->section = &cr16c_elf_fcom_section;
874
      asym->value = elfsym->internal_elf_sym.st_size;
875
      break;
876
    case SHN_CR16C_NCOMMON:
877
      if (cr16c_elf_ncom_section.name == NULL)
878
        {
879
          /* Initialize the far common section.  */
880
          cr16c_elf_ncom_section.name = ".ncommon";
881
          cr16c_elf_ncom_section.flags = SEC_IS_COMMON | SEC_ALLOC;
882
          cr16c_elf_ncom_section.output_section = &cr16c_elf_ncom_section;
883
          cr16c_elf_ncom_section.symbol = &cr16c_elf_ncom_symbol;
884
          cr16c_elf_ncom_section.symbol_ptr_ptr = &cr16c_elf_ncom_symbol_ptr;
885
          cr16c_elf_ncom_symbol.name = ".ncommon";
886
          cr16c_elf_ncom_symbol.flags = BSF_SECTION_SYM;
887
          cr16c_elf_ncom_symbol.section = &cr16c_elf_ncom_section;
888
          cr16c_elf_ncom_symbol_ptr = &cr16c_elf_ncom_symbol;
889
        }
890
      asym->section = &cr16c_elf_ncom_section;
891
      asym->value = elfsym->internal_elf_sym.st_size;
892
      break;
893
    }
894
}
895
 
896
/* Hook called by the linker routine which adds symbols from an object
897
   file.  We must handle the special cr16c section numbers here.  */
898
 
899
static bfd_boolean
900
elf32_cr16c_add_symbol_hook (bfd *abfd,
901
                             struct bfd_link_info *info ATTRIBUTE_UNUSED,
902
                             Elf_Internal_Sym *sym,
903
                             const char **namep ATTRIBUTE_UNUSED,
904
                             flagword *flagsp ATTRIBUTE_UNUSED,
905
                             asection **secp,
906
                             bfd_vma *valp)
907
{
908
  unsigned int indx = sym->st_shndx;
909
 
910
  switch (indx)
911
    {
912
    case SHN_CR16C_FCOMMON:
913
      *secp = bfd_make_section_old_way (abfd, ".fcommon");
914
      (*secp)->flags |= SEC_IS_COMMON;
915
      *valp = sym->st_size;
916
      break;
917
    case SHN_CR16C_NCOMMON:
918
      *secp = bfd_make_section_old_way (abfd, ".ncommon");
919
      (*secp)->flags |= SEC_IS_COMMON;
920
      *valp = sym->st_size;
921
      break;
922
    }
923
 
924
  return TRUE;
925
}
926
 
927
static int
928
elf32_cr16c_link_output_symbol_hook (struct bfd_link_info *info ATTRIBUTE_UNUSED,
929
                                     const char *name ATTRIBUTE_UNUSED,
930
                                     Elf_Internal_Sym *sym,
931
                                     asection *input_sec,
932
                                     struct elf_link_hash_entry *h ATTRIBUTE_UNUSED)
933
{
934
  /* If we see a common symbol, which implies a relocatable link, then
935
     if a symbol was in a special common section in an input file, mark
936
     it as a special common in the output file.  */
937
 
938
  if (sym->st_shndx == SHN_COMMON)
939
    {
940
      if (strcmp (input_sec->name, ".fcommon") == 0)
941
        sym->st_shndx = SHN_CR16C_FCOMMON;
942
      else if (strcmp (input_sec->name, ".ncommon") == 0)
943
        sym->st_shndx = SHN_CR16C_NCOMMON;
944
    }
945
 
946
  return 1;
947
}
948
 
949
/* Definitions for setting CR16C target vector.  */
950
#define TARGET_LITTLE_SYM               bfd_elf32_cr16c_vec
951
#define TARGET_LITTLE_NAME              "elf32-cr16c"
952
#define ELF_ARCH                        bfd_arch_cr16c
953
#define ELF_MACHINE_CODE                EM_CR
954
#define ELF_MAXPAGESIZE                 0x1
955
#define elf_symbol_leading_char         '_'
956
 
957
#define bfd_elf32_bfd_reloc_type_lookup         elf_cr16c_reloc_type_lookup
958
#define bfd_elf32_bfd_reloc_name_lookup elf_cr16c_reloc_name_lookup
959
#define elf_info_to_howto                       elf_cr16c_info_to_howto
960
#define elf_info_to_howto_rel                   elf_cr16c_info_to_howto_rel
961
#define elf_backend_relocate_section            elf32_cr16c_relocate_section
962
#define elf_backend_symbol_processing           elf32_cr16c_symbol_processing
963
#define elf_backend_section_from_bfd_section    elf32_cr16c_section_from_bfd_section
964
#define elf_backend_add_symbol_hook             elf32_cr16c_add_symbol_hook
965
#define elf_backend_link_output_symbol_hook     elf32_cr16c_link_output_symbol_hook
966
 
967
#define elf_backend_can_gc_sections     1
968
 
969
#include "elf32-target.h"

powered by: WebSVN 2.1.0

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