OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

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

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 CR16 ELF
2
   Copyright 2007 Free Software Foundation, Inc.
3
   Written by M R Swami Reddy.
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 Foundation,
19
   Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
20
 
21
#include "sysdep.h"
22
#include "bfd.h"
23
#include "bfdlink.h"
24
#include "libbfd.h"
25
#include "libiberty.h"
26
#include "elf-bfd.h"
27
#include "elf/cr16.h"
28
 
29
/* cr16_reloc_map array maps BFD relocation enum into a CRGAS relocation type.  */
30
 
31
struct cr16_reloc_map
32
{
33
  bfd_reloc_code_real_type bfd_reloc_enum; /* BFD relocation enum.  */
34
  unsigned short cr16_reloc_type;          /* CR16 relocation type.  */
35
};
36
 
37
static const struct cr16_reloc_map cr16_reloc_map[R_CR16_MAX] =
38
{
39
  {BFD_RELOC_NONE,           R_CR16_NONE},
40
  {BFD_RELOC_CR16_NUM8,      R_CR16_NUM8},
41
  {BFD_RELOC_CR16_NUM16,     R_CR16_NUM16},
42
  {BFD_RELOC_CR16_NUM32,     R_CR16_NUM32},
43
  {BFD_RELOC_CR16_NUM32a,    R_CR16_NUM32a},
44
  {BFD_RELOC_CR16_REGREL4,   R_CR16_REGREL4},
45
  {BFD_RELOC_CR16_REGREL4a,  R_CR16_REGREL4a},
46
  {BFD_RELOC_CR16_REGREL14,  R_CR16_REGREL14},
47
  {BFD_RELOC_CR16_REGREL14a, R_CR16_REGREL14a},
48
  {BFD_RELOC_CR16_REGREL16,  R_CR16_REGREL16},
49
  {BFD_RELOC_CR16_REGREL20,  R_CR16_REGREL20},
50
  {BFD_RELOC_CR16_REGREL20a, R_CR16_REGREL20a},
51
  {BFD_RELOC_CR16_ABS20,     R_CR16_ABS20},
52
  {BFD_RELOC_CR16_ABS24,     R_CR16_ABS24},
53
  {BFD_RELOC_CR16_IMM4,      R_CR16_IMM4},
54
  {BFD_RELOC_CR16_IMM8,      R_CR16_IMM8},
55
  {BFD_RELOC_CR16_IMM16,     R_CR16_IMM16},
56
  {BFD_RELOC_CR16_IMM20,     R_CR16_IMM20},
57
  {BFD_RELOC_CR16_IMM24,     R_CR16_IMM24},
58
  {BFD_RELOC_CR16_IMM32,     R_CR16_IMM32},
59
  {BFD_RELOC_CR16_IMM32a,    R_CR16_IMM32a},
60
  {BFD_RELOC_CR16_DISP4,     R_CR16_DISP4},
61
  {BFD_RELOC_CR16_DISP8,     R_CR16_DISP8},
62
  {BFD_RELOC_CR16_DISP16,    R_CR16_DISP16},
63
  {BFD_RELOC_CR16_DISP24,    R_CR16_DISP24},
64
  {BFD_RELOC_CR16_DISP24a,   R_CR16_DISP24a},
65
  {BFD_RELOC_CR16_SWITCH8,   R_CR16_SWITCH8},
66
  {BFD_RELOC_CR16_SWITCH16,  R_CR16_SWITCH16},
67
  {BFD_RELOC_CR16_SWITCH32,  R_CR16_SWITCH32}
68
};
69
 
