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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [bfd/] [elf32-cr16c.c] - Blame information for rev 167

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

Line No. Rev Author Line
1 14 khays
/* 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
        RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
728
                                         rel, relend, howto, contents);
729
 
730
      if (info->relocatable)
731
        {
732
          /* This is a relocatable link.  We don't have to change
733
             anything, unless the reloc is against a section symbol,
734
             in which case we have to adjust according to where the
735
             section symbol winds up in the output section.  */
736
          if (sym != NULL && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
737
            rel->r_addend += sec->output_offset;
738
          continue;
739
        }
740
 
741
      r = cr16c_elf_final_link_relocate (howto, input_bfd, output_bfd,
742
                                         input_section,
743
                                         contents, rel->r_offset,
744
                                         relocation, rel->r_addend,
745
                                         info, sec, h == NULL);
746
 
747
      if (r != bfd_reloc_ok)
748
        {
749
          const char *name;
750
          const char *msg = (const char *) 0;
751
 
752
          if (h != NULL)
753
            name = h->root.root.string;
754
          else
755
            {
756
              name = (bfd_elf_string_from_elf_section
757
                      (input_bfd, symtab_hdr->sh_link, sym->st_name));
758
              if (name == NULL || *name == '\0')
759
                name = bfd_section_name (input_bfd, sec);
760
            }
761
 
762
          switch (r)
763
            {
764
            case bfd_reloc_overflow:
765
              if (!((*info->callbacks->reloc_overflow)
766
                    (info, (h ? &h->root : NULL), name, howto->name,
767
                     (bfd_vma) 0, input_bfd, input_section,
768
                     rel->r_offset)))
769
                return FALSE;
770
              break;
771
 
772
            case bfd_reloc_undefined:
773
              if (!((*info->callbacks->undefined_symbol)
774
                    (info, name, input_bfd, input_section,
775
                     rel->r_offset, TRUE)))
776
                return FALSE;
777
              break;
778
 
779
            case bfd_reloc_outofrange:
780
              msg = _("internal error: out of range error");
781
              goto common_error;
782
 
783
            case bfd_reloc_notsupported:
784
              msg = _("internal error: unsupported relocation error");
785
              goto common_error;
786
 
787
            case bfd_reloc_dangerous:
788
              msg = _("internal error: dangerous error");
789
              goto common_error;
790
 
791
            default:
792
              msg = _("internal error: unknown error");
793
              /* fall through */
794
 
795
            common_error:
796
              if (!((*info->callbacks->warning)
797
                    (info, msg, name, input_bfd, input_section,
798
                     rel->r_offset)))
799
                return FALSE;
800
              break;
801
            }
802
        }
803
    }
804
 
805
  return TRUE;
806
}
807
 
808
/* CR16C ELF uses three common sections:
809
   One is for default common symbols (placed in usual common section).
810
   Second is for near common symbols (placed in "ncommon" section).
811
   Third is for far common symbols (placed in "fcommon" section).
812
   The following implementation is based on elf32-mips architecture */
813
 
814
static asection  cr16c_elf_fcom_section;
815
static asymbol   cr16c_elf_fcom_symbol;
816
static asymbol * cr16c_elf_fcom_symbol_ptr;
817
static asection  cr16c_elf_ncom_section;
818
static asymbol   cr16c_elf_ncom_symbol;
819
static asymbol * cr16c_elf_ncom_symbol_ptr;
820
 
821
/* Given a BFD section, try to locate the
822
   corresponding ELF section index.  */
823
 
824
static bfd_boolean
825
elf32_cr16c_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED,
826
                                      asection *sec,
827
                                      int *retval)
828
{
829
  if (strcmp (bfd_get_section_name (abfd, sec), ".fcommon") == 0)
830
    *retval = SHN_CR16C_FCOMMON;
831
  else if (strcmp (bfd_get_section_name (abfd, sec), ".ncommon") == 0)
832
    *retval = SHN_CR16C_NCOMMON;
833
  else
834
    return FALSE;
835
 
836
  return TRUE;
837
}
838
 
839
/* Handle the special CR16C section numbers that a symbol may use.  */
840
 
841
static void
842
elf32_cr16c_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED,
843
                               asymbol *asym)
