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

Subversion Repositories openrisc_me

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

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

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

powered by: WebSVN 2.1.0

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