70
static reloc_howto_type cr16_elf_howto_table[] =
71
{
72
  HOWTO (R_CR16_NONE,              /* type */
73
         0,                        /* rightshift */
74
         2,                        /* size */
75
         32,                       /* bitsize */
76
         FALSE,                    /* pc_relative */
77
         0,                        /* bitpos */
78
         complain_overflow_dont,   /* complain_on_overflow */
79
         bfd_elf_generic_reloc,    /* special_function */
80
         "R_CR16_NONE",            /* name */
81
         FALSE,                    /* partial_inplace */
82
         0,                        /* src_mask */
83
         0,                        /* dst_mask */
84
         FALSE),                   /* pcrel_offset */
85
 
86
  HOWTO (R_CR16_NUM8,              /* type */
87
         0,                        /* rightshift */
88
         0,                        /* size */
89
         8,                        /* bitsize */
90
         FALSE,                    /* pc_relative */
91
         0,                        /* bitpos */
92
         complain_overflow_bitfield,/* complain_on_overflow */
93
         bfd_elf_generic_reloc,    /* special_function */
94
         "R_CR16_NUM8",            /* name */
95
         FALSE,                    /* partial_inplace */
96
         0xff,                     /* src_mask */
97
         0xff,                     /* dst_mask */
98
         FALSE),                   /* pcrel_offset */
99
 
100
  HOWTO (R_CR16_NUM16,             /* type */
101
         0,                        /* rightshift */
102
         1,                        /* size */
103
         16,                       /* bitsize */
104
         FALSE,                    /* pc_relative */
105
         0,                        /* bitpos */
106
         complain_overflow_bitfield,/* complain_on_overflow */
107
         bfd_elf_generic_reloc,    /* special_function */
108
         "R_CR16_NUM16",           /* name */
109
         FALSE,                    /* partial_inplace */
110
         0xffff,                   /* src_mask */
111
         0xffff,                   /* dst_mask */
112
         FALSE),                   /* pcrel_offset */
113
 
114
  HOWTO (R_CR16_NUM32,             /* type */
115
         0,                        /* rightshift */
116
         2,                        /* size */
117
         32,                       /* bitsize */
118
         FALSE,                    /* pc_relative */
119
         0,                        /* bitpos */
120
         complain_overflow_bitfield,/* complain_on_overflow */
121
         bfd_elf_generic_reloc,    /* special_function */
122
         "R_CR16_NUM32",           /* name */
123
         FALSE,                    /* partial_inplace */
124
         0xffffffff,               /* src_mask */
125
         0xffffffff,               /* dst_mask */
126
         FALSE),                   /* pcrel_offset */
127
 
128
  HOWTO (R_CR16_NUM32a,            /* type */
129
         1,                        /* rightshift */
130
         2,                        /* size */
131
         32,                       /* bitsize */
132
         FALSE,                    /* pc_relative */
133
         0,                        /* bitpos */
134
         complain_overflow_bitfield,/* complain_on_overflow */
135
         bfd_elf_generic_reloc,    /* special_function */
136
         "R_CR16_NUM32a",          /* name */
137
         FALSE,                    /* partial_inplace */
138
         0xffffffff,               /* src_mask */
139
         0xffffffff,               /* dst_mask */
140
         FALSE),                   /* pcrel_offset */
141
 
142
  HOWTO (R_CR16_REGREL4,           /* type */
143
         0,                        /* rightshift */
144
         0,                        /* size */
145
         4,                        /* bitsize */
146
         FALSE,                    /* pc_relative */
147
         0,                        /* bitpos */
148
         complain_overflow_bitfield,/* complain_on_overflow */
149
         bfd_elf_generic_reloc,    /* special_function */
150
         "R_CR16_REGREL4",         /* name */
151
         FALSE,                    /* partial_inplace */
152
         0xf,                      /* src_mask */
153
         0xf,                      /* dst_mask */
154
         FALSE),                   /* pcrel_offset */
155
 
156
  HOWTO (R_CR16_REGREL4a,          /* type */
157
         0,                        /* rightshift */
158
         0,                        /* size */
159
         4,                        /* bitsize */
160
         FALSE,                    /* pc_relative */
161
         0,                        /* bitpos */
162
         complain_overflow_bitfield,/* complain_on_overflow */
163
         bfd_elf_generic_reloc,    /* special_function */
164
         "R_CR16_REGREL4a",        /* name */
165
         FALSE,                    /* partial_inplace */
166
         0xf,                      /* src_mask */
167
         0xf,                      /* dst_mask */
168
         FALSE),                   /* pcrel_offset */
169
 
170
  HOWTO (R_CR16_REGREL14,          /* type */
171
         0,                        /* rightshift */
172
         1,                        /* size */
173
         14,                       /* bitsize */
174
         FALSE,                    /* pc_relative */
175
         0,                        /* bitpos */
176
         complain_overflow_bitfield,/* complain_on_overflow */
177
         bfd_elf_generic_reloc,    /* special_function */
178
         "R_CR16_REGREL14",        /* name */
179
         FALSE,                    /* partial_inplace */
180
         0x3fff,                   /* src_mask */
181
         0x3fff,                   /* dst_mask */
182
         FALSE),                   /* pcrel_offset */
183
 
184
  HOWTO (R_CR16_REGREL14a,         /* type */
185
         0,                        /* rightshift */
186
         1,                        /* size */
187
         14,                       /* bitsize */
188
         FALSE,                    /* pc_relative */
189
         0,                        /* bitpos */
190
         complain_overflow_bitfield,/* complain_on_overflow */
191
         bfd_elf_generic_reloc,    /* special_function */
192
         "R_CR16_REGREL14a",       /* name */
193
         FALSE,                    /* partial_inplace */
194
         0x3fff,                   /* src_mask */
195
         0x3fff,                   /* dst_mask */
196
         FALSE),                   /* pcrel_offset */
197
 
198
  HOWTO (R_CR16_REGREL16,          /* type */
199
         0,                        /* rightshift */
200
         1,                        /* size */
201
         16,                       /* bitsize */
202
         FALSE,                    /* pc_relative */
203
         0,                        /* bitpos */
204
         complain_overflow_bitfield,/* complain_on_overflow */
205
         bfd_elf_generic_reloc,    /* special_function */
206
         "R_CR16_REGREL16",        /* name */
207
         FALSE,                    /* partial_inplace */
208
         0xffff,                   /* src_mask */
209
         0xffff,                   /* dst_mask */
210
         FALSE),                   /* pcrel_offset */
211
 
212
  HOWTO (R_CR16_REGREL20,          /* type */
213
         0,                        /* rightshift */
214
         2,                        /* size */
215
         20,                       /* bitsize */
216
         FALSE,                    /* pc_relative */
217
         0,                        /* bitpos */
218
         complain_overflow_bitfield,/* complain_on_overflow */
219
         bfd_elf_generic_reloc,    /* special_function */
220
         "R_CR16_REGREL20",        /* name */
221
         FALSE,                    /* partial_inplace */
222
         0xfffff,                  /* src_mask */
223
         0xfffff,                  /* dst_mask */
224
         FALSE),                   /* pcrel_offset */
225
 
226
  HOWTO (R_CR16_REGREL20a,         /* type */
227
         0,                        /* rightshift */
228
         2,                        /* size */
229
         20,                       /* bitsize */
230
         FALSE,                    /* pc_relative */
231
         0,                        /* bitpos */
232
         complain_overflow_bitfield,/* complain_on_overflow */
233
         bfd_elf_generic_reloc,    /* special_function */
234
         "R_CR16_REGREL20a",       /* name */
235
         FALSE,                    /* partial_inplace */
236
         0xfffff,                  /* src_mask */
237
         0xfffff,                  /* dst_mask */
238
         FALSE),                   /* pcrel_offset */
239
 
240
  HOWTO (R_CR16_ABS20,             /* type */
241
         0,                        /* rightshift */
242
         2,                        /* size */
243
         20,                       /* bitsize */
244
         FALSE,                    /* pc_relative */
245
         0,                        /* bitpos */
246
         complain_overflow_bitfield,/* complain_on_overflow */
247
         bfd_elf_generic_reloc,    /* special_function */
248
         "R_CR16_ABS20",           /* name */
249
         FALSE,                    /* partial_inplace */
250
         0xfffff,                  /* src_mask */
251
         0xfffff,                  /* dst_mask */
252
         FALSE),                   /* pcrel_offset */
253
 
254
  HOWTO (R_CR16_ABS24,             /* type */
255
         0,                        /* rightshift */
256
         2,                        /* size */
257
         24,                       /* bitsize */
258
         FALSE,                    /* pc_relative */
259
         0,                        /* bitpos */
260
         complain_overflow_bitfield,/* complain_on_overflow */
261
         bfd_elf_generic_reloc,    /* special_function */
262
         "R_CR16_ABS24",           /* name */
263
         FALSE,                    /* partial_inplace */
264
         0xffffff,                 /* src_mask */
265
         0xffffff,                 /* dst_mask */
266
         FALSE),                   /* pcrel_offset */
267
 
268
  HOWTO (R_CR16_IMM4,              /* type */
269
         0,                        /* rightshift */
270
         0,                        /* size */
271
         4,                        /* bitsize */
272
         FALSE,                    /* pc_relative */
273
         0,                        /* bitpos */
274
         complain_overflow_bitfield,/* complain_on_overflow */
275
         bfd_elf_generic_reloc,    /* special_function */
276
         "R_CR16_IMM4",            /* name */
277
         FALSE,                    /* partial_inplace */
278
         0xf,                      /* src_mask */
279
         0xf,                      /* dst_mask */
280
         FALSE),                   /* pcrel_offset */
281
 
282
  HOWTO (R_CR16_IMM8,              /* type */
283
         0,                        /* rightshift */
284
         0,                        /* size */
285
         8,                        /* bitsize */
286
         FALSE,                    /* pc_relative */
287
         0,                        /* bitpos */
288
         complain_overflow_bitfield,/* complain_on_overflow */
289
         bfd_elf_generic_reloc,    /* special_function */
290
         "R_CR16_IMM8",            /* name */
291
         FALSE,                    /* partial_inplace */
292
         0xff,                     /* src_mask */
293
         0xff,                     /* dst_mask */
294
         FALSE),                   /* pcrel_offset */
295
 
296
  HOWTO (R_CR16_IMM16,             /* type */
297
         0,                        /* rightshift */
298
         1,                        /* size */
299
         16,                       /* bitsize */
300
         FALSE,                    /* pc_relative */
301
         0,                        /* bitpos */
302
         complain_overflow_bitfield,/* complain_on_overflow */
303
         bfd_elf_generic_reloc,    /* special_function */
304
         "R_CR16_IMM16",           /* name */
305
         FALSE,                    /* partial_inplace */
306
         0xffff,                   /* src_mask */
307
         0xffff,                   /* dst_mask */
308
         FALSE),                   /* pcrel_offset */
309
 
310
  HOWTO (R_CR16_IMM20,             /* type */
311
         0,                        /* rightshift */
312
         2,                        /* size */
313
         20,                       /* bitsize */
314
         FALSE,                    /* pc_relative */
315
         0,                        /* bitpos */
316
         complain_overflow_bitfield,/* complain_on_overflow */
317
         bfd_elf_generic_reloc,    /* special_function */
318
         "R_CR16_IMM20",           /* name */
319
         FALSE,                    /* partial_inplace */
320
         0xfffff,                  /* src_mask */
321
         0xfffff,                  /* dst_mask */
322
         FALSE),                   /* pcrel_offset */
323
 
324
  HOWTO (R_CR16_IMM24,             /* type */
325
         0,                        /* rightshift */
326
         2,                        /* size */
327
         24,                       /* bitsize */
328
         FALSE,                    /* pc_relative */
329
         0,                        /* bitpos */
330
         complain_overflow_bitfield,/* complain_on_overflow */
331
         bfd_elf_generic_reloc,    /* special_function */
332
         "R_CR16_IMM24",           /* name */
333
         FALSE,                    /* partial_inplace */
334
         0xffffff,                 /* src_mask */
335
         0xffffff,                 /* dst_mask */
336
         FALSE),                   /* pcrel_offset */
337
 
338
  HOWTO (R_CR16_IMM32,             /* type */
339
         0,                        /* rightshift */
340
         2,                        /* size */
341
         32,                       /* bitsize */
342
         FALSE,                    /* pc_relative */
343
         0,                        /* bitpos */
344
         complain_overflow_bitfield,/* complain_on_overflow */
345
         bfd_elf_generic_reloc,    /* special_function */
346
         "R_CR16_IMM32",           /* name */
347
         FALSE,                    /* partial_inplace */
348
         0xffffffff,               /* src_mask */
349
         0xffffffff,               /* dst_mask */
350
         FALSE),                   /* pcrel_offset */
351
 
352
  HOWTO (R_CR16_IMM32a,            /* type */
353
         1,                        /* rightshift */
354
         2,                        /* size */
355
         32,                       /* bitsize */
356
         FALSE,                    /* pc_relative */
357
         0,                        /* bitpos */
358
         complain_overflow_bitfield,/* complain_on_overflow */
359
         bfd_elf_generic_reloc,    /* special_function */
360
         "R_CR16_IMM32a",          /* name */
361
         FALSE,                    /* partial_inplace */
362
         0xffffffff,               /* src_mask */
363
         0xffffffff,               /* dst_mask */
364
         FALSE),                   /* pcrel_offset */
365
 
366
  HOWTO (R_CR16_DISP4,             /* type */
367
         1,                        /* rightshift */
368
         0,                        /* size (0 = byte, 1 = short, 2 = long) */
369
         4,                        /* bitsize */
370
         TRUE,                     /* pc_relative */
371
         0,                        /* bitpos */
372
         complain_overflow_unsigned, /* complain_on_overflow */
373
         bfd_elf_generic_reloc,    /* special_function */
374
         "R_CR16_DISP4",           /* name */
375
         FALSE,                    /* partial_inplace */
376
         0xf,                      /* src_mask */
377
         0xf,                      /* dst_mask */
378
         FALSE),                   /* pcrel_offset */
379
 
380
  HOWTO (R_CR16_DISP8,             /* type */
381
         1,                        /* rightshift */
382
         0,                        /* size (0 = byte, 1 = short, 2 = long) */
383
         8,                        /* bitsize */
384
         TRUE,                     /* pc_relative */
385
         0,                        /* bitpos */
386
         complain_overflow_unsigned, /* complain_on_overflow */
387
         bfd_elf_generic_reloc,    /* special_function */
388
         "R_CR16_DISP8",           /* name */
389
         FALSE,                    /* partial_inplace */
390
         0x1ff,                    /* src_mask */
391
         0x1ff,                    /* dst_mask */
392
         FALSE),                   /* pcrel_offset */
393
 
394
  HOWTO (R_CR16_DISP16,            /* type */
395
         0,                        /* rightshift REVIITS: To sync with WinIDEA*/
396
         1,                        /* size (0 = byte, 1 = short, 2 = long) */
397
         16,                       /* bitsize */
398
         TRUE,                     /* pc_relative */
399
         0,                        /* bitpos */
400
         complain_overflow_unsigned, /* complain_on_overflow */
401
         bfd_elf_generic_reloc,    /* special_function */
402
         "R_CR16_DISP16",          /* name */
403
         FALSE,                    /* partial_inplace */
404
         0x1ffff,                  /* src_mask */
405
         0x1ffff,                  /* dst_mask */
406
         FALSE),                   /* pcrel_offset */
407
  /* REVISIT: DISP24 should be left-shift by 2 as per ISA doc
408
     but its not done, to sync with WinIDEA and CR16 4.1 tools */
409
  HOWTO (R_CR16_DISP24,            /* type */
410
         0,                        /* rightshift */
411
         2,                        /* size (0 = byte, 1 = short, 2 = long) */
412
         24,                       /* bitsize */
413
         TRUE,                     /* pc_relative */
414
         0,                        /* bitpos */
415
         complain_overflow_unsigned, /* complain_on_overflow */
416
         bfd_elf_generic_reloc,    /* special_function */
417
         "R_CR16_DISP24",          /* name */
418
         FALSE,                    /* partial_inplace */
419
         0x1ffffff,                /* src_mask */
420
         0x1ffffff,                /* dst_mask */
421
         FALSE),                   /* pcrel_offset */
422
 
423
  HOWTO (R_CR16_DISP24a,           /* type */
424
         0,                        /* rightshift */
425
         2,                        /* size (0 = byte, 1 = short, 2 = long) */
426
         24,                       /* bitsize */
427
         TRUE,                     /* pc_relative */
428
         0,                        /* bitpos */
429
         complain_overflow_unsigned, /* complain_on_overflow */
430
         bfd_elf_generic_reloc,    /* special_function */
431
         "R_CR16_DISP24a",         /* name */
432
         FALSE,                    /* partial_inplace */
433
         0xffffff,                 /* src_mask */
434
         0xffffff,                 /* dst_mask */
435
         FALSE),                   /* pcrel_offset */
436
 
437
  /* An 8 bit switch table entry.  This is generated for an expression
438
     such as ``.byte L1 - L2''.  The offset holds the difference
439
     between the reloc address and L2.  */
440
  HOWTO (R_CR16_SWITCH8,           /* type */
441
         0,                        /* rightshift */
442
         0,                        /* size (0 = byte, 1 = short, 2 = long) */
443
         8,                        /* bitsize */
444
         FALSE,                    /* pc_relative */
445
         0,                        /* bitpos */
446
         complain_overflow_unsigned, /* complain_on_overflow */
447
         bfd_elf_generic_reloc,    /* special_function */
448
         "R_CR16_SWITCH8",         /* name */
449
         FALSE,                    /* partial_inplace */
450
         0xff,                     /* src_mask */
451
         0xff,                     /* dst_mask */
452
         TRUE),                    /* pcrel_offset */
453
 
454
  /* A 16 bit switch table entry.  This is generated for an expression
455
     such as ``.word L1 - L2''.  The offset holds the difference
456
     between the reloc address and L2.  */
457
  HOWTO (R_CR16_SWITCH16,          /* type */
458
         0,                        /* rightshift */
459
         1,                        /* size (0 = byte, 1 = short, 2 = long) */
460
         16,                       /* bitsize */
461
         FALSE,                    /* pc_relative */
462
         0,                        /* bitpos */
463
         complain_overflow_unsigned, /* complain_on_overflow */
464
         bfd_elf_generic_reloc,    /* special_function */
465
         "R_CR16_SWITCH16",        /* name */
466
         FALSE,                    /* partial_inplace */
467
         0xffff,                   /* src_mask */
468
         0xffff,                   /* dst_mask */
469
         TRUE),                    /* pcrel_offset */
470
 
471
  /* A 32 bit switch table entry.  This is generated for an expression
472
     such as ``.long L1 - L2''.  The offset holds the difference
473
     between the reloc address and L2.  */
474
  HOWTO (R_CR16_SWITCH32,          /* type */
475
         0,                        /* rightshift */
476
         2,                        /* size (0 = byte, 1 = short, 2 = long) */
477
         32,                       /* bitsize */
478
         FALSE,                    /* pc_relative */
479
         0,                        /* bitpos */
480
         complain_overflow_unsigned, /* complain_on_overflow */
481
         bfd_elf_generic_reloc,    /* special_function */
482
         "R_CR16_SWITCH32",        /* name */
483
         FALSE,                    /* partial_inplace */
484
         0xffffffff,               /* src_mask */
485
         0xffffffff,               /* dst_mask */
486
         TRUE)                     /* pcrel_offset */
487
};
488
 
