Back to index

cell-binutils  2.17cvs20070401
elf32-cr16c.c
Go to the documentation of this file.
00001 /* BFD back-end for National Semiconductor's CR16C ELF
00002    Copyright 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
00003 
00004    This file is part of BFD, the Binary File Descriptor library.
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010 
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015 
00016    You should have received a copy of the GNU General Public License
00017    along with this program; if not, write to the Free Software
00018    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00019 
00020 #include "bfd.h"
00021 #include "sysdep.h"
00022 #include "libbfd.h"
00023 #include "bfdlink.h"
00024 #include "elf/cr16c.h"
00025 #include "elf-bfd.h"
00026 
00027 
00028 #define USE_REL      1      /* CR16C uses REL relocations instead of RELA.  */
00029 
00030 /* The following definition is based on EMPTY_HOWTO macro, 
00031    but also initiates the "name" field in HOWTO struct.  */
00032 #define ONLY_NAME_HOWTO(C) \
00033   HOWTO ((C), 0, 0, 0, FALSE, 0, complain_overflow_dont, NULL, \
00034          STRINGX(C), FALSE, 0, 0, FALSE)
00035 
00036 /* reloc_map_index array maps CRASM relocation type into a BFD
00037    relocation enum. The array's indices are synchronized with 
00038    RINDEX_16C_* indices, created in include/elf/cr16c.h.
00039    The array is used in:
00040    1. elf32-cr16c.c : elf_cr16c_reloc_type_lookup().
00041    2. asreloc.c : find_reloc_type(). */
00042 
00043 RELOC_MAP reloc_map_index[RINDEX_16C_MAX] =
00044 {
00045   {R_16C_NUM08,     BFD_RELOC_16C_NUM08},
00046   {R_16C_NUM08_C,   BFD_RELOC_16C_NUM08_C},
00047   {R_16C_NUM16,     BFD_RELOC_16C_NUM16},
00048   {R_16C_NUM16_C,   BFD_RELOC_16C_NUM16_C},
00049   {R_16C_NUM32,     BFD_RELOC_16C_NUM32},
00050   {R_16C_NUM32_C,   BFD_RELOC_16C_NUM32_C},
00051   {R_16C_DISP04,    BFD_RELOC_16C_DISP04},
00052   {R_16C_DISP04_C,  BFD_RELOC_16C_DISP04_C},
00053   {R_16C_DISP08,    BFD_RELOC_16C_DISP08},
00054   {R_16C_DISP08_C,  BFD_RELOC_16C_DISP08_C},
00055   {R_16C_DISP16,    BFD_RELOC_16C_DISP16},
00056   {R_16C_DISP16_C,  BFD_RELOC_16C_DISP16_C},
00057   {R_16C_DISP24,    BFD_RELOC_16C_DISP24},
00058   {R_16C_DISP24_C,  BFD_RELOC_16C_DISP24_C},
00059   {R_16C_DISP24a,   BFD_RELOC_16C_DISP24a},
00060   {R_16C_DISP24a_C, BFD_RELOC_16C_DISP24a_C},
00061   {R_16C_REG04,     BFD_RELOC_16C_REG04},
00062   {R_16C_REG04_C,   BFD_RELOC_16C_REG04_C},
00063   {R_16C_REG04a,    BFD_RELOC_16C_REG04a},
00064   {R_16C_REG04a_C,  BFD_RELOC_16C_REG04a_C},
00065   {R_16C_REG14,     BFD_RELOC_16C_REG14},
00066   {R_16C_REG14_C,   BFD_RELOC_16C_REG14_C},
00067   {R_16C_REG16,     BFD_RELOC_16C_REG16},
00068   {R_16C_REG16_C,   BFD_RELOC_16C_REG16_C},
00069   {R_16C_REG20,     BFD_RELOC_16C_REG20},
00070   {R_16C_REG20_C,   BFD_RELOC_16C_REG20_C},
00071   {R_16C_ABS20,     BFD_RELOC_16C_ABS20},
00072   {R_16C_ABS20_C,   BFD_RELOC_16C_ABS20_C},
00073   {R_16C_ABS24,     BFD_RELOC_16C_ABS24},
00074   {R_16C_ABS24_C,   BFD_RELOC_16C_ABS24_C},
00075   {R_16C_IMM04,     BFD_RELOC_16C_IMM04},
00076   {R_16C_IMM04_C,   BFD_RELOC_16C_IMM04_C},
00077   {R_16C_IMM16,     BFD_RELOC_16C_IMM16},
00078   {R_16C_IMM16_C,   BFD_RELOC_16C_IMM16_C},
00079   {R_16C_IMM20,     BFD_RELOC_16C_IMM20},
00080   {R_16C_IMM20_C,   BFD_RELOC_16C_IMM20_C},
00081   {R_16C_IMM24,     BFD_RELOC_16C_IMM24},
00082   {R_16C_IMM24_C,   BFD_RELOC_16C_IMM24_C},
00083   {R_16C_IMM32,     BFD_RELOC_16C_IMM32},
00084   {R_16C_IMM32_C,   BFD_RELOC_16C_IMM32_C}
00085 };
00086 
00087 static reloc_howto_type elf_howto_table[] =
00088 {
00089   /* 00 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM08),
00090   /* 01 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM08_C),
00091   /* 02 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM16),
00092   /* 03 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM16_C),
00093   /* 04 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM32),
00094   /* 05 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM32_C),
00095   /* 06 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP04),
00096   /* 07 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP04_C),
00097   /* 08 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP08),
00098   /* 09 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP08_C),
00099   /* 10 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP16),
00100   /* 11 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP16_C),
00101   /* 12 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP24),
00102   /* 13 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP24_C),
00103   /* 14 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP24a),
00104   /* 15 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP24a_C),
00105   /* 16 */ ONLY_NAME_HOWTO (RINDEX_16C_REG04),
00106   /* 17 */ ONLY_NAME_HOWTO (RINDEX_16C_REG04_C),
00107   /* 18 */ ONLY_NAME_HOWTO (RINDEX_16C_REG04a),
00108   /* 19 */ ONLY_NAME_HOWTO (RINDEX_16C_REG04a_C),
00109   /* 20 */ ONLY_NAME_HOWTO (RINDEX_16C_REG14),
00110   /* 21 */ ONLY_NAME_HOWTO (RINDEX_16C_REG14_C),
00111   /* 22 */ ONLY_NAME_HOWTO (RINDEX_16C_REG16),
00112   /* 23 */ ONLY_NAME_HOWTO (RINDEX_16C_REG16_C),
00113   /* 24 */ ONLY_NAME_HOWTO (RINDEX_16C_REG20),
00114   /* 25 */ ONLY_NAME_HOWTO (RINDEX_16C_REG20_C),
00115   /* 26 */ ONLY_NAME_HOWTO (RINDEX_16C_ABS20),
00116   /* 27 */ ONLY_NAME_HOWTO (RINDEX_16C_ABS20_C),
00117   /* 28 */ ONLY_NAME_HOWTO (RINDEX_16C_ABS24),
00118   /* 29 */ ONLY_NAME_HOWTO (RINDEX_16C_ABS24_C),
00119   /* 30 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM04),
00120   /* 31 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM04_C),
00121   /* 32 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM16),
00122   /* 33 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM16_C),
00123   /* 34 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM20),
00124   /* 35 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM20_C),
00125   /* 36 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM24),
00126   /* 37 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM24_C),
00127   /* 38 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM32),
00128   /* 39 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM32_C)
00129 };
00130 
00131 
00132 /* Code to turn a code_type into a howto ptr, uses the above howto table.  */
00133 
00134 static reloc_howto_type *
00135 elf_cr16c_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
00136                           bfd_reloc_code_real_type code)
00137 {
00138   unsigned int i;
00139 
00140   for (i = 0; i < RINDEX_16C_MAX; i++)
00141     {
00142       if (code == reloc_map_index[i].bfd_reloc_enum)
00143        {
00144          /* printf ("CR16C Relocation Type is - %x\n", code); */
00145          return & elf_howto_table[i];
00146        }
00147     }
00148 
00149   /* printf ("This relocation Type is not supported - %x\n", code); */
00150   return 0;
00151 }
00152 
00153 static reloc_howto_type *
00154 elf_cr16c_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
00155                           const char *r_name)
00156 {
00157   unsigned int i;
00158 
00159   for (i = 0; i < sizeof (elf_howto_table) / sizeof (elf_howto_table[0]); i++)
00160     if (elf_howto_table[i].name != NULL
00161        && strcasecmp (elf_howto_table[i].name, r_name) == 0)
00162       return &elf_howto_table[i];
00163 
00164   return NULL;
00165 }
00166 
00167 static void
00168 elf_cr16c_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
00169                       arelent *cache_ptr ATTRIBUTE_UNUSED,
00170                       Elf_Internal_Rela *dst ATTRIBUTE_UNUSED)
00171 {
00172   abort ();
00173 }
00174 
00175 static void
00176 elf_cr16c_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
00177                           arelent *cache_ptr,
00178                           Elf_Internal_Rela *dst)
00179 {
00180   unsigned int r_type = ELF32_R_TYPE (dst->r_info);
00181 
00182   BFD_ASSERT (r_type < (unsigned int) RINDEX_16C_MAX);
00183   cache_ptr->howto = &elf_howto_table[r_type];
00184 }
00185 
00186 /* Perform a relocation as part of a final link.  */
00187 
00188 static bfd_reloc_status_type
00189 cr16c_elf_final_link_relocate (reloc_howto_type *howto,
00190                             bfd *abfd,
00191                             bfd *output_bfd ATTRIBUTE_UNUSED,
00192                             asection *input_section,
00193                             bfd_byte *data,
00194                             bfd_vma octets,
00195                             bfd_vma Rvalue,
00196                             bfd_vma addend ATTRIBUTE_UNUSED,
00197                             struct bfd_link_info *info ATTRIBUTE_UNUSED,
00198                             asection *sym_sec ATTRIBUTE_UNUSED,
00199                             int is_local ATTRIBUTE_UNUSED)
00200 {
00201   long value;
00202   short sword;                     /* Extracted from the hole and put back.  */
00203   unsigned long format, addr_type, code_factor;
00204   unsigned short size;
00205   unsigned short r_type;
00206   asymbol *symbol = NULL;
00207 
00208   unsigned long disp20_opcod;
00209   char neg = 0;
00210   char neg2pos = 0;
00211 
00212   long left_val = 0;
00213   long plus_factor = 0;            /* To be added to the hole.  */
00214 
00215 #define MIN_BYTE     ((int) 0xFFFFFF80)
00216 #define MIN_WORD     ((int) 0xFFFF8000)
00217 #define       MAX_UWORD     ((unsigned) 0x0000FFFF)
00218 #define       MAX_UBYTE     ((unsigned) 0x000000FF)
00219 
00220   r_type = reloc_map_index[howto->type].cr_reloc_type;
00221   format = r_type & R_FORMAT;
00222   size = r_type & R_SIZESP;
00223   addr_type = r_type & R_ADDRTYPE;
00224   code_factor = ((addr_type == R_CODE_ADDR) ? 1 : 0);
00225 
00226   if (sym_sec)
00227     symbol = sym_sec->symbol;
00228 
00229   switch (format)
00230     {
00231     case R_NUMBER:
00232       switch (size)
00233        {
00234        case R_S_16C_08:     /* One byte.  */
00235          value = bfd_get_8 (abfd, (char *) data + octets);
00236          break;
00237        case R_S_16C_16:     /* Two bytes. */
00238          sword = bfd_get_16 (abfd, (bfd_byte *) data + octets);
00239          value = sword;
00240          break;
00241        case R_S_16C_32:     /* Four bytes.  */
00242          value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
00243          break;
00244        default:
00245          return bfd_reloc_notsupported;
00246        }
00247       break;
00248 
00249     case R_16C_DISPL:
00250       switch (size)
00251        {
00252        case R_S_16C_04:    /* word1(4-7).  */
00253          value = bfd_get_8 (abfd, (char *) data + octets);
00254          left_val = value & 0xF;
00255          value = (value & 0xF0) >> 4;
00256          value++;
00257          value <<= 1;
00258          break;
00259        case R_S_16C_08:    /* word1(0-3,8-11).  */
00260          sword = bfd_get_16 (abfd, (char *) data + octets);
00261          value = sword & 0x000F;
00262          value |= ((sword & 0x0F00) >> 4);
00263          left_val = sword & 0xF0F0;
00264          value <<= 1;
00265          if (value & 0x100)
00266            value |= 0xFFFFFF00;
00267          break;
00268        case R_S_16C_16:    /* word2.  */
00269          sword = bfd_get_16 (abfd, (bfd_byte *) data + octets);
00270          value = sword;
00271          value = ((value & 0xFFFE) >> 1) | ((value & 0x1) << 15);
00272          value <<= 1;
00273          if (value & 0x10000)
00274            value |= 0xFFFF0000;
00275          break;
00276        case R_S_16C_24_a:   /* word1(0-7),word2.  */
00277          value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
00278          left_val = value & 0x0000FF00;
00279          value = ((value & 0xFFFE0000) >> 17) |
00280            ((value & 0x00010000) << 7) | ((value & 0x000000FF) << 15);
00281          value <<= 1;
00282          if (value & 0x1000000)
00283            value |= 0xFE000000;
00284          break;
00285        case R_S_16C_24:    /* word2(0-3,8-11),word3.  */
00286          value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
00287          left_val = value & 0x0000F0F0;
00288          value = ((value >> 16) & 0x0000FFFF) |
00289            ((value & 0x00000F00) << 8) | ((value & 0x0000000F) << 20);
00290 
00291          value = ((value & 0x00FFFFFE) >> 1) | ((value & 0x00000001) << 23);
00292 
00293          value <<= 1;
00294          if (value & 0x1000000)
00295            value |= 0xFE000000;
00296          break;
00297        default:
00298          return bfd_reloc_notsupported;
00299        }
00300       break;
00301 
00302     case R_16C_REGREL:
00303       switch (size)
00304        {
00305        case R_S_16C_04:    /* word1(12-15) not scaled.  */
00306          value = bfd_get_8 (abfd, (char *) data + octets);
00307          left_val = value & 0xF0;
00308          value = value & 0xF;
00309          break;
00310        case R_S_16C_04_a:   /* word1(12-15) scaled by 2.  */
00311          value = bfd_get_8 (abfd, (char *) data + octets);
00312          left_val = value & 0xF0;
00313          value = value & 0xF;
00314          value <<= 1;
00315          break;
00316        case R_S_16C_14:    /* word1(4-5),word2(0-3,8-15).  */
00317          value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
00318          left_val = value & 0x00F0FFCF;
00319          value = ((value & 0xc0000000) >> 24) |
00320            ((value & 0x3F000000) >> 16) |
00321            ((value & 0x000F0000) >> 16) | (value & 0x00000030);
00322          break;
00323        case R_S_16C_16:    /* word2.  */
00324          sword = bfd_get_16 (abfd, (bfd_byte *) data + octets);
00325          value = sword;
00326          break;
00327        case R_S_16C_20:    /* word2(8-11),word3.  */
00328          value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
00329          left_val = value & 0xF0;
00330          value = (value & 0xF) << 16;
00331          sword = bfd_get_16 (abfd, (bfd_byte *) data + octets + 1);
00332          value = value | (unsigned short) sword;
00333          disp20_opcod = bfd_get_32 (abfd, (bfd_byte *) data + octets - 3);
00334          disp20_opcod |= 0x0FFF0000;
00335          if ((disp20_opcod == 0x4FFF0018) ||     /* loadb -disp20(reg) */
00336              (disp20_opcod == 0x5FFF0018) ||     /* loadb -disp20(rp)  */
00337              (disp20_opcod == 0x8FFF0018) ||     /* loadd -disp20(reg) */
00338              (disp20_opcod == 0x9FFF0018) ||     /* loadd -disp20(rp)  */
00339              (disp20_opcod == 0xCFFF0018) ||     /* loadw -disp20(reg) */
00340              (disp20_opcod == 0xDFFF0018) ||     /* loadw -disp20(rp)  */
00341              (disp20_opcod == 0x4FFF0019) ||     /* storb -disp20(reg) */
00342              (disp20_opcod == 0x5FFF0019) ||     /* storb -disp20(rp)  */
00343              (disp20_opcod == 0x8FFF0019) ||     /* stord -disp20(reg) */
00344              (disp20_opcod == 0x9FFF0019) ||     /* stord -disp20(rp)  */
00345              (disp20_opcod == 0xCFFF0019) ||     /* storw -disp20(reg) */
00346              (disp20_opcod == 0xDFFF0019))
00347            {  /* storw -disp20(rp).  */
00348              neg = 1;
00349              value |= 0xFFF00000;
00350            }
00351 
00352          break;
00353        default:
00354          return bfd_reloc_notsupported;
00355        }
00356       break;
00357 
00358     case R_16C_ABS:
00359       switch (size)
00360        {
00361        case R_S_16C_20:    /* word1(0-3),word2.  */
00362          value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
00363          left_val = value & 0x0000FFF0;
00364          value = ((value & 0xFFFF0000) >> 16) |
00365            ((value & 0x0000000F) << 16);
00366          break;
00367        case R_S_16C_24:   /* word2(0-3,8-11),word3.  */
00368          value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
00369          left_val = value & 0x0000F0F0;
00370          value = ((value & 0xFFFF0000) >> 16) |
00371            ((value & 0x00000F00) << 8) | ((value & 0x0000000F) << 20);
00372          break;
00373        default:
00374          return bfd_reloc_notsupported;
00375        }
00376       break;
00377 
00378     case R_16C_IMMED:
00379       switch (size)
00380        {
00381        case R_S_16C_04:    /* word1/2(4-7).  */
00382          value = bfd_get_8 (abfd, (char *) data + octets);
00383          left_val = value & 0xF;
00384          value = (value & 0xF0) >> 4;
00385          break;
00386        case R_S_16C_16:    /* word2.  */
00387          sword = bfd_get_16 (abfd, (bfd_byte *) data + octets);
00388          value = sword;
00389          break;
00390        case R_S_16C_20:    /* word1(0-3),word2.  */
00391          value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
00392          left_val = value & 0x0000FFF0;
00393          value = ((value & 0xFFFF0000) >> 16) |
00394            ((value & 0x0000000F) << 16);
00395          break;
00396        case R_S_16C_32:    /* word2, word3.  */
00397          value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
00398          value = ((value & 0x0000FFFF) << 16) |
00399            ((value & 0xFFFF0000) >> 16);
00400          break;
00401        default:
00402          return bfd_reloc_notsupported;
00403        }
00404       break;
00405     default:
00406       return bfd_reloc_notsupported;
00407     }
00408 
00409   switch ((r_type & R_RELTO) >> 4)
00410     {
00411 
00412     case 0:   /* R_ABS.  */
00413       plus_factor = Rvalue;
00414       break;
00415     case 1:   /* R_PCREL.  */
00416       plus_factor = Rvalue -
00417        (input_section->output_section->vma + input_section->output_offset);
00418       break;
00419     default:
00420       return bfd_reloc_notsupported;
00421     }
00422 
00423   if (neg)
00424     {
00425       if (plus_factor >= -value)
00426        neg2pos = 1;
00427       /* We need to change load/stor with negative
00428         displ opcode to positive disp opcode (CR16C).  */
00429     }
00430 
00431   value = value + (plus_factor >> code_factor);
00432 
00433   switch (format)
00434     {
00435     case R_NUMBER:
00436       switch (size)
00437        {
00438        case R_S_16C_08:     /* One byte.  */
00439          if (value > (int) MAX_UBYTE || value < MIN_BYTE)
00440            return bfd_reloc_overflow;
00441          value &= 0xFF;
00442          bfd_put_8 (abfd, (bfd_vma) value, (unsigned char *) data + octets);
00443          break;
00444 
00445        case R_S_16C_16:     /* Two bytes.  */
00446          if (value > (int) MAX_UWORD || value < MIN_WORD)
00447            return bfd_reloc_overflow;
00448          value &= 0xFFFF;
00449          sword = value;
00450          bfd_put_16 (abfd, (bfd_vma) sword,
00451                     (unsigned char *) data + octets);
00452          break;
00453 
00454        case R_S_16C_32:     /* Four bytes.  */
00455          value &= 0xFFFFFFFF;
00456          bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
00457          break;
00458 
00459        default:
00460          return bfd_reloc_notsupported;
00461        }
00462       break;
00463 
00464     case R_16C_DISPL:
00465       switch (size)
00466        {
00467        case R_S_16C_04:     /* word1(4-7).  */
00468          if ((value - 32) > 32 || value < 2)
00469            return bfd_reloc_overflow;
00470          value >>= 1;
00471          value--;
00472          value &= 0xF;
00473          value <<= 4;
00474          value |= left_val;
00475          bfd_put_8 (abfd, (bfd_vma) value, (unsigned char *) data + octets);
00476          break;
00477 
00478        case R_S_16C_08:    /* word1(0-3,8-11).  */
00479          if (value > 255 || value < -256 || value == 0x80)
00480            return bfd_reloc_overflow;
00481          value &= 0x1FF;
00482          value >>= 1;
00483          sword = value & 0x000F;
00484          sword |= (value & 0x00F0) << 4;
00485          sword |= left_val;
00486          bfd_put_16 (abfd, (bfd_vma) sword,
00487                     (unsigned char *) data + octets);
00488          break;
00489 
00490        case R_S_16C_16:    /* word2.  */
00491          if (value > 65535 || value < -65536)
00492            return bfd_reloc_overflow;
00493          value >>= 1;
00494          value &= 0xFFFF;
00495          value = ((value & 0x8000) >> 15) | ((value & 0x7FFF) << 1);
00496          sword = value;
00497          bfd_put_16 (abfd, (bfd_vma) sword,
00498                     (unsigned char *) data + octets);
00499          break;
00500 
00501        case R_S_16C_24_a:   /* word1(0-7),word2.  */
00502          if (value > 16777215 || value < -16777216)
00503            return bfd_reloc_overflow;
00504          value &= 0x1FFFFFF;
00505          value >>= 1;
00506          value = ((value & 0x00007FFF) << 17) |
00507            ((value & 0x00800000) >> 7) | ((value & 0x007F8000) >> 15);
00508          value |= left_val;
00509          bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
00510          break;
00511 
00512        case R_S_16C_24:    /* word2(0-3,8-11),word3.  */
00513          if (value > 16777215 || value < -16777216)
00514            return bfd_reloc_overflow;
00515          value &= 0x1FFFFFF;
00516          value >>= 1;
00517 
00518          value = ((value & 0x007FFFFF) << 1) | ((value & 0x00800000) >> 23);
00519 
00520          value = ((value & 0x0000FFFF) << 16) |
00521            ((value & 0x000F0000) >> 8) | ((value & 0x00F00000) >> 20);
00522          value |= left_val;
00523          bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
00524          break;
00525 
00526        default:
00527          return bfd_reloc_notsupported;
00528        }
00529       break;
00530 
00531     case R_16C_REGREL:
00532       switch (size)
00533        {
00534        case R_S_16C_04:     /* word1(12-15) not scaled.  */
00535          if (value > 13 || value < 0)
00536            return bfd_reloc_overflow;
00537          value &= 0xF;
00538          value |= left_val;
00539          bfd_put_8 (abfd, (bfd_vma) value, (unsigned char *) data + octets);
00540          break;
00541 
00542        case R_S_16C_04_a:   /* word1(12-15) not scaled.  */
00543          if (value > 26 || value < 0)
00544            return bfd_reloc_overflow;
00545          value &= 0x1F;
00546          value >>= 1;
00547          value |= left_val;
00548          bfd_put_8 (abfd, (bfd_vma) value, (unsigned char *) data + octets);
00549          break;
00550 
00551        case R_S_16C_14:     /* word1(4-5),word2(0-3,8-15).  */
00552          if (value < 0 || value > 16383)
00553            return bfd_reloc_overflow;
00554          value &= 0x3FFF;
00555          value = ((value & 0x000000c0) << 24) |
00556            ((value & 0x00003F00) << 16) |
00557            ((value & 0x0000000F) << 16) | (value & 0x00000030);
00558          value |= left_val;
00559          bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
00560          break;
00561 
00562        case R_S_16C_16:     /* word2.  */
00563          if (value > 65535 || value < 0)
00564            return bfd_reloc_overflow;
00565          value &= 0xFFFF;
00566          sword = value;
00567          bfd_put_16 (abfd, (bfd_vma) sword,
00568                     (unsigned char *) data + octets);
00569          break;
00570 
00571        case R_S_16C_20:     /* word2(8-11),word3.  */
00572          /* if (value > 1048575 || value < 0) RELOC_ERROR(1); */
00573          value &= 0xFFFFF;
00574          sword = value & 0x0000FFFF;
00575          value = (value & 0x000F0000) >> 16;
00576          value |= left_val;
00577          bfd_put_8 (abfd, (bfd_vma) value, (unsigned char *) data + octets);
00578          bfd_put_16 (abfd, (bfd_vma) sword,
00579                     (unsigned char *) data + octets + 1);
00580          if (neg2pos)
00581            {
00582              /* Change load/stor negative displ opcode
00583                 to load/stor positive displ opcode.  */
00584              value = bfd_get_8 (abfd, (char *) data + octets - 3);
00585              value &= 0xF7;
00586              value |= 0x2;
00587              bfd_put_8 (abfd, (bfd_vma) value,
00588                       (unsigned char *) data + octets - 3);
00589            }
00590          break;
00591 
00592        default:
00593          return bfd_reloc_notsupported;
00594        }
00595       break;
00596 
00597     case R_16C_ABS:
00598       switch (size)
00599        {
00600        case R_S_16C_20:     /* word1(0-3),word2.  */
00601          if (value > 1048575 || value < 0)
00602            return bfd_reloc_overflow;
00603          value &= 0xFFFFF;
00604          value = ((value & 0x0000FFFF) << 16) |
00605            ((value & 0x000F0000) >> 16);
00606          value |= left_val;
00607          bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
00608          break;
00609 
00610        case R_S_16C_24:     /* word2(0-3,8-11),word3.  */
00611          /* if (value > 16777215 || value < 0) RELOC_ERROR(1); */
00612          value &= 0xFFFFFF;
00613          value = ((value & 0x0000FFFF) << 16) |
00614            ((value & 0x000F0000) >> 8) | ((value & 0x00F00000) >> 20);
00615          value |= left_val;
00616          bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
00617          break;
00618 
00619        default:
00620          return bfd_reloc_notsupported;
00621        }
00622       break;
00623 
00624     case R_16C_IMMED:
00625       switch (size)
00626        {
00627        case R_S_16C_04:     /* word1/2(4-7).  */
00628          if (value > 15 || value < -1)
00629            return bfd_reloc_overflow;
00630          value &= 0xF;
00631          value <<= 4;
00632          value |= left_val;
00633          bfd_put_8 (abfd, (bfd_vma) value, (unsigned char *) data + octets);
00634          break;
00635 
00636        case R_S_16C_16:     /* word2.  */
00637          if (value > 32767 || value < -32768)
00638            return bfd_reloc_overflow;
00639          value &= 0xFFFF;
00640          sword = value;
00641          bfd_put_16 (abfd, (bfd_vma) sword,
00642                     (unsigned char *) data + octets);
00643          break;
00644 
00645        case R_S_16C_20:     /* word1(0-3),word2.  */
00646          if (value > 1048575 || value < 0)
00647            return bfd_reloc_overflow;
00648          value &= 0xFFFFF;
00649          value = ((value & 0x0000FFFF) << 16) |
00650            ((value & 0x000F0000) >> 16);
00651          value |= left_val;
00652          bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
00653          break;
00654 
00655        case R_S_16C_32:     /* word2, word3.  */
00656          value &= 0xFFFFFFFF;
00657          value = ((value & 0x0000FFFF) << 16) |
00658            ((value & 0xFFFF0000) >> 16);
00659          bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
00660          break;
00661 
00662        default:
00663          return bfd_reloc_notsupported;
00664        }
00665       break;
00666     default:
00667       return bfd_reloc_notsupported;
00668     }
00669 
00670   return bfd_reloc_ok;
00671 }
00672 
00673 /* Relocate a CR16C ELF section.  */
00674 
00675 static bfd_boolean
00676 elf32_cr16c_relocate_section (bfd *output_bfd,
00677                            struct bfd_link_info *info,
00678                            bfd *input_bfd,
00679                            asection *input_section,
00680                            bfd_byte *contents,
00681                            Elf_Internal_Rela *relocs,
00682                            Elf_Internal_Sym *local_syms,
00683                            asection **local_sections)
00684 {
00685   Elf_Internal_Shdr *symtab_hdr;
00686   struct elf_link_hash_entry **sym_hashes;
00687   Elf_Internal_Rela *rel, *relend;
00688 
00689   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
00690   sym_hashes = elf_sym_hashes (input_bfd);
00691 
00692   rel = relocs;
00693   relend = relocs + input_section->reloc_count;
00694   for (; rel < relend; rel++)
00695     {
00696       int r_type;
00697       reloc_howto_type *howto;
00698       unsigned long r_symndx;
00699       Elf_Internal_Sym *sym;
00700       asection *sec;
00701       struct elf_link_hash_entry *h;
00702       bfd_vma relocation;
00703       bfd_reloc_status_type r;
00704 
00705       r_symndx = ELF32_R_SYM (rel->r_info);
00706       r_type = ELF32_R_TYPE (rel->r_info);
00707       howto = elf_howto_table + r_type;
00708 
00709       h = NULL;
00710       sym = NULL;
00711       sec = NULL;
00712       if (r_symndx < symtab_hdr->sh_info)
00713        {
00714          sym = local_syms + r_symndx;
00715          sec = local_sections[r_symndx];
00716          relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
00717        }
00718       else
00719        {
00720          bfd_boolean unresolved_reloc, warned;
00721 
00722          RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
00723                                r_symndx, symtab_hdr, sym_hashes,
00724                                h, sec, relocation,
00725                                unresolved_reloc, warned);
00726        }
00727 
00728       if (sec != NULL && elf_discarded_section (sec))
00729        {
00730          /* For relocs against symbols from removed linkonce sections,
00731             or sections discarded by a linker script, we just want the
00732             section contents zeroed.  Avoid any special processing.  */
00733          _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
00734          rel->r_info = 0;
00735          rel->r_addend = 0;
00736          continue;
00737        }
00738 
00739       if (info->relocatable)
00740        {
00741          /* This is a relocatable link.  We don't have to change
00742             anything, unless the reloc is against a section symbol,
00743             in which case we have to adjust according to where the
00744             section symbol winds up in the output section.  */
00745          if (sym != NULL && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
00746            rel->r_addend += sec->output_offset;
00747          continue;
00748        }
00749 
00750       r = cr16c_elf_final_link_relocate (howto, input_bfd, output_bfd,
00751                                     input_section,
00752                                     contents, rel->r_offset,
00753                                     relocation, rel->r_addend,
00754                                     info, sec, h == NULL);
00755 
00756       if (r != bfd_reloc_ok)
00757        {
00758          const char *name;
00759          const char *msg = (const char *) 0;
00760 
00761          if (h != NULL)
00762            name = h->root.root.string;
00763          else
00764            {
00765              name = (bfd_elf_string_from_elf_section
00766                     (input_bfd, symtab_hdr->sh_link, sym->st_name));
00767              if (name == NULL || *name == '\0')
00768               name = bfd_section_name (input_bfd, sec);
00769            }
00770 
00771          switch (r)
00772            {
00773            case bfd_reloc_overflow:
00774              if (!((*info->callbacks->reloc_overflow)
00775                   (info, (h ? &h->root : NULL), name, howto->name,
00776                    (bfd_vma) 0, input_bfd, input_section,
00777                    rel->r_offset)))
00778               return FALSE;
00779              break;
00780 
00781            case bfd_reloc_undefined:
00782              if (!((*info->callbacks->undefined_symbol)
00783                   (info, name, input_bfd, input_section,
00784                    rel->r_offset, TRUE)))
00785               return FALSE;
00786              break;
00787 
00788            case bfd_reloc_outofrange:
00789              msg = _("internal error: out of range error");
00790              goto common_error;
00791 
00792            case bfd_reloc_notsupported:
00793              msg = _("internal error: unsupported relocation error");
00794              goto common_error;
00795 
00796            case bfd_reloc_dangerous:
00797              msg = _("internal error: dangerous error");
00798              goto common_error;
00799 
00800            default:
00801              msg = _("internal error: unknown error");
00802              /* fall through */
00803 
00804            common_error:
00805              if (!((*info->callbacks->warning)
00806                   (info, msg, name, input_bfd, input_section,
00807                    rel->r_offset)))
00808               return FALSE;
00809              break;
00810            }
00811        }
00812     }
00813 
00814   return TRUE;
00815 }
00816 
00817 /* CR16C ELF uses three common sections:
00818    One is for default common symbols (placed in usual common section).
00819    Second is for near common symbols (placed in "ncommon" section).
00820    Third is for far common symbols (placed in "fcommon" section).
00821    The following implementation is based on elf32-mips architecture */
00822 
00823 static asection  cr16c_elf_fcom_section;
00824 static asymbol   cr16c_elf_fcom_symbol;
00825 static asymbol * cr16c_elf_fcom_symbol_ptr;
00826 static asection  cr16c_elf_ncom_section;
00827 static asymbol   cr16c_elf_ncom_symbol;
00828 static asymbol * cr16c_elf_ncom_symbol_ptr;
00829 
00830 /* Given a BFD section, try to locate the
00831    corresponding ELF section index.  */
00832 
00833 static bfd_boolean
00834 elf32_cr16c_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED,
00835                                   asection *sec,
00836                                   int *retval)
00837 {
00838   if (strcmp (bfd_get_section_name (abfd, sec), ".fcommon") == 0)
00839     *retval = SHN_CR16C_FCOMMON;
00840   else if (strcmp (bfd_get_section_name (abfd, sec), ".ncommon") == 0)
00841     *retval = SHN_CR16C_NCOMMON;
00842   else
00843     return FALSE;
00844 
00845   return TRUE;
00846 }
00847 
00848 /* Handle the special CR16C section numbers that a symbol may use.  */
00849 
00850 static void
00851 elf32_cr16c_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED,
00852                             asymbol *asym)
00853 {
00854   elf_symbol_type *elfsym = (elf_symbol_type *) asym;
00855   unsigned int indx;
00856 
00857   indx = elfsym->internal_elf_sym.st_shndx;
00858 
00859   switch (indx)
00860     {
00861     case SHN_CR16C_FCOMMON:
00862       if (cr16c_elf_fcom_section.name == NULL)
00863        {
00864          /* Initialize the far common section.  */
00865          cr16c_elf_fcom_section.name = ".fcommon";
00866          cr16c_elf_fcom_section.flags = SEC_IS_COMMON | SEC_ALLOC;
00867          cr16c_elf_fcom_section.output_section = &cr16c_elf_fcom_section;
00868          cr16c_elf_fcom_section.symbol = &cr16c_elf_fcom_symbol;
00869          cr16c_elf_fcom_section.symbol_ptr_ptr = &cr16c_elf_fcom_symbol_ptr;
00870          cr16c_elf_fcom_symbol.name = ".fcommon";
00871          cr16c_elf_fcom_symbol.flags = BSF_SECTION_SYM;
00872          cr16c_elf_fcom_symbol.section = &cr16c_elf_fcom_section;
00873          cr16c_elf_fcom_symbol_ptr = &cr16c_elf_fcom_symbol;
00874        }
00875       asym->section = &cr16c_elf_fcom_section;
00876       asym->value = elfsym->internal_elf_sym.st_size;
00877       break;
00878     case SHN_CR16C_NCOMMON:
00879       if (cr16c_elf_ncom_section.name == NULL)
00880        {
00881          /* Initialize the far common section.  */
00882          cr16c_elf_ncom_section.name = ".ncommon";
00883          cr16c_elf_ncom_section.flags = SEC_IS_COMMON | SEC_ALLOC;
00884          cr16c_elf_ncom_section.output_section = &cr16c_elf_ncom_section;
00885          cr16c_elf_ncom_section.symbol = &cr16c_elf_ncom_symbol;
00886          cr16c_elf_ncom_section.symbol_ptr_ptr = &cr16c_elf_ncom_symbol_ptr;
00887          cr16c_elf_ncom_symbol.name = ".ncommon";
00888          cr16c_elf_ncom_symbol.flags = BSF_SECTION_SYM;
00889          cr16c_elf_ncom_symbol.section = &cr16c_elf_ncom_section;
00890          cr16c_elf_ncom_symbol_ptr = &cr16c_elf_ncom_symbol;
00891        }
00892       asym->section = &cr16c_elf_ncom_section;
00893       asym->value = elfsym->internal_elf_sym.st_size;
00894       break;
00895     }
00896 }
00897 
00898 /* Hook called by the linker routine which adds symbols from an object
00899    file.  We must handle the special cr16c section numbers here.  */
00900 
00901 static bfd_boolean
00902 elf32_cr16c_add_symbol_hook (bfd *abfd,
00903                           struct bfd_link_info *info ATTRIBUTE_UNUSED,
00904                           Elf_Internal_Sym *sym,
00905                           const char **namep ATTRIBUTE_UNUSED,
00906                           flagword *flagsp ATTRIBUTE_UNUSED,
00907                           asection **secp,
00908                           bfd_vma *valp)
00909 {
00910   unsigned int indx = sym->st_shndx;
00911 
00912   switch (indx)
00913     {
00914     case SHN_CR16C_FCOMMON:
00915       *secp = bfd_make_section_old_way (abfd, ".fcommon");
00916       (*secp)->flags |= SEC_IS_COMMON;
00917       *valp = sym->st_size;
00918       break;
00919     case SHN_CR16C_NCOMMON:
00920       *secp = bfd_make_section_old_way (abfd, ".ncommon");
00921       (*secp)->flags |= SEC_IS_COMMON;
00922       *valp = sym->st_size;
00923       break;
00924     }
00925 
00926   return TRUE;
00927 }
00928 
00929 static bfd_boolean
00930 elf32_cr16c_link_output_symbol_hook (struct bfd_link_info *info ATTRIBUTE_UNUSED,
00931                                  const char *name ATTRIBUTE_UNUSED,
00932                                  Elf_Internal_Sym *sym,
00933                                  asection *input_sec,
00934                                  struct elf_link_hash_entry *h ATTRIBUTE_UNUSED)
00935 {
00936   /* If we see a common symbol, which implies a relocatable link, then
00937      if a symbol was in a special common section in an input file, mark
00938      it as a special common in the output file.  */
00939 
00940   if (sym->st_shndx == SHN_COMMON)
00941     {
00942       if (strcmp (input_sec->name, ".fcommon") == 0)
00943        sym->st_shndx = SHN_CR16C_FCOMMON;
00944       else if (strcmp (input_sec->name, ".ncommon") == 0)
00945        sym->st_shndx = SHN_CR16C_NCOMMON;
00946     }
00947 
00948   return TRUE;
00949 }
00950 
00951 /* Definitions for setting CR16C target vector.  */
00952 #define TARGET_LITTLE_SYM          bfd_elf32_cr16c_vec
00953 #define TARGET_LITTLE_NAME         "elf32-cr16c"
00954 #define ELF_ARCH                   bfd_arch_cr16c
00955 #define ELF_MACHINE_CODE           EM_CR
00956 #define ELF_MAXPAGESIZE                   0x1
00957 #define elf_symbol_leading_char           '_'
00958 
00959 #define bfd_elf32_bfd_reloc_type_lookup          elf_cr16c_reloc_type_lookup
00960 #define bfd_elf32_bfd_reloc_name_lookup   elf_cr16c_reloc_name_lookup
00961 #define elf_info_to_howto                 elf_cr16c_info_to_howto
00962 #define elf_info_to_howto_rel                    elf_cr16c_info_to_howto_rel
00963 #define elf_backend_relocate_section             elf32_cr16c_relocate_section
00964 #define elf_backend_symbol_processing            elf32_cr16c_symbol_processing
00965 #define elf_backend_section_from_bfd_section     elf32_cr16c_section_from_bfd_section
00966 #define elf_backend_add_symbol_hook              elf32_cr16c_add_symbol_hook
00967 #define elf_backend_link_output_symbol_hook      elf32_cr16c_link_output_symbol_hook
00968 
00969 #define elf_backend_can_gc_sections     1
00970 
00971 #include "elf32-target.h"