844
{
845
  elf_symbol_type *elfsym = (elf_symbol_type *) asym;
846
  unsigned int indx;
847
 
848
  indx = elfsym->internal_elf_sym.st_shndx;
849
 
850
  switch (indx)
851
    {
852
    case SHN_CR16C_FCOMMON:
853
      if (cr16c_elf_fcom_section.name == NULL)
854
        {
855
          /* Initialize the far common section.  */
856
          cr16c_elf_fcom_section.name = ".fcommon";
857
          cr16c_elf_fcom_section.flags = SEC_IS_COMMON | SEC_ALLOC;
858
          cr16c_elf_fcom_section.output_section = &cr16c_elf_fcom_section;
859
          cr16c_elf_fcom_section.symbol = &cr16c_elf_fcom_symbol;
860
          cr16c_elf_fcom_section.symbol_ptr_ptr = &cr16c_elf_fcom_symbol_ptr;
861
          cr16c_elf_fcom_symbol.name = ".fcommon";
862
          cr16c_elf_fcom_symbol.flags = BSF_SECTION_SYM;
863
          cr16c_elf_fcom_symbol.section = &cr16c_elf_fcom_section;
864
          cr16c_elf_fcom_symbol_ptr = &cr16c_elf_fcom_symbol;
865
        }
866
      asym->section = &cr16c_elf_fcom_section;
867
      asym->value = elfsym->internal_elf_sym.st_size;
868
      break;
869
    case SHN_CR16C_NCOMMON:
870
      if (cr16c_elf_ncom_section.name == NULL)
871
        {
872
          /* Initialize the far common section.  */
873
          cr16c_elf_ncom_section.name = ".ncommon";
874
          cr16c_elf_ncom_section.flags = SEC_IS_COMMON | SEC_ALLOC;
875
          cr16c_elf_ncom_section.output_section = &cr16c_elf_ncom_section;
876
          cr16c_elf_ncom_section.symbol = &cr16c_elf_ncom_symbol;
877
          cr16c_elf_ncom_section.symbol_ptr_ptr = &cr16c_elf_ncom_symbol_ptr;
878
          cr16c_elf_ncom_symbol.name = ".ncommon";
879
          cr16c_elf_ncom_symbol.flags = BSF_SECTION_SYM;
880
          cr16c_elf_ncom_symbol.section = &cr16c_elf_ncom_section;
881
          cr16c_elf_ncom_symbol_ptr = &cr16c_elf_ncom_symbol;
882
        }
883
      asym->section = &cr16c_elf_ncom_section;
884
      asym->value = elfsym->internal_elf_sym.st_size;
885
      break;
886
    }
887
}
888
 
889
/* Hook called by the linker routine which adds symbols from an object
890
   file.  We must handle the special cr16c section numbers here.  */
891
 
892
static bfd_boolean
893
elf32_cr16c_add_symbol_hook (bfd *abfd,
894
                             struct bfd_link_info *info ATTRIBUTE_UNUSED,
895
                             Elf_Internal_Sym *sym,
896
                             const char **namep ATTRIBUTE_UNUSED,
897
                             flagword *flagsp ATTRIBUTE_UNUSED,
898
                             asection **secp,
899
                             bfd_vma *valp)
900
{
901
  unsigned int indx = sym->st_shndx;
902
 
903
  switch (indx)
904
    {
905
    case SHN_CR16C_FCOMMON:
906
      *secp = bfd_make_section_old_way (abfd, ".fcommon");
907
      (*secp)->flags |= SEC_IS_COMMON;
908
      *valp = sym->st_size;
909
      break;
910
    case SHN_CR16C_NCOMMON:
911
      *secp = bfd_make_section_old_way (abfd, ".ncommon");
912
      (*secp)->flags |= SEC_IS_COMMON;
913
      *valp = sym->st_size;
914
      break;
915
    }
916
 
917
  return TRUE;
918
}
919
 
920
static int
921
elf32_cr16c_link_output_symbol_hook (struct bfd_link_info *info ATTRIBUTE_UNUSED,
922
                                     const char *name ATTRIBUTE_UNUSED,
923
                                     Elf_Internal_Sym *sym,
924
                                     asection *input_sec,
925
                                     struct elf_link_hash_entry *h ATTRIBUTE_UNUSED)
926
{
927
  /* If we see a common symbol, which implies a relocatable link, then
928
     if a symbol was in a special common section in an input file, mark
929
     it as a special common in the output file.  */
930
 
931
  if (sym->st_shndx == SHN_COMMON)
932
    {
933
      if (strcmp (input_sec->name, ".fcommon") == 0)
934
        sym->st_shndx = SHN_CR16C_FCOMMON;
935
      else if (strcmp (input_sec->name, ".ncommon") == 0)
936
        sym->st_shndx = SHN_CR16C_NCOMMON;
937
    }
938
 
939
  return 1;
940
}
941
 
942
/* Definitions for setting CR16C target vector.  */
943
#define TARGET_LITTLE_SYM               bfd_elf32_cr16c_vec
944
#define TARGET_LITTLE_NAME              "elf32-cr16c"
945
#define ELF_ARCH                        bfd_arch_cr16c
946
#define ELF_MACHINE_CODE                EM_CR
947
#define ELF_MAXPAGESIZE                 0x1
948
#define elf_symbol_leading_char         '_'
949
 
950
#define bfd_elf32_bfd_reloc_type_lookup         elf_cr16c_reloc_type_lookup
951
#define bfd_elf32_bfd_reloc_name_lookup elf_cr16c_reloc_name_lookup
952
#define elf_info_to_howto                       elf_cr16c_info_to_howto
953
#define elf_info_to_howto_rel                   elf_cr16c_info_to_howto_rel
954
#define elf_backend_relocate_section            elf32_cr16c_relocate_section
955
#define elf_backend_symbol_processing           elf32_cr16c_symbol_processing
956
#define elf_backend_section_from_bfd_section    elf32_cr16c_section_from_bfd_section
957
#define elf_backend_add_symbol_hook             elf32_cr16c_add_symbol_hook
958
#define elf_backend_link_output_symbol_hook     elf32_cr16c_link_output_symbol_hook
959
 
960
#define elf_backend_can_gc_sections     1
961
 
962
#include "elf32-target.h"

powered by: WebSVN 2.1.0

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