489
/* Retrieve a howto ptr using a BFD reloc_code.  */
490
 
491
static reloc_howto_type *
492
elf_cr16_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
493
                            bfd_reloc_code_real_type code)
494
{
495
  unsigned int i;
496
 
497
  for (i = 0; i < R_CR16_MAX; i++)
498
    if (code == cr16_reloc_map[i].bfd_reloc_enum)
499
      return &cr16_elf_howto_table[cr16_reloc_map[i].cr16_reloc_type];
500
 
501
  _bfd_error_handler ("Unsupported CR16 relocation type: 0x%x\n", code);
502
  return NULL;
503
}
504
 
505
static reloc_howto_type *
506
elf_cr16_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
507
                            const char *r_name)
508
{
509
  unsigned int i;
510
 
511
  for (i = 0; ARRAY_SIZE (cr16_elf_howto_table); i++)
512
    if (cr16_elf_howto_table[i].name != NULL
513
        && strcasecmp (cr16_elf_howto_table[i].name, r_name) == 0)
514
      return cr16_elf_howto_table + i;
515
 
516
  return NULL;
517
}
518
 
519
/* Retrieve a howto ptr using an internal relocation entry.  */
520
 
521
static void
522
elf_cr16_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr,
523
                        Elf_Internal_Rela *dst)
524
{
525
  unsigned int r_type = ELF32_R_TYPE (dst->r_info);
526
 
527
  BFD_ASSERT (r_type < (unsigned int) R_CR16_MAX);
528
  cache_ptr->howto = &cr16_elf_howto_table[r_type];
529
}
530
 
531
/* Perform a relocation as part of a final link.  */
532
 
533
static bfd_reloc_status_type
534
cr16_elf_final_link_relocate (reloc_howto_type *howto,
535
                              bfd *input_bfd,
536
                              bfd *output_bfd ATTRIBUTE_UNUSED,
537
                              asection *input_section,
538
                              bfd_byte *contents,
539
                              bfd_vma offset,
540
                              bfd_vma Rvalue,
541
                              bfd_vma addend,
542
                              struct bfd_link_info *info ATTRIBUTE_UNUSED,
543
                              asection *sec ATTRIBUTE_UNUSED,
544
                              int is_local ATTRIBUTE_UNUSED)
545
{
546
  unsigned short r_type = howto->type;
547
  bfd_byte *hit_data = contents + offset;
548
  bfd_vma reloc_bits, check, Rvalue1;
549
 
550
  switch (r_type)
551
    {
552
     case R_CR16_IMM4:
553
     case R_CR16_IMM20:
554
     case R_CR16_ABS20:
555
       break;
556
 
557
     case R_CR16_IMM8:
558
     case R_CR16_IMM16:
559
     case R_CR16_IMM32:
560
     case R_CR16_IMM32a:
561
     case R_CR16_REGREL4:
562
     case R_CR16_REGREL4a:
563
     case R_CR16_REGREL14:
564
     case R_CR16_REGREL14a:
565
     case R_CR16_REGREL16:
566
     case R_CR16_REGREL20:
567
     case R_CR16_ABS24:
568
     case R_CR16_DISP16:
569
     case R_CR16_DISP24:
570
       /* 'hit_data' is relative to the start of the instruction, not the
571
           relocation offset. Advance it to account for the exact offset.  */
572
       hit_data += 2;
573
       break;
574
 
575
     case R_CR16_NONE:
576
       return bfd_reloc_ok;
577
       break;
578
 
579
     case R_CR16_DISP4:
580
       if (is_local)
581
         Rvalue += -1;
582
       break;
583
 
584
     case R_CR16_DISP8:
585
     case R_CR16_DISP24a:
586
       if (is_local)
587
         Rvalue -= -1;
588
       break;
589
 
590
     case R_CR16_SWITCH8:
591
     case R_CR16_SWITCH16:
592
     case R_CR16_SWITCH32:
593
       /* We only care about the addend, where the difference between
594
          expressions is kept.  */
595
       Rvalue = 0;
596
 
597
     default:
598
       break;
599
    }
600
 
601
  if (howto->pc_relative)
602
    {
603
      /* Subtract the address of the section containing the location.  */
604
      Rvalue -= (input_section->output_section->vma
605
                 + input_section->output_offset);
606
      /* Subtract the position of the location within the section.  */
607
      Rvalue -= offset;
608
    }
609
 
610
  /* Add in supplied addend.  */
611
  Rvalue += addend;
612
 
613
  /* Complain if the bitfield overflows, whether it is considered
614
     as signed or unsigned.  */
615
  check = Rvalue >> howto->rightshift;
616
 
617
  /* Assumes two's complement.  This expression avoids
618
     overflow if howto->bitsize is the number of bits in
619
     bfd_vma.  */
620
  reloc_bits = (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
621
 
622
  if (((bfd_vma) check & ~reloc_bits) != 0
623
      && (((bfd_vma) check & ~reloc_bits)
624
      != (-(bfd_vma) 1 & ~reloc_bits)))
625
    {
626
      /* The above right shift is incorrect for a signed
627
         value.  See if turning on the upper bits fixes the
628
         overflow.  */
629
      if (howto->rightshift && (bfd_signed_vma) Rvalue < 0)
630
        {
631
          check |= ((bfd_vma) - 1
632
                    & ~((bfd_vma) - 1
633
                        >> howto->rightshift));
634
 
635
          if (((bfd_vma) check & ~reloc_bits)
636
              != (-(bfd_vma) 1 & ~reloc_bits))
637
             return bfd_reloc_overflow;
638
        }
639
      else
640
        return bfd_reloc_overflow;
641
    }
642
 
643
  /* Drop unwanted bits from the value we are relocating to.  */
644
  Rvalue >>= (bfd_vma) howto->rightshift;
645
 
646
  /* Apply dst_mask to select only relocatable part of the insn.  */
647
  Rvalue &= howto->dst_mask;
648
 
649
  switch (howto->size)
650
    {
651
      case 0:
652
        if (r_type == R_CR16_DISP8)
653
          {
654
             Rvalue1 = bfd_get_16 (input_bfd, hit_data);
655
             Rvalue = ((Rvalue1 & 0xf000) | ((Rvalue << 4) & 0xf00)
656
                       | (Rvalue1 & 0x00f0) | (Rvalue & 0xf));
657
             bfd_put_16 (input_bfd, Rvalue, hit_data);
658
          }
659
        else if (r_type == R_CR16_IMM4)
660
          {
661
             Rvalue1 = bfd_get_16 (input_bfd, hit_data);
662
             Rvalue = (((Rvalue1 & 0xff) << 8) | ((Rvalue << 4) & 0xf0)
663
                       | ((Rvalue1 & 0x0f00) >> 8));
664
             bfd_put_16 (input_bfd, Rvalue, hit_data);
665
          }
666
        else if (r_type == R_CR16_DISP4)
667
          {
668
             Rvalue1 = bfd_get_16 (input_bfd, hit_data);
669
             Rvalue = (Rvalue1 | ((Rvalue & 0xf) << 4));
670
             bfd_put_16 (input_bfd, Rvalue, hit_data);
671
          }
672
        else
673
          {
674
             bfd_put_8 (input_bfd, (unsigned char) Rvalue, hit_data);
675
          }
676
        break;
677
 
678
      case 1:
679
        if (r_type == R_CR16_DISP16)
680
          {
681
            Rvalue |= (bfd_get_16 (input_bfd, hit_data));
682
            Rvalue = ((Rvalue & 0xfffe) | ((Rvalue >> 16) & 0x1));
683
          }
684
 
685
          bfd_put_16 (input_bfd, Rvalue, hit_data);
686
        break;
687
 
688
      case 2:
689
        if ((r_type == R_CR16_ABS20) || (r_type == R_CR16_IMM20))
690
          {
691
             bfd_put_16 (input_bfd, (bfd_get_16 (input_bfd, hit_data))
692
                         | ((Rvalue >> 16) & 0xf), hit_data);
693
             bfd_put_16 (input_bfd, (Rvalue) & 0xffff, hit_data + 2);
694
          }
695
        else
696
          {
697
            if (r_type == R_CR16_ABS24)
698
              {
699
                Rvalue = ((((Rvalue >> 20)& 0xf) | (((Rvalue >> 16) & 0xf) << 8)
700
                          | (bfd_get_16 (input_bfd, hit_data)))
701
                          | ((Rvalue & 0xffff) << 16));
702
              }
703
            if (r_type == R_CR16_DISP24)
704
              {
705
                Rvalue = ((((Rvalue >> 20)& 0xf) | (((Rvalue >>16) & 0xf) << 8)
706
                          | (bfd_get_16 (input_bfd, hit_data)))
707
                          | (((Rvalue & 0xfffe)
708
                              | ((Rvalue >> 24) & 0x1)) << 16));
709
              }
710
            else if ((r_type == R_CR16_IMM32) ||(r_type == R_CR16_IMM32a))
711
              {
712
                Rvalue = (((Rvalue >> 16)& 0xffff)
713
                          | (bfd_get_16 (input_bfd, hit_data)))
714
                          | ((Rvalue & 0xffff) << 16);
715
              }
716
            else if (r_type == R_CR16_DISP24a)
717
              {
718
                Rvalue = (((Rvalue & 0xfffffe) | (Rvalue >> 23)));
719
                Rvalue = ((Rvalue >> 16) & 0xff) | ((Rvalue & 0xffff) << 16)
720
                          | (bfd_get_32 (input_bfd, hit_data));
721
              }
722
 
723
            bfd_put_32 (input_bfd, Rvalue, hit_data);
724
          }
725
        break;
726
 
727
      default:
728
        return bfd_reloc_notsupported;
729
    }
730
 
731
  return bfd_reloc_ok;
732
}
733
 
734
/* Delete some bytes from a section while relaxing.  */
735
 
736
static bfd_boolean
737
elf32_cr16_relax_delete_bytes (struct bfd_link_info *link_info, bfd *abfd,
738
                               asection *sec, bfd_vma addr, int count)
739
{
740
  Elf_Internal_Shdr *symtab_hdr;
741
  unsigned int sec_shndx;
742
  bfd_byte *contents;
743
  Elf_Internal_Rela *irel, *irelend;
744
  Elf_Internal_Rela *irelalign;
745
  bfd_vma toaddr;
746
  Elf_Internal_Sym *isym;
747
  Elf_Internal_Sym *isymend;
748
  struct elf_link_hash_entry **sym_hashes;
749
  struct elf_link_hash_entry **end_hashes;
750
  struct elf_link_hash_entry **start_hashes;
751
  unsigned int symcount;
752
 
753
  sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
754
 
755
  contents = elf_section_data (sec)->this_hdr.contents;
756
 
757
  /* The deletion must stop at the next ALIGN reloc for an aligment
758
     power larger than the number of bytes we are deleting.  */
759
  irelalign = NULL;
760
  toaddr = sec->size;
761
 
762
  irel = elf_section_data (sec)->relocs;
763
  irelend = irel + sec->reloc_count;
764
 
765
  /* Actually delete the bytes.  */
766
  memmove (contents + addr, contents + addr + count,
767
           (size_t) (toaddr - addr - count));
768
  sec->size -= count;
769
 
770
  /* Adjust all the relocs.  */
771
  for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
772
    /* Get the new reloc address.  */
773
    if ((irel->r_offset > addr && irel->r_offset < toaddr))
774
        irel->r_offset -= count;
775
 
776
  /* Adjust the local symbols defined in this section.  */
777
  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
778
  isym = (Elf_Internal_Sym *) symtab_hdr->contents;
779
  for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++)
780
    {
781
      if (isym->st_shndx == sec_shndx
782
          && isym->st_value > addr
783
          && isym->st_value < toaddr)
784
        {
785
          /* Adjust the addend of SWITCH relocations in this section,
786
             which reference this local symbol.  */
787
          for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
788
            {
789
              unsigned long r_symndx;
790
              Elf_Internal_Sym *rsym;
791
              bfd_vma addsym, subsym;
792
 
793
              /* Skip if not a SWITCH relocation.  */
794
              if (ELF32_R_TYPE (irel->r_info) != (int) R_CR16_SWITCH8
795
                  && ELF32_R_TYPE (irel->r_info) != (int) R_CR16_SWITCH16
796
                  && ELF32_R_TYPE (irel->r_info) != (int) R_CR16_SWITCH32)
797
                continue;
798
 
799
              r_symndx = ELF32_R_SYM (irel->r_info);
800
              rsym = (Elf_Internal_Sym *) symtab_hdr->contents + r_symndx;
801
 
802
              /* Skip if not the local adjusted symbol.  */
803
              if (rsym != isym)
804
                continue;
805
 
806
              addsym = isym->st_value;
807
              subsym = addsym - irel->r_addend;
808
 
809
              /* Fix the addend only when -->> (addsym > addr >= subsym).  */
810
              if (subsym <= addr)
811
                irel->r_addend -= count;
812
              else
813
                continue;
814
            }
815
 
816
          isym->st_value -= count;
817
        }
818
    }
819
 
820
  /* Now adjust the global symbols defined in this section.  */
821
  symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
822
               - symtab_hdr->sh_info);
823
  sym_hashes = start_hashes = elf_sym_hashes (abfd);
824
  end_hashes = sym_hashes + symcount;
825
 
826
  for (; sym_hashes < end_hashes; sym_hashes++)
827
    {
828
      struct elf_link_hash_entry *sym_hash = *sym_hashes;
829
 
830
      /* The '--wrap SYMBOL' option is causing a pain when the object file,
831
         containing the definition of __wrap_SYMBOL, includes a direct
832
         call to SYMBOL as well. Since both __wrap_SYMBOL and SYMBOL reference
833
         the same symbol (which is __wrap_SYMBOL), but still exist as two
834
         different symbols in 'sym_hashes', we don't want to adjust
835
         the global symbol __wrap_SYMBOL twice.
836
         This check is only relevant when symbols are being wrapped.  */
837
      if (link_info->wrap_hash != NULL)
838
        {
839
          struct elf_link_hash_entry **cur_sym_hashes;
840
 
841
          /* Loop only over the symbols whom been already checked.  */
842
          for (cur_sym_hashes = start_hashes; cur_sym_hashes < sym_hashes;
843
               cur_sym_hashes++)
844
            /* If the current symbol is identical to 'sym_hash', that means
845
               the symbol was already adjusted (or at least checked).  */
846
            if (*cur_sym_hashes == sym_hash)
847
              break;
848
 
849
          /* Don't adjust the symbol again.  */
850
          if (cur_sym_hashes < sym_hashes)
851
            continue;
852
        }
853
 
854
      if ((sym_hash->root.type == bfd_link_hash_defined
855
          || sym_hash->root.type == bfd_link_hash_defweak)
856
          && sym_hash->root.u.def.section == sec
857
          && sym_hash->root.u.def.value > addr
858
          && sym_hash->root.u.def.value < toaddr)
859
        sym_hash->root.u.def.value -= count;
860
    }
861
 
862
  return TRUE;
863
}
864
 
865
/* Relocate a CR16 ELF section.  */
866
 
867
static bfd_boolean
868
elf32_cr16_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
869
                             bfd *input_bfd, asection *input_section,
870
                             bfd_byte *contents, Elf_Internal_Rela *relocs,
871
                             Elf_Internal_Sym *local_syms,
872
                             asection **local_sections)
873
{
874
  Elf_Internal_Shdr *symtab_hdr;
875
  struct elf_link_hash_entry **sym_hashes;
876
  Elf_Internal_Rela *rel, *relend;
877
 
878
  if (info->relocatable)
879
    return TRUE;
880
 
881
  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
882
  sym_hashes = elf_sym_hashes (input_bfd);
883
 
884
  rel = relocs;
885
  relend = relocs + input_section->reloc_count;
886
  for (; rel < relend; rel++)
887
    {
888
      int r_type;
889
      reloc_howto_type *howto;
890
      unsigned long r_symndx;
891
      Elf_Internal_Sym *sym;
892
      asection *sec;
893
      struct elf_link_hash_entry *h;
894
      bfd_vma relocation;
895
      bfd_reloc_status_type r;
896
 
897
      r_symndx = ELF32_R_SYM (rel->r_info);
898
      r_type = ELF32_R_TYPE (rel->r_info);
899
      howto = cr16_elf_howto_table + (r_type);
900
 
901
      h = NULL;
902
      sym = NULL;
903
      sec = NULL;
904
      if (r_symndx < symtab_hdr->sh_info)
905
        {
906
          sym = local_syms + r_symndx;
907
          sec = local_sections[r_symndx];
908
          relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
909
        }
910
      else
911
        {
912
          bfd_boolean unresolved_reloc, warned;
913
 
914
          RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
915
                                   r_symndx, symtab_hdr, sym_hashes,
916
                                   h, sec, relocation,
917
                                   unresolved_reloc, warned);
918
        }
919
 
920
      r = cr16_elf_final_link_relocate (howto, input_bfd, output_bfd,
921
                                        input_section,
922
                                        contents, rel->r_offset,
923
                                        relocation, rel->r_addend,
924
                                        info, sec, h == NULL);
925
 
926
      if (r != bfd_reloc_ok)
927
        {
928
          const char *name;
929
          const char *msg = NULL;
930
 
931
          if (h != NULL)
932
            name = h->root.root.string;
933
          else
934
            {
935
              name = (bfd_elf_string_from_elf_section
936
                      (input_bfd, symtab_hdr->sh_link, sym->st_name));
937
              if (name == NULL || *name == '\0')
938
                name = bfd_section_name (input_bfd, sec);
939
            }
940
 
941
          switch (r)
942
            {
943
             case bfd_reloc_overflow:
944
               if (!((*info->callbacks->reloc_overflow)
945
                     (info, (h ? &h->root : NULL), name, howto->name,
946
                      (bfd_vma) 0, input_bfd, input_section,
947
                      rel->r_offset)))
948
                 return FALSE;
949
               break;
950
 
951
             case bfd_reloc_undefined:
952
               if (!((*info->callbacks->undefined_symbol)
953
                     (info, name, input_bfd, input_section,
954
                      rel->r_offset, TRUE)))
955
                 return FALSE;
956
               break;
957
 
958
             case bfd_reloc_outofrange:
959
               msg = _("internal error: out of range error");
960
               goto common_error;
961
 
962
             case bfd_reloc_notsupported:
963
               msg = _("internal error: unsupported relocation error");
964
               goto common_error;
965
 
966
             case bfd_reloc_dangerous:
967
               msg = _("internal error: dangerous error");
968
               goto common_error;
969
 
970
             default:
971
               msg = _("internal error: unknown error");
972
               /* Fall through.  */
973
 
974
             common_error:
975
               if (!((*info->callbacks->warning)
976
                     (info, msg, name, input_bfd, input_section,
977
                      rel->r_offset)))
978
                 return FALSE;
979
               break;
980
            }
981
        }
982
    }
983
 
984
  return TRUE;
985
}
986
 
987
/* This is a version of bfd_generic_get_relocated_section_contents
988
   which uses elf32_cr16_relocate_section.  */
989
 
990
static bfd_byte *
991
elf32_cr16_get_relocated_section_contents (bfd *output_bfd,
992
                                           struct bfd_link_info *link_info,
993
                                           struct bfd_link_order *link_order,
994
                                           bfd_byte *data,
995
                                           bfd_boolean relocatable,
996
                                           asymbol **symbols)
997
{
998
  Elf_Internal_Shdr *symtab_hdr;
999
  asection *input_section = link_order->u.indirect.section;
1000
  bfd *input_bfd = input_section->owner;
1001
  asection **sections = NULL;
1002
  Elf_Internal_Rela *internal_relocs = NULL;
1003
  Elf_Internal_Sym *isymbuf = NULL;
1004
 
1005
  /* We only need to handle the case of relaxing, or of having a
1006
     particular set of section contents, specially.  */
1007
  if (relocatable
1008
      || elf_section_data (input_section)->this_hdr.contents == NULL)
1009
    return bfd_generic_get_relocated_section_contents (output_bfd, link_info,
1010
                                                       link_order, data,
1011
                                                       relocatable,
1012
                                                       symbols);
1013
 
1014
  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
1015
 
1016
  memcpy (data, elf_section_data (input_section)->this_hdr.contents,
1017
          (size_t) input_section->size);
1018
 
1019
  if ((input_section->flags & SEC_RELOC) != 0
1020
      && input_section->reloc_count > 0)
1021
    {
1022
      Elf_Internal_Sym *isym;
1023
      Elf_Internal_Sym *isymend;
1024
      asection **secpp;
1025
      bfd_size_type amt;
1026
 
1027
      internal_relocs = _bfd_elf_link_read_relocs (input_bfd, input_section,
1028
                                                   NULL, NULL, FALSE);
1029
      if (internal_relocs == NULL)
1030
        goto error_return;
1031
 
1032
      if (symtab_hdr->sh_info != 0)
1033
        {
1034
          isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1035
          if (isymbuf == NULL)
1036
            isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
1037
                                            symtab_hdr->sh_info, 0,
1038
                                            NULL, NULL, NULL);
1039
          if (isymbuf == NULL)
1040
            goto error_return;
1041
        }
1042
 
1043
      amt = symtab_hdr->sh_info;
1044
      amt *= sizeof (asection *);
1045
      sections = bfd_malloc (amt);
1046
      if (sections == NULL && amt != 0)
1047
        goto error_return;
1048
 
1049
      isymend = isymbuf + symtab_hdr->sh_info;
1050
      for (isym = isymbuf, secpp = sections; isym < isymend; ++isym, ++secpp)
1051
        {
1052
          asection *isec;
1053
 
1054
          if (isym->st_shndx == SHN_UNDEF)
1055
            isec = bfd_und_section_ptr;
1056
          else if (isym->st_shndx == SHN_ABS)
1057
            isec = bfd_abs_section_ptr;
1058
          else if (isym->st_shndx == SHN_COMMON)
1059
            isec = bfd_com_section_ptr;
1060
          else
1061
            isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx);
1062
 
1063
          *secpp = isec;
1064
        }
1065
 
1066
      if (! elf32_cr16_relocate_section (output_bfd, link_info, input_bfd,
1067
                                     input_section, data, internal_relocs,
1068
                                     isymbuf, sections))
1069
        goto error_return;
1070
 
1071
      if (sections != NULL)
1072
        free (sections);
1073
      if (isymbuf != NULL
1074
          && symtab_hdr->contents != (unsigned char *) isymbuf)
1075
        free (isymbuf);
1076
      if (elf_section_data (input_section)->relocs != internal_relocs)
1077
        free (internal_relocs);
1078
    }
1079
 
1080
  return data;
1081
 
1082
 error_return:
1083
  if (sections != NULL)
1084
    free (sections);
1085
  if (isymbuf != NULL
1086
      && symtab_hdr->contents != (unsigned char *) isymbuf)
1087
    free (isymbuf);
1088
  if (internal_relocs != NULL
1089
      && elf_section_data (input_section)->relocs != internal_relocs)
1090
    free (internal_relocs);
1091
  return NULL;
1092
}
1093
 
1094
/* This function handles relaxing for the CR16.
1095
 
1096
   There's quite a few relaxing opportunites available on the CR16:
1097
 
1098
        * bcond:24 -> bcond:16                                2 bytes
1099
        * bcond:16 -> bcond:8                                 2 bytes
1100
        * arithmetic imm32 -> arithmetic imm20/imm16          2 bytes
1101
        * arithmetic imm20/imm16 -> arithmetic imm4           2 bytes
1102
 
1103
   Symbol- and reloc-reading infrastructure copied from elf-m10200.c.  */
1104
 
1105
static bfd_boolean
1106
elf32_cr16_relax_section (bfd *abfd, asection *sec,
1107
                         struct bfd_link_info *link_info, bfd_boolean *again)
1108
{
1109
  Elf_Internal_Shdr *symtab_hdr;
1110
  Elf_Internal_Rela *internal_relocs;
1111
  Elf_Internal_Rela *irel, *irelend;
1112
  bfd_byte *contents = NULL;
1113
  Elf_Internal_Sym *isymbuf = NULL;
1114
 
1115
  /* Assume nothing changes.  */
1116
  *again = FALSE;
1117
 
1118
  /* We don't have to do anything for a relocatable link, if
1119
     this section does not have relocs, or if this is not a
1120
     code section.  */
1121
  if (link_info->relocatable
1122
      || (sec->flags & SEC_RELOC) == 0
1123
      || sec->reloc_count == 0
1124
      || (sec->flags & SEC_CODE) == 0)
1125
    return TRUE;
1126
 
1127
  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
1128
 
1129
  /* Get a copy of the native relocations.  */
1130
  internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
1131
                                               link_info->keep_memory);
1132
  if (internal_relocs == NULL)
1133
    goto error_return;
1134
 
1135
  /* Walk through them looking for relaxing opportunities.  */
1136
  irelend = internal_relocs + sec->reloc_count;
1137
  for (irel = internal_relocs; irel < irelend; irel++)
1138
    {
1139
      bfd_vma symval;
1140
 
1141
      /* If this isn't something that can be relaxed, then ignore
1142
         this reloc.  */
1143
      if (ELF32_R_TYPE (irel->r_info) != (int) R_CR16_DISP16
1144
          && ELF32_R_TYPE (irel->r_info) != (int) R_CR16_DISP24
1145
          && ELF32_R_TYPE (irel->r_info) != (int) R_CR16_IMM32
1146
          && ELF32_R_TYPE (irel->r_info) != (int) R_CR16_IMM20
1147
          && ELF32_R_TYPE (irel->r_info) != (int) R_CR16_IMM16)
1148
        continue;
1149
 
1150
      /* Get the section contents if we haven't done so already.  */
1151
      if (contents == NULL)
1152
        {
1153
          /* Get cached copy if it exists.  */
1154
          if (elf_section_data (sec)->this_hdr.contents != NULL)
1155
            contents = elf_section_data (sec)->this_hdr.contents;
1156
          /* Go get them off disk.  */
1157
          else if (!bfd_malloc_and_get_section (abfd, sec, &contents))
1158
            goto error_return;
1159
        }
1160
 
1161
      /* Read this BFD's local symbols if we haven't done so already.  */
1162
      if (isymbuf == NULL && symtab_hdr->sh_info != 0)
1163
        {
1164
          isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1165
          if (isymbuf == NULL)
1166
            isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
1167
                                            symtab_hdr->sh_info, 0,
1168
                                            NULL, NULL, NULL);
1169
          if (isymbuf == NULL)
1170
            goto error_return;
1171
        }
1172
 
1173
      /* Get the value of the symbol referred to by the reloc.  */
1174
      if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1175
        {
1176
          /* A local symbol.  */
1177
          Elf_Internal_Sym *isym;
1178
          asection *sym_sec;
1179
 
1180
          isym = isymbuf + ELF32_R_SYM (irel->r_info);
1181
          if (isym->st_shndx == SHN_UNDEF)
1182
            sym_sec = bfd_und_section_ptr;
1183
          else if (isym->st_shndx == SHN_ABS)
1184
            sym_sec = bfd_abs_section_ptr;
1185
          else if (isym->st_shndx == SHN_COMMON)
1186
            sym_sec = bfd_com_section_ptr;
1187
          else
1188
            sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
1189
          symval = (isym->st_value
1190
                    + sym_sec->output_section->vma
1191
                    + sym_sec->output_offset);
1192
        }
1193
      else
1194
        {
1195
          unsigned long indx;
1196
          struct elf_link_hash_entry *h;
1197
 
1198
          /* An external symbol.  */
1199
          indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
1200
          h = elf_sym_hashes (abfd)[indx];
1201
          BFD_ASSERT (h != NULL);
1202
 
1203
          if (h->root.type != bfd_link_hash_defined
1204
              && h->root.type != bfd_link_hash_defweak)
1205
            /* This appears to be a reference to an undefined
1206
               symbol.  Just ignore it--it will be caught by the
1207
               regular reloc processing.  */
1208
            continue;
1209
 
1210
          symval = (h->root.u.def.value
1211
                    + h->root.u.def.section->output_section->vma
1212
                    + h->root.u.def.section->output_offset);
1213
        }
1214
 
1215
      /* For simplicity of coding, we are going to modify the section
1216
         contents, the section relocs, and the BFD symbol table.  We
1217
         must tell the rest of the code not to free up this
1218
         information.  It would be possible to instead create a table
1219
         of changes which have to be made, as is done in coff-mips.c;
1220
         that would be more work, but would require less memory when
1221
         the linker is run.  */
1222
 
1223
      /* Try to turn a 24  branch/call into a 16bit relative
1224
         branch/call.  */
1225
      if (ELF32_R_TYPE (irel->r_info) == (int) R_CR16_DISP24)
1226
        {
1227
          bfd_vma value = symval;
1228
 
1229
          /* Deal with pc-relative gunk.  */
1230
          value -= (sec->output_section->vma + sec->output_offset);
1231
          value -= irel->r_offset;
1232
          value += irel->r_addend;
1233
 
1234
          /* See if the value will fit in 16 bits, note the high value is
1235
             0xfffe + 2 as the target will be two bytes closer if we are
1236
             able to relax.  */
1237
          if ((long) value < 0x10000 && (long) value > -0x10002)
1238
            {
1239
              unsigned int code;
1240
 
1241
              /* Get the opcode.  */
1242
              code = (unsigned int) bfd_get_32 (abfd, contents + irel->r_offset);
1243
 
1244
              /* Verify it's a 'bcond' and fix the opcode.  */
1245
              if ((code  & 0xffff) == 0x0010)
1246
                {
1247
                  bfd_put_16 (abfd, 0x1800 | ((0xf & (code >> 20)) << 4), contents + irel->r_offset);
1248
                  bfd_put_16 (abfd, value, contents + irel->r_offset + 2);
1249
                }
1250
              else
1251
                continue;
1252
 
1253
              /* Note that we've changed the relocs, section contents, etc.  */
1254
              elf_section_data (sec)->relocs = internal_relocs;
1255
              elf_section_data (sec)->this_hdr.contents = contents;
1256
              symtab_hdr->contents = (unsigned char *) isymbuf;
1257
 
1258
              /* Fix the relocation's type.  */
1259
              irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1260
                                           R_CR16_DISP16);
1261
 
1262
              /* Delete two bytes of data.  */
1263
              if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec,
1264
                                                   irel->r_offset + 2, 2))
1265
                goto error_return;
1266
 
1267
              /* That will change things, so, we should relax again.
1268
                 Note that this is not required, and it may be slow.  */
1269
              *again = TRUE;
1270
            }
1271
        }
1272
 
1273
      /* Try to turn a 16-bit pc-relative branch into an
1274
         8-bit pc-relative branch.  */
1275
      if (ELF32_R_TYPE (irel->r_info) == (int) R_CR16_DISP16)
1276
        {
1277
          bfd_vma value = symval;
1278
 
1279
          /* Deal with pc-relative gunk.  */
1280
          value -= (sec->output_section->vma + sec->output_offset);
1281
          value -= irel->r_offset;
1282
          value += irel->r_addend;
1283
 
1284
          /* See if the value will fit in 8 bits, note the high value is
1285
             0xfc + 2 as the target will be two bytes closer if we are
1286
             able to relax.  */
1287
          if ((long) value < 0xfe && (long) value > -0x100)
1288
            {
1289
              unsigned short code;
1290
 
1291
              /* Get the opcode.  */
1292
              code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1293
 
1294
              /* Verify it's a 'bcond' opcode.  */
1295
              if ((code & 0xff00) == 0x1800)
1296
                {
1297
                 bfd_put_8 (abfd, 0x1 | ((0xf & (code >> 4)) << 4), contents + irel->r_offset);
1298
                 bfd_put_8 (abfd, value, contents + irel->r_offset + 2);
1299
                }
1300
              else
1301
                continue;
1302
 
1303
              /* Note that we've changed the relocs, section contents, etc.  */
1304
              elf_section_data (sec)->relocs = internal_relocs;
1305
              elf_section_data (sec)->this_hdr.contents = contents;
1306
              symtab_hdr->contents = (unsigned char *) isymbuf;
1307
 
1308
              /* Fix the relocation's type.  */
1309
              irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1310
                                           R_CR16_DISP8);
1311
 
1312
              /* Delete two bytes of data.  */
1313
              if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec,
1314
                                                   irel->r_offset + 2, 2))
1315
                goto error_return;
1316
 
1317
              /* That will change things, so, we should relax again.
1318
                 Note that this is not required, and it may be slow.  */
1319
              *again = TRUE;
1320
            }
1321
        }
1322
 
1323
      /* Try to turn a 32bit immediate address into
1324
         a 20/16bit immediate address.  */
1325
      if (ELF32_R_TYPE (irel->r_info) == (int) R_CR16_IMM32)
1326
        {
1327
          bfd_vma value = symval;
1328
          unsigned short is_add_mov = 0;
1329
 
1330
          /* See if the value will fit in 20 bits.  */
1331
          if ((long) value < 0xfffff && (long) value > 0)
1332
            {
1333
              unsigned short code;
1334
 
1335
              /* Get the opcode.  */
1336
              code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1337
 
1338
              /* Verify it's a arithmetic ADDD or MOVD instruction.
1339
                 For ADDD and MOVD only, convert to IMM32 -> IMM20.  */
1340
              if (((code & 0xfff0) == 0x0070) || ((code & 0xfff0) == 0x0020))
1341
                is_add_mov = 1;
1342
 
1343
              if (is_add_mov)
1344
                {
1345
                  /* Note that we've changed the relocs, section contents,
1346
                     etc.  */
1347
                  elf_section_data (sec)->relocs = internal_relocs;
1348
                  elf_section_data (sec)->this_hdr.contents = contents;
1349
                  symtab_hdr->contents = (unsigned char *) isymbuf;
1350
 
1351
                  /* Fix the opcode.  */
1352
                  if ((code & 0xfff0) == 0x0070) /* For movd.  */
1353
                    bfd_put_8 (abfd, 0x05, contents + irel->r_offset + 1);
1354
                  else                          /* code == 0x0020 for addd.  */
1355
                    bfd_put_8 (abfd, 0x04, contents + irel->r_offset + 1);
1356
 
1357
                  bfd_put_8 (abfd, (code & 0xf) << 4, contents + irel->r_offset);
1358
 
1359
 
1360
                  /* Fix the relocation's type.  */
1361
                  irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1362
                                               R_CR16_IMM20);
1363
                  /* Delete two bytes of data.  */
1364
                  if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec,
1365
                                                      irel->r_offset + 2, 2))
1366
                    goto error_return;
1367
 
1368
                  /* That will change things, so, we should relax again.
1369
                     Note that this is not required, and it may be slow.  */
1370
                  *again = TRUE;
1371
                }
1372
            }
1373
         /* See if the value will fit in 16 bits.  */
1374
          if ((!is_add_mov) && ((long) value < 0x7fff && (long) value > 0))
1375
            {
1376
              unsigned short code;
1377
 
1378
              /* Get the opcode.  */
1379
              code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1380
 
1381
              /* Note that we've changed the relocs, section contents, etc.  */
1382
              elf_section_data (sec)->relocs = internal_relocs;
1383
              elf_section_data (sec)->this_hdr.contents = contents;
1384
              symtab_hdr->contents = (unsigned char *) isymbuf;
1385
 
1386
              /* Fix the opcode.  */
1387
              if ((code & 0xf0) == 0x70)          /* For movd.  */
1388
                bfd_put_8 (abfd, 0x54, contents + irel->r_offset + 1);
1389
              else if ((code & 0xf0) == 0x20)     /* For addd.  */
1390
                bfd_put_8 (abfd, 0x60, contents + irel->r_offset + 1);
1391
              else if ((code & 0xf0) == 0x90)     /* For cmpd.  */
1392
                bfd_put_8 (abfd, 0x56, contents + irel->r_offset + 1);
1393
              else
1394
                continue;
1395
 
1396
              bfd_put_8 (abfd, 0xb0 | (code & 0xf), contents + irel->r_offset);
1397
 
1398
              /* Fix the relocation's type.  */
1399
              irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1400
                                           R_CR16_IMM16);
1401
 
1402
              /* Delete two bytes of data.  */
1403
              if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec,
1404
                                                  irel->r_offset + 2, 2))
1405
                 goto error_return;
1406
 
1407
              /* That will change things, so, we should relax again.
1408
                 Note that this is not required, and it may be slow.  */
1409
                 *again = TRUE;
1410
            }
1411
        }
1412
 
1413
      /* Try to turn a 20/16bit immediate address into
1414
         a 4bit immediate address.  */
1415
      if ((ELF32_R_TYPE (irel->r_info) == (int) R_CR16_IMM20)
1416
          || (ELF32_R_TYPE (irel->r_info) == (int) R_CR16_IMM16))
1417
        {
1418
          bfd_vma value = symval;
1419
 
1420
          /* See if the value will fit in 4 bits.  */
1421
          if ((long) value < 0xf && (long) value > 0)
1422
            {
1423
              unsigned short code;
1424
 
1425
              /* Get the opcode.  */
1426
              code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1427
 
1428
              /* Note that we've changed the relocs, section contents, etc.  */
1429
              elf_section_data (sec)->relocs = internal_relocs;
1430
              elf_section_data (sec)->this_hdr.contents = contents;
1431
              symtab_hdr->contents = (unsigned char *) isymbuf;
1432
 
1433
              /* Fix the opcode.  */
1434
              if (((code & 0x0f00) == 0x0400) || ((code & 0x0f00) == 0x0500))
1435
                {
1436
                  if ((code & 0x0f00) == 0x0400)      /* For movd imm20.  */
1437
                    bfd_put_8 (abfd, 0x60, contents + irel->r_offset);
1438
                  else                                /* For addd imm20.  */
1439
                    bfd_put_8 (abfd, 0x54, contents + irel->r_offset);
1440
                  bfd_put_8 (abfd, (code & 0xf0) >> 4, contents + irel->r_offset + 1);
1441
                }
1442
              else
1443
                {
1444
                  if ((code & 0xfff0) == 0x56b0)       /*  For cmpd imm16.  */
1445
                    bfd_put_8 (abfd, 0x56, contents + irel->r_offset);
1446
                  else if ((code & 0xfff0) == 0x54b0)  /*  For movd imm16.  */
1447
                    bfd_put_8 (abfd, 0x54, contents + irel->r_offset);
1448
                  else if ((code & 0xfff0) == 0x58b0)  /*  For movb imm16.  */
1449
                    bfd_put_8 (abfd, 0x58, contents + irel->r_offset);
1450
                  else if ((code & 0xfff0) == 0x5Ab0)  /*  For movw imm16.  */
1451
                    bfd_put_8 (abfd, 0x5A, contents + irel->r_offset);
1452
                  else if ((code & 0xfff0) == 0x60b0)  /*  For addd imm16.  */
1453
                    bfd_put_8 (abfd, 0x60, contents + irel->r_offset);
1454
                  else if ((code & 0xfff0) == 0x30b0)  /*  For addb imm16.  */
1455
                    bfd_put_8 (abfd, 0x30, contents + irel->r_offset);
1456
                  else if ((code & 0xfff0) == 0x2Cb0)  /*  For addub imm16.  */
1457
                    bfd_put_8 (abfd, 0x2C, contents + irel->r_offset);
1458
                  else if ((code & 0xfff0) == 0x32b0)  /*  For adduw imm16.  */
1459
                    bfd_put_8 (abfd, 0x32, contents + irel->r_offset);
1460
                  else if ((code & 0xfff0) == 0x38b0)  /*  For subb imm16.  */
1461
                    bfd_put_8 (abfd, 0x38, contents + irel->r_offset);
1462
                  else if ((code & 0xfff0) == 0x3Ab0)  /*  For subw imm16.  */
1463
                    bfd_put_8 (abfd, 0x3A, contents + irel->r_offset);
1464
                  else if ((code & 0xfff0) == 0x50b0)  /*  For cmpb imm16.  */
1465
                    bfd_put_8 (abfd, 0x50, contents + irel->r_offset);
1466
                  else if ((code & 0xfff0) == 0x52b0)  /*  For cmpw imm16.  */
1467
                    bfd_put_8 (abfd, 0x52, contents + irel->r_offset);
1468
                  else
1469
                    continue;
1470
 
1471
                  bfd_put_8 (abfd, (code & 0xf), contents + irel->r_offset + 1);
1472
                }
1473
 
1474
              /* Fix the relocation's type.  */
1475
              irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1476
                                           R_CR16_IMM4);
1477
 
1478
              /* Delete two bytes of data.  */
1479
              if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec,
1480
                                                  irel->r_offset + 2, 2))
1481
                goto error_return;
1482
 
1483
              /* That will change things, so, we should relax again.
1484
                 Note that this is not required, and it may be slow.  */
1485
              *again = TRUE;
1486
            }
1487
        }
1488
    }
1489
 
1490
  if (isymbuf != NULL
1491
      && symtab_hdr->contents != (unsigned char *) isymbuf)
1492
    {
1493
      if (! link_info->keep_memory)
1494
        free (isymbuf);
1495
      else
1496
        /* Cache the symbols for elf_link_input_bfd.  */
1497
        symtab_hdr->contents = (unsigned char *) isymbuf;
1498
    }
1499
 
1500
  if (contents != NULL
1501
      && elf_section_data (sec)->this_hdr.contents != contents)
1502
    {
1503
      if (! link_info->keep_memory)
1504
        free (contents);
1505
      else
1506
        /* Cache the section contents for elf_link_input_bfd.  */
1507
        elf_section_data (sec)->this_hdr.contents = contents;
1508
    }
1509
 
1510
  if (internal_relocs != NULL
1511
      && elf_section_data (sec)->relocs != internal_relocs)
1512
    free (internal_relocs);
1513
 
1514
  return TRUE;
1515
 
1516
 error_return:
1517
  if (isymbuf != NULL
1518
      && symtab_hdr->contents != (unsigned char *) isymbuf)
1519
    free (isymbuf);
1520
  if (contents != NULL
1521
      && elf_section_data (sec)->this_hdr.contents != contents)
1522
    free (contents);
1523
  if (internal_relocs != NULL
1524
      && elf_section_data (sec)->relocs != internal_relocs)
1525
    free (internal_relocs);
1526
 
1527
  return FALSE;
1528
}
1529
 
1530
static asection *
1531
elf32_cr16_gc_mark_hook (asection *sec,
1532
                         struct bfd_link_info *info ATTRIBUTE_UNUSED,
1533
                         Elf_Internal_Rela *rel ATTRIBUTE_UNUSED,
1534
                         struct elf_link_hash_entry *h,
1535
                         Elf_Internal_Sym *sym)
1536
{
1537
  if (h == NULL)
1538
    return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
1539
 
1540
  switch (h->root.type)
1541
    {
1542
      case bfd_link_hash_defined:
1543
      case bfd_link_hash_defweak:
1544
        return h->root.u.def.section;
1545
 
1546
      case bfd_link_hash_common:
1547
        return h->root.u.c.p->section;
1548
 
1549
      default:
1550
        return NULL;
1551
    }
1552
}
1553
 
1554
/* Update the got entry reference counts for the section being removed.  */
1555
 
1556
static bfd_boolean
1557
elf32_cr16_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED,
1558
                          struct bfd_link_info *info ATTRIBUTE_UNUSED,
1559
                          asection *sec ATTRIBUTE_UNUSED,
1560
                          const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED)
1561
{
1562
  /* We don't support garbage collection of GOT and PLT relocs yet.  */
1563
  return TRUE;
1564
}
1565
 
1566
/* Definitions for setting CR16 target vector.  */
1567
#define TARGET_LITTLE_SYM                 bfd_elf32_cr16_vec
1568
#define TARGET_LITTLE_NAME                "elf32-cr16"
1569
#define ELF_ARCH                          bfd_arch_cr16
1570
#define ELF_MACHINE_CODE                  EM_CR16
1571
#define ELF_MAXPAGESIZE                   0x1
1572
#define elf_symbol_leading_char           '_'
1573
 
1574
#define bfd_elf32_bfd_reloc_type_lookup   elf_cr16_reloc_type_lookup
1575
#define bfd_elf32_bfd_reloc_name_lookup   elf_cr16_reloc_name_lookup
1576
#define elf_info_to_howto                 elf_cr16_info_to_howto
1577
#define elf_info_to_howto_rel             0
1578
#define elf_backend_relocate_section      elf32_cr16_relocate_section
1579
#define bfd_elf32_bfd_relax_section       elf32_cr16_relax_section
1580
#define bfd_elf32_bfd_get_relocated_section_contents \
1581
                                elf32_cr16_get_relocated_section_contents
1582
#define elf_backend_gc_mark_hook          elf32_cr16_gc_mark_hook
1583
#define elf_backend_gc_sweep_hook         elf32_cr16_gc_sweep_hook
1584
#define elf_backend_can_gc_sections       1
1585
#define elf_backend_rela_normal           1
1586
 
1587
#include "elf32-target.h"

powered by: WebSVN 2.1.0

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