Blame bfd/elf32-cr16c.c

Packit Service 706eca
/* BFD back-end for National Semiconductor's CR16C ELF
Packit Service 706eca
   Copyright (C) 2004-2018 Free Software Foundation, Inc.
Packit Service 706eca
Packit Service 706eca
   This file is part of BFD, the Binary File Descriptor library.
Packit Service 706eca
Packit Service 706eca
   This program is free software; you can redistribute it and/or modify
Packit Service 706eca
   it under the terms of the GNU General Public License as published by
Packit Service 706eca
   the Free Software Foundation; either version 3 of the License, or
Packit Service 706eca
   (at your option) any later version.
Packit Service 706eca
Packit Service 706eca
   This program is distributed in the hope that it will be useful,
Packit Service 706eca
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 706eca
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 706eca
   GNU General Public License for more details.
Packit Service 706eca
Packit Service 706eca
   You should have received a copy of the GNU General Public License
Packit Service 706eca
   along with this program; if not, write to the Free Software
Packit Service 706eca
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
Packit Service 706eca
   MA 02110-1301, USA.  */
Packit Service 706eca
Packit Service 706eca
#include "sysdep.h"
Packit Service 706eca
#include "bfd.h"
Packit Service 706eca
#include "libbfd.h"
Packit Service 706eca
#include "bfdlink.h"
Packit Service 706eca
#include "elf/cr16c.h"
Packit Service 706eca
#include "elf-bfd.h"
Packit Service 706eca
Packit Service 706eca
Packit Service 706eca
#define USE_REL	1	/* CR16C uses REL relocations instead of RELA.  */
Packit Service 706eca
Packit Service 706eca
/* The following definition is based on EMPTY_HOWTO macro,
Packit Service 706eca
   but also initiates the "name" field in HOWTO struct.  */
Packit Service 706eca
#define ONLY_NAME_HOWTO(C) \
Packit Service 706eca
  HOWTO ((C), 0, 0, 0, FALSE, 0, complain_overflow_dont, NULL, \
Packit Service 706eca
	  STRINGX(C), FALSE, 0, 0, FALSE)
Packit Service 706eca
Packit Service 706eca
/* reloc_map_index array maps CRASM relocation type into a BFD
Packit Service 706eca
   relocation enum. The array's indices are synchronized with
Packit Service 706eca
   RINDEX_16C_* indices, created in include/elf/cr16c.h.
Packit Service 706eca
   The array is used in:
Packit Service 706eca
   1. elf32-cr16c.c : elf_cr16c_reloc_type_lookup().
Packit Service 706eca
   2. asreloc.c : find_reloc_type(). */
Packit Service 706eca
Packit Service 706eca
RELOC_MAP reloc_map_index[RINDEX_16C_MAX] =
Packit Service 706eca
{
Packit Service 706eca
  {R_16C_NUM08,     BFD_RELOC_16C_NUM08},
Packit Service 706eca
  {R_16C_NUM08_C,   BFD_RELOC_16C_NUM08_C},
Packit Service 706eca
  {R_16C_NUM16,     BFD_RELOC_16C_NUM16},
Packit Service 706eca
  {R_16C_NUM16_C,   BFD_RELOC_16C_NUM16_C},
Packit Service 706eca
  {R_16C_NUM32,     BFD_RELOC_16C_NUM32},
Packit Service 706eca
  {R_16C_NUM32_C,   BFD_RELOC_16C_NUM32_C},
Packit Service 706eca
  {R_16C_DISP04,    BFD_RELOC_16C_DISP04},
Packit Service 706eca
  {R_16C_DISP04_C,  BFD_RELOC_16C_DISP04_C},
Packit Service 706eca
  {R_16C_DISP08,    BFD_RELOC_16C_DISP08},
Packit Service 706eca
  {R_16C_DISP08_C,  BFD_RELOC_16C_DISP08_C},
Packit Service 706eca
  {R_16C_DISP16,    BFD_RELOC_16C_DISP16},
Packit Service 706eca
  {R_16C_DISP16_C,  BFD_RELOC_16C_DISP16_C},
Packit Service 706eca
  {R_16C_DISP24,    BFD_RELOC_16C_DISP24},
Packit Service 706eca
  {R_16C_DISP24_C,  BFD_RELOC_16C_DISP24_C},
Packit Service 706eca
  {R_16C_DISP24a,   BFD_RELOC_16C_DISP24a},
Packit Service 706eca
  {R_16C_DISP24a_C, BFD_RELOC_16C_DISP24a_C},
Packit Service 706eca
  {R_16C_REG04,     BFD_RELOC_16C_REG04},
Packit Service 706eca
  {R_16C_REG04_C,   BFD_RELOC_16C_REG04_C},
Packit Service 706eca
  {R_16C_REG04a,    BFD_RELOC_16C_REG04a},
Packit Service 706eca
  {R_16C_REG04a_C,  BFD_RELOC_16C_REG04a_C},
Packit Service 706eca
  {R_16C_REG14,     BFD_RELOC_16C_REG14},
Packit Service 706eca
  {R_16C_REG14_C,   BFD_RELOC_16C_REG14_C},
Packit Service 706eca
  {R_16C_REG16,     BFD_RELOC_16C_REG16},
Packit Service 706eca
  {R_16C_REG16_C,   BFD_RELOC_16C_REG16_C},
Packit Service 706eca
  {R_16C_REG20,     BFD_RELOC_16C_REG20},
Packit Service 706eca
  {R_16C_REG20_C,   BFD_RELOC_16C_REG20_C},
Packit Service 706eca
  {R_16C_ABS20,     BFD_RELOC_16C_ABS20},
Packit Service 706eca
  {R_16C_ABS20_C,   BFD_RELOC_16C_ABS20_C},
Packit Service 706eca
  {R_16C_ABS24,     BFD_RELOC_16C_ABS24},
Packit Service 706eca
  {R_16C_ABS24_C,   BFD_RELOC_16C_ABS24_C},
Packit Service 706eca
  {R_16C_IMM04,     BFD_RELOC_16C_IMM04},
Packit Service 706eca
  {R_16C_IMM04_C,   BFD_RELOC_16C_IMM04_C},
Packit Service 706eca
  {R_16C_IMM16,     BFD_RELOC_16C_IMM16},
Packit Service 706eca
  {R_16C_IMM16_C,   BFD_RELOC_16C_IMM16_C},
Packit Service 706eca
  {R_16C_IMM20,     BFD_RELOC_16C_IMM20},
Packit Service 706eca
  {R_16C_IMM20_C,   BFD_RELOC_16C_IMM20_C},
Packit Service 706eca
  {R_16C_IMM24,     BFD_RELOC_16C_IMM24},
Packit Service 706eca
  {R_16C_IMM24_C,   BFD_RELOC_16C_IMM24_C},
Packit Service 706eca
  {R_16C_IMM32,     BFD_RELOC_16C_IMM32},
Packit Service 706eca
  {R_16C_IMM32_C,   BFD_RELOC_16C_IMM32_C}
Packit Service 706eca
};
Packit Service 706eca
Packit Service 706eca
static reloc_howto_type elf_howto_table[] =
Packit Service 706eca
{
Packit Service 706eca
  /* 00 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM08),
Packit Service 706eca
  /* 01 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM08_C),
Packit Service 706eca
  /* 02 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM16),
Packit Service 706eca
  /* 03 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM16_C),
Packit Service 706eca
  /* 04 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM32),
Packit Service 706eca
  /* 05 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM32_C),
Packit Service 706eca
  /* 06 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP04),
Packit Service 706eca
  /* 07 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP04_C),
Packit Service 706eca
  /* 08 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP08),
Packit Service 706eca
  /* 09 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP08_C),
Packit Service 706eca
  /* 10 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP16),
Packit Service 706eca
  /* 11 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP16_C),
Packit Service 706eca
  /* 12 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP24),
Packit Service 706eca
  /* 13 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP24_C),
Packit Service 706eca
  /* 14 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP24a),
Packit Service 706eca
  /* 15 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP24a_C),
Packit Service 706eca
  /* 16 */ ONLY_NAME_HOWTO (RINDEX_16C_REG04),
Packit Service 706eca
  /* 17 */ ONLY_NAME_HOWTO (RINDEX_16C_REG04_C),
Packit Service 706eca
  /* 18 */ ONLY_NAME_HOWTO (RINDEX_16C_REG04a),
Packit Service 706eca
  /* 19 */ ONLY_NAME_HOWTO (RINDEX_16C_REG04a_C),
Packit Service 706eca
  /* 20 */ ONLY_NAME_HOWTO (RINDEX_16C_REG14),
Packit Service 706eca
  /* 21 */ ONLY_NAME_HOWTO (RINDEX_16C_REG14_C),
Packit Service 706eca
  /* 22 */ ONLY_NAME_HOWTO (RINDEX_16C_REG16),
Packit Service 706eca
  /* 23 */ ONLY_NAME_HOWTO (RINDEX_16C_REG16_C),
Packit Service 706eca
  /* 24 */ ONLY_NAME_HOWTO (RINDEX_16C_REG20),
Packit Service 706eca
  /* 25 */ ONLY_NAME_HOWTO (RINDEX_16C_REG20_C),
Packit Service 706eca
  /* 26 */ ONLY_NAME_HOWTO (RINDEX_16C_ABS20),
Packit Service 706eca
  /* 27 */ ONLY_NAME_HOWTO (RINDEX_16C_ABS20_C),
Packit Service 706eca
  /* 28 */ ONLY_NAME_HOWTO (RINDEX_16C_ABS24),
Packit Service 706eca
  /* 29 */ ONLY_NAME_HOWTO (RINDEX_16C_ABS24_C),
Packit Service 706eca
  /* 30 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM04),
Packit Service 706eca
  /* 31 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM04_C),
Packit Service 706eca
  /* 32 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM16),
Packit Service 706eca
  /* 33 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM16_C),
Packit Service 706eca
  /* 34 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM20),
Packit Service 706eca
  /* 35 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM20_C),
Packit Service 706eca
  /* 36 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM24),
Packit Service 706eca
  /* 37 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM24_C),
Packit Service 706eca
  /* 38 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM32),
Packit Service 706eca
  /* 39 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM32_C)
Packit Service 706eca
};
Packit Service 706eca
Packit Service 706eca
Packit Service 706eca
/* Code to turn a code_type into a howto ptr, uses the above howto table.  */
Packit Service 706eca
Packit Service 706eca
static reloc_howto_type *
Packit Service 706eca
elf_cr16c_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
Packit Service 706eca
			     bfd_reloc_code_real_type code)
Packit Service 706eca
{
Packit Service 706eca
  unsigned int i;
Packit Service 706eca
Packit Service 706eca
  for (i = 0; i < RINDEX_16C_MAX; i++)
Packit Service 706eca
    {
Packit Service 706eca
      if (code == reloc_map_index[i].bfd_reloc_enum)
Packit Service 706eca
	{
Packit Service 706eca
	  /* printf ("CR16C Relocation Type is - %x\n", code); */
Packit Service 706eca
	  return & elf_howto_table[i];
Packit Service 706eca
	}
Packit Service 706eca
    }
Packit Service 706eca
Packit Service 706eca
  /* printf ("This relocation Type is not supported - %x\n", code); */
Packit Service 706eca
  return 0;
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
static reloc_howto_type *
Packit Service 706eca
elf_cr16c_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
Packit Service 706eca
			     const char *r_name)
Packit Service 706eca
{
Packit Service 706eca
  unsigned int i;
Packit Service 706eca
Packit Service 706eca
  for (i = 0; i < sizeof (elf_howto_table) / sizeof (elf_howto_table[0]); i++)
Packit Service 706eca
    if (elf_howto_table[i].name != NULL
Packit Service 706eca
	&& strcasecmp (elf_howto_table[i].name, r_name) == 0)
Packit Service 706eca
      return &elf_howto_table[i];
Packit Service 706eca
Packit Service 706eca
  return NULL;
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
static bfd_boolean
Packit Service 706eca
elf_cr16c_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
Packit Service 706eca
			 arelent *cache_ptr ATTRIBUTE_UNUSED,
Packit Service 706eca
			 Elf_Internal_Rela *dst ATTRIBUTE_UNUSED)
Packit Service 706eca
{
Packit Service 706eca
  return FALSE;
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
static bfd_boolean
Packit Service 706eca
elf_cr16c_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
Packit Service 706eca
			     arelent *cache_ptr,
Packit Service 706eca
			     Elf_Internal_Rela *dst)
Packit Service 706eca
{
Packit Service 706eca
  unsigned int r_type = ELF32_R_TYPE (dst->r_info);
Packit Service 706eca
Packit Service 706eca
  if (r_type >= RINDEX_16C_MAX)
Packit Service 706eca
    {
Packit Service 706eca
      /* xgettext:c-format */
Packit Service 706eca
      _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
Packit Service 706eca
			  abfd, r_type);
Packit Service 706eca
      bfd_set_error (bfd_error_bad_value);
Packit Service 706eca
      return FALSE;
Packit Service 706eca
    }
Packit Service 706eca
  cache_ptr->howto = &elf_howto_table[r_type];
Packit Service 706eca
  return TRUE;
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
/* Perform a relocation as part of a final link.  */
Packit Service 706eca
Packit Service 706eca
static bfd_reloc_status_type
Packit Service 706eca
cr16c_elf_final_link_relocate (reloc_howto_type *howto,
Packit Service 706eca
			       bfd *abfd,
Packit Service 706eca
			       bfd *output_bfd ATTRIBUTE_UNUSED,
Packit Service 706eca
			       asection *input_section,
Packit Service 706eca
			       bfd_byte *data,
Packit Service 706eca
			       bfd_vma octets,
Packit Service 706eca
			       bfd_vma Rvalue,
Packit Service 706eca
			       bfd_vma addend ATTRIBUTE_UNUSED,
Packit Service 706eca
			       struct bfd_link_info *info ATTRIBUTE_UNUSED,
Packit Service 706eca
			       asection *sym_sec ATTRIBUTE_UNUSED,
Packit Service 706eca
			       int is_local ATTRIBUTE_UNUSED)
Packit Service 706eca
{
Packit Service 706eca
  long value;
Packit Service 706eca
  short sword;			/* Extracted from the hole and put back.  */
Packit Service 706eca
  unsigned long format, addr_type, code_factor;
Packit Service 706eca
  unsigned short size;
Packit Service 706eca
  unsigned short r_type;
Packit Service 706eca
Packit Service 706eca
  unsigned long disp20_opcod;
Packit Service 706eca
  char neg = 0;
Packit Service 706eca
  char neg2pos = 0;
Packit Service 706eca
Packit Service 706eca
  long left_val = 0;
Packit Service 706eca
  long plus_factor = 0;		/* To be added to the hole.  */
Packit Service 706eca
Packit Service 706eca
#define MIN_BYTE	((int) 0xFFFFFF80)
Packit Service 706eca
#define MIN_WORD	((int) 0xFFFF8000)
Packit Service 706eca
#define	MAX_UWORD	((unsigned) 0x0000FFFF)
Packit Service 706eca
#define	MAX_UBYTE	((unsigned) 0x000000FF)
Packit Service 706eca
Packit Service 706eca
  r_type = reloc_map_index[howto->type].cr_reloc_type;
Packit Service 706eca
  format = r_type & R_FORMAT;
Packit Service 706eca
  size = r_type & R_SIZESP;
Packit Service 706eca
  addr_type = r_type & R_ADDRTYPE;
Packit Service 706eca
  code_factor = ((addr_type == R_CODE_ADDR) ? 1 : 0);
Packit Service 706eca
Packit Service 706eca
  switch (format)
Packit Service 706eca
    {
Packit Service 706eca
    case R_NUMBER:
Packit Service 706eca
      switch (size)
Packit Service 706eca
	{
Packit Service 706eca
	case R_S_16C_08:	/* One byte.  */
Packit Service 706eca
	  value = bfd_get_8 (abfd, (char *) data + octets);
Packit Service 706eca
	  break;
Packit Service 706eca
	case R_S_16C_16:	/* Two bytes. */
Packit Service 706eca
	  sword = bfd_get_16 (abfd, (bfd_byte *) data + octets);
Packit Service 706eca
	  value = sword;
Packit Service 706eca
	  break;
Packit Service 706eca
	case R_S_16C_32:	/* Four bytes.  */
Packit Service 706eca
	  value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
Packit Service 706eca
	  break;
Packit Service 706eca
	default:
Packit Service 706eca
	  return bfd_reloc_notsupported;
Packit Service 706eca
	}
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case R_16C_DISPL:
Packit Service 706eca
      switch (size)
Packit Service 706eca
	{
Packit Service 706eca
	case R_S_16C_04:    /* word1(4-7).  */
Packit Service 706eca
	  value = bfd_get_8 (abfd, (char *) data + octets);
Packit Service 706eca
	  left_val = value & 0xF;
Packit Service 706eca
	  value = (value & 0xF0) >> 4;
Packit Service 706eca
	  value++;
Packit Service 706eca
	  value <<= 1;
Packit Service 706eca
	  break;
Packit Service 706eca
	case R_S_16C_08:    /* word1(0-3,8-11).  */
Packit Service 706eca
	  sword = bfd_get_16 (abfd, (char *) data + octets);
Packit Service 706eca
	  value = sword & 0x000F;
Packit Service 706eca
	  value |= ((sword & 0x0F00) >> 4);
Packit Service 706eca
	  left_val = sword & 0xF0F0;
Packit Service 706eca
	  value <<= 1;
Packit Service 706eca
	  if (value & 0x100)
Packit Service 706eca
	    value |= 0xFFFFFF00;
Packit Service 706eca
	  break;
Packit Service 706eca
	case R_S_16C_16:    /* word2.  */
Packit Service 706eca
	  sword = bfd_get_16 (abfd, (bfd_byte *) data + octets);
Packit Service 706eca
	  value = sword;
Packit Service 706eca
	  value = ((value & 0xFFFE) >> 1) | ((value & 0x1) << 15);
Packit Service 706eca
	  value <<= 1;
Packit Service 706eca
	  if (value & 0x10000)
Packit Service 706eca
	    value |= 0xFFFF0000;
Packit Service 706eca
	  break;
Packit Service 706eca
	case R_S_16C_24_a:	/* word1(0-7),word2.  */
Packit Service 706eca
	  value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
Packit Service 706eca
	  left_val = value & 0x0000FF00;
Packit Service 706eca
	  value = ((value & 0xFFFE0000) >> 17) |
Packit Service 706eca
	    ((value & 0x00010000) << 7) | ((value & 0x000000FF) << 15);
Packit Service 706eca
	  value <<= 1;
Packit Service 706eca
	  if (value & 0x1000000)
Packit Service 706eca
	    value |= 0xFE000000;
Packit Service 706eca
	  break;
Packit Service 706eca
	case R_S_16C_24:    /* word2(0-3,8-11),word3.  */
Packit Service 706eca
	  value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
Packit Service 706eca
	  left_val = value & 0x0000F0F0;
Packit Service 706eca
	  value = ((value >> 16) & 0x0000FFFF) |
Packit Service 706eca
	    ((value & 0x00000F00) << 8) | ((value & 0x0000000F) << 20);
Packit Service 706eca
Packit Service 706eca
	  value = ((value & 0x00FFFFFE) >> 1) | ((value & 0x00000001) << 23);
Packit Service 706eca
Packit Service 706eca
	  value <<= 1;
Packit Service 706eca
	  if (value & 0x1000000)
Packit Service 706eca
	    value |= 0xFE000000;
Packit Service 706eca
	  break;
Packit Service 706eca
	default:
Packit Service 706eca
	  return bfd_reloc_notsupported;
Packit Service 706eca
	}
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case R_16C_REGREL:
Packit Service 706eca
      switch (size)
Packit Service 706eca
	{
Packit Service 706eca
	case R_S_16C_04:    /* word1(12-15) not scaled.  */
Packit Service 706eca
	  value = bfd_get_8 (abfd, (char *) data + octets);
Packit Service 706eca
	  left_val = value & 0xF0;
Packit Service 706eca
	  value = value & 0xF;
Packit Service 706eca
	  break;
Packit Service 706eca
	case R_S_16C_04_a:	/* word1(12-15) scaled by 2.  */
Packit Service 706eca
	  value = bfd_get_8 (abfd, (char *) data + octets);
Packit Service 706eca
	  left_val = value & 0xF0;
Packit Service 706eca
	  value = value & 0xF;
Packit Service 706eca
	  value <<= 1;
Packit Service 706eca
	  break;
Packit Service 706eca
	case R_S_16C_14:    /* word1(4-5),word2(0-3,8-15).  */
Packit Service 706eca
	  value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
Packit Service 706eca
	  left_val = value & 0x00F0FFCF;
Packit Service 706eca
	  value = ((value & 0xc0000000) >> 24) |
Packit Service 706eca
	    ((value & 0x3F000000) >> 16) |
Packit Service 706eca
	    ((value & 0x000F0000) >> 16) | (value & 0x00000030);
Packit Service 706eca
	  break;
Packit Service 706eca
	case R_S_16C_16:    /* word2.  */
Packit Service 706eca
	  sword = bfd_get_16 (abfd, (bfd_byte *) data + octets);
Packit Service 706eca
	  value = sword;
Packit Service 706eca
	  break;
Packit Service 706eca
	case R_S_16C_20:    /* word2(8-11),word3.  */
Packit Service 706eca
	  value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
Packit Service 706eca
	  left_val = value & 0xF0;
Packit Service 706eca
	  value = (value & 0xF) << 16;
Packit Service 706eca
	  sword = bfd_get_16 (abfd, (bfd_byte *) data + octets + 1);
Packit Service 706eca
	  value = value | (unsigned short) sword;
Packit Service 706eca
	  disp20_opcod = bfd_get_32 (abfd, (bfd_byte *) data + octets - 3);
Packit Service 706eca
	  disp20_opcod |= 0x0FFF0000;
Packit Service 706eca
	  if ((disp20_opcod == 0x4FFF0018) ||	/* loadb -disp20(reg) */
Packit Service 706eca
	      (disp20_opcod == 0x5FFF0018) ||	/* loadb -disp20(rp)  */
Packit Service 706eca
	      (disp20_opcod == 0x8FFF0018) ||	/* loadd -disp20(reg) */
Packit Service 706eca
	      (disp20_opcod == 0x9FFF0018) ||	/* loadd -disp20(rp)  */
Packit Service 706eca
	      (disp20_opcod == 0xCFFF0018) ||	/* loadw -disp20(reg) */
Packit Service 706eca
	      (disp20_opcod == 0xDFFF0018) ||	/* loadw -disp20(rp)  */
Packit Service 706eca
	      (disp20_opcod == 0x4FFF0019) ||	/* storb -disp20(reg) */
Packit Service 706eca
	      (disp20_opcod == 0x5FFF0019) ||	/* storb -disp20(rp)  */
Packit Service 706eca
	      (disp20_opcod == 0x8FFF0019) ||	/* stord -disp20(reg) */
Packit Service 706eca
	      (disp20_opcod == 0x9FFF0019) ||	/* stord -disp20(rp)  */
Packit Service 706eca
	      (disp20_opcod == 0xCFFF0019) ||	/* storw -disp20(reg) */
Packit Service 706eca
	      (disp20_opcod == 0xDFFF0019))
Packit Service 706eca
	    {	/* storw -disp20(rp).  */
Packit Service 706eca
	      neg = 1;
Packit Service 706eca
	      value |= 0xFFF00000;
Packit Service 706eca
	    }
Packit Service 706eca
Packit Service 706eca
	  break;
Packit Service 706eca
	default:
Packit Service 706eca
	  return bfd_reloc_notsupported;
Packit Service 706eca
	}
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case R_16C_ABS:
Packit Service 706eca
      switch (size)
Packit Service 706eca
	{
Packit Service 706eca
	case R_S_16C_20:    /* word1(0-3),word2.  */
Packit Service 706eca
	  value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
Packit Service 706eca
	  left_val = value & 0x0000FFF0;
Packit Service 706eca
	  value = ((value & 0xFFFF0000) >> 16) |
Packit Service 706eca
	    ((value & 0x0000000F) << 16);
Packit Service 706eca
	  break;
Packit Service 706eca
	case R_S_16C_24:   /* word2(0-3,8-11),word3.  */
Packit Service 706eca
	  value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
Packit Service 706eca
	  left_val = value & 0x0000F0F0;
Packit Service 706eca
	  value = ((value & 0xFFFF0000) >> 16) |
Packit Service 706eca
	    ((value & 0x00000F00) << 8) | ((value & 0x0000000F) << 20);
Packit Service 706eca
	  break;
Packit Service 706eca
	default:
Packit Service 706eca
	  return bfd_reloc_notsupported;
Packit Service 706eca
	}
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case R_16C_IMMED:
Packit Service 706eca
      switch (size)
Packit Service 706eca
	{
Packit Service 706eca
	case R_S_16C_04:    /* word1/2(4-7).  */
Packit Service 706eca
	  value = bfd_get_8 (abfd, (char *) data + octets);
Packit Service 706eca
	  left_val = value & 0xF;
Packit Service 706eca
	  value = (value & 0xF0) >> 4;
Packit Service 706eca
	  break;
Packit Service 706eca
	case R_S_16C_16:    /* word2.  */
Packit Service 706eca
	  sword = bfd_get_16 (abfd, (bfd_byte *) data + octets);
Packit Service 706eca
	  value = sword;
Packit Service 706eca
	  break;
Packit Service 706eca
	case R_S_16C_20:    /* word1(0-3),word2.  */
Packit Service 706eca
	  value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
Packit Service 706eca
	  left_val = value & 0x0000FFF0;
Packit Service 706eca
	  value = ((value & 0xFFFF0000) >> 16) |
Packit Service 706eca
	    ((value & 0x0000000F) << 16);
Packit Service 706eca
	  break;
Packit Service 706eca
	case R_S_16C_32:    /* word2, word3.  */
Packit Service 706eca
	  value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
Packit Service 706eca
	  value = ((value & 0x0000FFFF) << 16) |
Packit Service 706eca
	    ((value & 0xFFFF0000) >> 16);
Packit Service 706eca
	  break;
Packit Service 706eca
	default:
Packit Service 706eca
	  return bfd_reloc_notsupported;
Packit Service 706eca
	}
Packit Service 706eca
      break;
Packit Service 706eca
    default:
Packit Service 706eca
      return bfd_reloc_notsupported;
Packit Service 706eca
    }
Packit Service 706eca
Packit Service 706eca
  switch ((r_type & R_RELTO) >> 4)
Packit Service 706eca
    {
Packit Service 706eca
Packit Service 706eca
    case 0:	/* R_ABS.  */
Packit Service 706eca
      plus_factor = Rvalue;
Packit Service 706eca
      break;
Packit Service 706eca
    case 1:	/* R_PCREL.  */
Packit Service 706eca
      plus_factor = Rvalue -
Packit Service 706eca
	(input_section->output_section->vma + input_section->output_offset);
Packit Service 706eca
      break;
Packit Service 706eca
    default:
Packit Service 706eca
      return bfd_reloc_notsupported;
Packit Service 706eca
    }
Packit Service 706eca
Packit Service 706eca
  if (neg)
Packit Service 706eca
    {
Packit Service 706eca
      if (plus_factor >= -value)
Packit Service 706eca
	neg2pos = 1;
Packit Service 706eca
      /* We need to change load/stor with negative
Packit Service 706eca
	 displ opcode to positive disp opcode (CR16C).  */
Packit Service 706eca
    }
Packit Service 706eca
Packit Service 706eca
  value = value + (plus_factor >> code_factor);
Packit Service 706eca
Packit Service 706eca
  switch (format)
Packit Service 706eca
    {
Packit Service 706eca
    case R_NUMBER:
Packit Service 706eca
      switch (size)
Packit Service 706eca
	{
Packit Service 706eca
	case R_S_16C_08:	/* One byte.  */
Packit Service 706eca
	  if (value > (int) MAX_UBYTE || value < MIN_BYTE)
Packit Service 706eca
	    return bfd_reloc_overflow;
Packit Service 706eca
	  value &= 0xFF;
Packit Service 706eca
	  bfd_put_8 (abfd, (bfd_vma) value, (unsigned char *) data + octets);
Packit Service 706eca
	  break;
Packit Service 706eca
Packit Service 706eca
	case R_S_16C_16:	/* Two bytes.  */
Packit Service 706eca
	  if (value > (int) MAX_UWORD || value < MIN_WORD)
Packit Service 706eca
	    return bfd_reloc_overflow;
Packit Service 706eca
	  value &= 0xFFFF;
Packit Service 706eca
	  sword = value;
Packit Service 706eca
	  bfd_put_16 (abfd, (bfd_vma) sword,
Packit Service 706eca
		      (unsigned char *) data + octets);
Packit Service 706eca
	  break;
Packit Service 706eca
Packit Service 706eca
	case R_S_16C_32:	/* Four bytes.  */
Packit Service 706eca
	  value &= 0xFFFFFFFF;
Packit Service 706eca
	  bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
Packit Service 706eca
	  break;
Packit Service 706eca
Packit Service 706eca
	default:
Packit Service 706eca
	  return bfd_reloc_notsupported;
Packit Service 706eca
	}
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case R_16C_DISPL:
Packit Service 706eca
      switch (size)
Packit Service 706eca
	{
Packit Service 706eca
	case R_S_16C_04:	/* word1(4-7).  */
Packit Service 706eca
	  if ((value - 32) > 32 || value < 2)
Packit Service 706eca
	    return bfd_reloc_overflow;
Packit Service 706eca
	  value >>= 1;
Packit Service 706eca
	  value--;
Packit Service 706eca
	  value &= 0xF;
Packit Service 706eca
	  value <<= 4;
Packit Service 706eca
	  value |= left_val;
Packit Service 706eca
	  bfd_put_8 (abfd, (bfd_vma) value, (unsigned char *) data + octets);
Packit Service 706eca
	  break;
Packit Service 706eca
Packit Service 706eca
	case R_S_16C_08:    /* word1(0-3,8-11).  */
Packit Service 706eca
	  if (value > 255 || value < -256 || value == 0x80)
Packit Service 706eca
	    return bfd_reloc_overflow;
Packit Service 706eca
	  value &= 0x1FF;
Packit Service 706eca
	  value >>= 1;
Packit Service 706eca
	  sword = value & 0x000F;
Packit Service 706eca
	  sword |= (value & 0x00F0) << 4;
Packit Service 706eca
	  sword |= left_val;
Packit Service 706eca
	  bfd_put_16 (abfd, (bfd_vma) sword,
Packit Service 706eca
		      (unsigned char *) data + octets);
Packit Service 706eca
	  break;
Packit Service 706eca
Packit Service 706eca
	case R_S_16C_16:    /* word2.  */
Packit Service 706eca
	  if (value > 65535 || value < -65536)
Packit Service 706eca
	    return bfd_reloc_overflow;
Packit Service 706eca
	  value >>= 1;
Packit Service 706eca
	  value &= 0xFFFF;
Packit Service 706eca
	  value = ((value & 0x8000) >> 15) | ((value & 0x7FFF) << 1);
Packit Service 706eca
	  sword = value;
Packit Service 706eca
	  bfd_put_16 (abfd, (bfd_vma) sword,
Packit Service 706eca
		      (unsigned char *) data + octets);
Packit Service 706eca
	  break;
Packit Service 706eca
Packit Service 706eca
	case R_S_16C_24_a:	/* word1(0-7),word2.  */
Packit Service 706eca
	  if (value > 16777215 || value < -16777216)
Packit Service 706eca
	    return bfd_reloc_overflow;
Packit Service 706eca
	  value &= 0x1FFFFFF;
Packit Service 706eca
	  value >>= 1;
Packit Service 706eca
	  value = ((value & 0x00007FFF) << 17) |
Packit Service 706eca
	    ((value & 0x00800000) >> 7) | ((value & 0x007F8000) >> 15);
Packit Service 706eca
	  value |= left_val;
Packit Service 706eca
	  bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
Packit Service 706eca
	  break;
Packit Service 706eca
Packit Service 706eca
	case R_S_16C_24:    /* word2(0-3,8-11),word3.  */
Packit Service 706eca
	  if (value > 16777215 || value < -16777216)
Packit Service 706eca
	    return bfd_reloc_overflow;
Packit Service 706eca
	  value &= 0x1FFFFFF;
Packit Service 706eca
	  value >>= 1;
Packit Service 706eca
Packit Service 706eca
	  value = ((value & 0x007FFFFF) << 1) | ((value & 0x00800000) >> 23);
Packit Service 706eca
Packit Service 706eca
	  value = ((value & 0x0000FFFF) << 16) |
Packit Service 706eca
	    ((value & 0x000F0000) >> 8) | ((value & 0x00F00000) >> 20);
Packit Service 706eca
	  value |= left_val;
Packit Service 706eca
	  bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
Packit Service 706eca
	  break;
Packit Service 706eca
Packit Service 706eca
	default:
Packit Service 706eca
	  return bfd_reloc_notsupported;
Packit Service 706eca
	}
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case R_16C_REGREL:
Packit Service 706eca
      switch (size)
Packit Service 706eca
	{
Packit Service 706eca
	case R_S_16C_04:	/* word1(12-15) not scaled.  */
Packit Service 706eca
	  if (value > 13 || value < 0)
Packit Service 706eca
	    return bfd_reloc_overflow;
Packit Service 706eca
	  value &= 0xF;
Packit Service 706eca
	  value |= left_val;
Packit Service 706eca
	  bfd_put_8 (abfd, (bfd_vma) value, (unsigned char *) data + octets);
Packit Service 706eca
	  break;
Packit Service 706eca
Packit Service 706eca
	case R_S_16C_04_a:	/* word1(12-15) not scaled.  */
Packit Service 706eca
	  if (value > 26 || value < 0)
Packit Service 706eca
	    return bfd_reloc_overflow;
Packit Service 706eca
	  value &= 0x1F;
Packit Service 706eca
	  value >>= 1;
Packit Service 706eca
	  value |= left_val;
Packit Service 706eca
	  bfd_put_8 (abfd, (bfd_vma) value, (unsigned char *) data + octets);
Packit Service 706eca
	  break;
Packit Service 706eca
Packit Service 706eca
	case R_S_16C_14:	/* word1(4-5),word2(0-3,8-15).  */
Packit Service 706eca
	  if (value < 0 || value > 16383)
Packit Service 706eca
	    return bfd_reloc_overflow;
Packit Service 706eca
	  value &= 0x3FFF;
Packit Service 706eca
	  value = ((value & 0x000000c0) << 24) |
Packit Service 706eca
	    ((value & 0x00003F00) << 16) |
Packit Service 706eca
	    ((value & 0x0000000F) << 16) | (value & 0x00000030);
Packit Service 706eca
	  value |= left_val;
Packit Service 706eca
	  bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
Packit Service 706eca
	  break;
Packit Service 706eca
Packit Service 706eca
	case R_S_16C_16:	/* word2.  */
Packit Service 706eca
	  if (value > 65535 || value < 0)
Packit Service 706eca
	    return bfd_reloc_overflow;
Packit Service 706eca
	  value &= 0xFFFF;
Packit Service 706eca
	  sword = value;
Packit Service 706eca
	  bfd_put_16 (abfd, (bfd_vma) sword,
Packit Service 706eca
		      (unsigned char *) data + octets);
Packit Service 706eca
	  break;
Packit Service 706eca
Packit Service 706eca
	case R_S_16C_20:	/* word2(8-11),word3.  */
Packit Service 706eca
	  /* if (value > 1048575 || value < 0) RELOC_ERROR(1); */
Packit Service 706eca
	  value &= 0xFFFFF;
Packit Service 706eca
	  sword = value & 0x0000FFFF;
Packit Service 706eca
	  value = (value & 0x000F0000) >> 16;
Packit Service 706eca
	  value |= left_val;
Packit Service 706eca
	  bfd_put_8 (abfd, (bfd_vma) value, (unsigned char *) data + octets);
Packit Service 706eca
	  bfd_put_16 (abfd, (bfd_vma) sword,
Packit Service 706eca
		      (unsigned char *) data + octets + 1);
Packit Service 706eca
	  if (neg2pos)
Packit Service 706eca
	    {
Packit Service 706eca
	      /* Change load/stor negative displ opcode
Packit Service 706eca
		 to load/stor positive displ opcode.  */
Packit Service 706eca
	      value = bfd_get_8 (abfd, (char *) data + octets - 3);
Packit Service 706eca
	      value &= 0xF7;
Packit Service 706eca
	      value |= 0x2;
Packit Service 706eca
	      bfd_put_8 (abfd, (bfd_vma) value,
Packit Service 706eca
			 (unsigned char *) data + octets - 3);
Packit Service 706eca
	    }
Packit Service 706eca
	  break;
Packit Service 706eca
Packit Service 706eca
	default:
Packit Service 706eca
	  return bfd_reloc_notsupported;
Packit Service 706eca
	}
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case R_16C_ABS:
Packit Service 706eca
      switch (size)
Packit Service 706eca
	{
Packit Service 706eca
	case R_S_16C_20:	/* word1(0-3),word2.  */
Packit Service 706eca
	  if (value > 1048575 || value < 0)
Packit Service 706eca
	    return bfd_reloc_overflow;
Packit Service 706eca
	  value &= 0xFFFFF;
Packit Service 706eca
	  value = ((value & 0x0000FFFF) << 16) |
Packit Service 706eca
	    ((value & 0x000F0000) >> 16);
Packit Service 706eca
	  value |= left_val;
Packit Service 706eca
	  bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
Packit Service 706eca
	  break;
Packit Service 706eca
Packit Service 706eca
	case R_S_16C_24:	/* word2(0-3,8-11),word3.  */
Packit Service 706eca
	  /* if (value > 16777215 || value < 0) RELOC_ERROR(1); */
Packit Service 706eca
	  value &= 0xFFFFFF;
Packit Service 706eca
	  value = ((value & 0x0000FFFF) << 16) |
Packit Service 706eca
	    ((value & 0x000F0000) >> 8) | ((value & 0x00F00000) >> 20);
Packit Service 706eca
	  value |= left_val;
Packit Service 706eca
	  bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
Packit Service 706eca
	  break;
Packit Service 706eca
Packit Service 706eca
	default:
Packit Service 706eca
	  return bfd_reloc_notsupported;
Packit Service 706eca
	}
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case R_16C_IMMED:
Packit Service 706eca
      switch (size)
Packit Service 706eca
	{
Packit Service 706eca
	case R_S_16C_04:	/* word1/2(4-7).  */
Packit Service 706eca
	  if (value > 15 || value < -1)
Packit Service 706eca
	    return bfd_reloc_overflow;
Packit Service 706eca
	  value &= 0xF;
Packit Service 706eca
	  value <<= 4;
Packit Service 706eca
	  value |= left_val;
Packit Service 706eca
	  bfd_put_8 (abfd, (bfd_vma) value, (unsigned char *) data + octets);
Packit Service 706eca
	  break;
Packit Service 706eca
Packit Service 706eca
	case R_S_16C_16:	/* word2.  */
Packit Service 706eca
	  if (value > 32767 || value < -32768)
Packit Service 706eca
	    return bfd_reloc_overflow;
Packit Service 706eca
	  value &= 0xFFFF;
Packit Service 706eca
	  sword = value;
Packit Service 706eca
	  bfd_put_16 (abfd, (bfd_vma) sword,
Packit Service 706eca
		      (unsigned char *) data + octets);
Packit Service 706eca
	  break;
Packit Service 706eca
Packit Service 706eca
	case R_S_16C_20:	/* word1(0-3),word2.  */
Packit Service 706eca
	  if (value > 1048575 || value < 0)
Packit Service 706eca
	    return bfd_reloc_overflow;
Packit Service 706eca
	  value &= 0xFFFFF;
Packit Service 706eca
	  value = ((value & 0x0000FFFF) << 16) |
Packit Service 706eca
	    ((value & 0x000F0000) >> 16);
Packit Service 706eca
	  value |= left_val;
Packit Service 706eca
	  bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
Packit Service 706eca
	  break;
Packit Service 706eca
Packit Service 706eca
	case R_S_16C_32:	/* word2, word3.  */
Packit Service 706eca
	  value &= 0xFFFFFFFF;
Packit Service 706eca
	  value = ((value & 0x0000FFFF) << 16) |
Packit Service 706eca
	    ((value & 0xFFFF0000) >> 16);
Packit Service 706eca
	  bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
Packit Service 706eca
	  break;
Packit Service 706eca
Packit Service 706eca
	default:
Packit Service 706eca
	  return bfd_reloc_notsupported;
Packit Service 706eca
	}
Packit Service 706eca
      break;
Packit Service 706eca
    default:
Packit Service 706eca
      return bfd_reloc_notsupported;
Packit Service 706eca
    }
Packit Service 706eca
Packit Service 706eca
  return bfd_reloc_ok;
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
/* Relocate a CR16C ELF section.  */
Packit Service 706eca
Packit Service 706eca
static bfd_boolean
Packit Service 706eca
elf32_cr16c_relocate_section (bfd *output_bfd,
Packit Service 706eca
			      struct bfd_link_info *info,
Packit Service 706eca
			      bfd *input_bfd,
Packit Service 706eca
			      asection *input_section,
Packit Service 706eca
			      bfd_byte *contents,
Packit Service 706eca
			      Elf_Internal_Rela *relocs,
Packit Service 706eca
			      Elf_Internal_Sym *local_syms,
Packit Service 706eca
			      asection **local_sections)
Packit Service 706eca
{
Packit Service 706eca
  Elf_Internal_Shdr *symtab_hdr;
Packit Service 706eca
  struct elf_link_hash_entry **sym_hashes;
Packit Service 706eca
  Elf_Internal_Rela *rel, *relend;
Packit Service 706eca
Packit Service 706eca
  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
Packit Service 706eca
  sym_hashes = elf_sym_hashes (input_bfd);
Packit Service 706eca
Packit Service 706eca
  rel = relocs;
Packit Service 706eca
  relend = relocs + input_section->reloc_count;
Packit Service 706eca
  for (; rel < relend; rel++)
Packit Service 706eca
    {
Packit Service 706eca
      int r_type;
Packit Service 706eca
      reloc_howto_type *howto;
Packit Service 706eca
      unsigned long r_symndx;
Packit Service 706eca
      Elf_Internal_Sym *sym;
Packit Service 706eca
      asection *sec;
Packit Service 706eca
      struct elf_link_hash_entry *h;
Packit Service 706eca
      bfd_vma relocation;
Packit Service 706eca
      bfd_reloc_status_type r;
Packit Service 706eca
Packit Service 706eca
      r_symndx = ELF32_R_SYM (rel->r_info);
Packit Service 706eca
      r_type = ELF32_R_TYPE (rel->r_info);
Packit Service 706eca
      howto = elf_howto_table + r_type;
Packit Service 706eca
Packit Service 706eca
      h = NULL;
Packit Service 706eca
      sym = NULL;
Packit Service 706eca
      sec = NULL;
Packit Service 706eca
      if (r_symndx < symtab_hdr->sh_info)
Packit Service 706eca
	{
Packit Service 706eca
	  sym = local_syms + r_symndx;
Packit Service 706eca
	  sec = local_sections[r_symndx];
Packit Service 706eca
	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
Packit Service 706eca
	}
Packit Service 706eca
      else
Packit Service 706eca
	{
Packit Service 706eca
	  bfd_boolean unresolved_reloc, warned, ignored;
Packit Service 706eca
Packit Service 706eca
	  RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
Packit Service 706eca
				   r_symndx, symtab_hdr, sym_hashes,
Packit Service 706eca
				   h, sec, relocation,
Packit Service 706eca
				   unresolved_reloc, warned, ignored);
Packit Service 706eca
	}
Packit Service 706eca
Packit Service 706eca
      if (sec != NULL && discarded_section (sec))
Packit Service 706eca
	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
Packit Service 706eca
					 rel, 1, relend, howto, 0, contents);
Packit Service 706eca
Packit Service 706eca
      if (bfd_link_relocatable (info))
Packit Service 706eca
	{
Packit Service 706eca
	  /* This is a relocatable link.  We don't have to change
Packit Service 706eca
	     anything, unless the reloc is against a section symbol,
Packit Service 706eca
	     in which case we have to adjust according to where the
Packit Service 706eca
	     section symbol winds up in the output section.  */
Packit Service 706eca
	  if (sym != NULL && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
Packit Service 706eca
	    rel->r_addend += sec->output_offset;
Packit Service 706eca
	  continue;
Packit Service 706eca
	}
Packit Service 706eca
Packit Service 706eca
      r = cr16c_elf_final_link_relocate (howto, input_bfd, output_bfd,
Packit Service 706eca
					 input_section,
Packit Service 706eca
					 contents, rel->r_offset,
Packit Service 706eca
					 relocation, rel->r_addend,
Packit Service 706eca
					 info, sec, h == NULL);
Packit Service 706eca
Packit Service 706eca
      if (r != bfd_reloc_ok)
Packit Service 706eca
	{
Packit Service 706eca
	  const char *name;
Packit Service 706eca
	  const char *msg = (const char *) 0;
Packit Service 706eca
Packit Service 706eca
	  if (h != NULL)
Packit Service 706eca
	    name = h->root.root.string;
Packit Service 706eca
	  else
Packit Service 706eca
	    {
Packit Service 706eca
	      name = (bfd_elf_string_from_elf_section
Packit Service 706eca
		      (input_bfd, symtab_hdr->sh_link, sym->st_name));
Packit Service 706eca
	      if (name == NULL || *name == '\0')
Packit Service 706eca
		name = bfd_section_name (input_bfd, sec);
Packit Service 706eca
	    }
Packit Service 706eca
Packit Service 706eca
	  switch (r)
Packit Service 706eca
	    {
Packit Service 706eca
	    case bfd_reloc_overflow:
Packit Service 706eca
	      (*info->callbacks->reloc_overflow)
Packit Service 706eca
		(info, (h ? &h->root : NULL), name, howto->name,
Packit Service 706eca
		 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
Packit Service 706eca
	      break;
Packit Service 706eca
Packit Service 706eca
	    case bfd_reloc_undefined:
Packit Service 706eca
	      (*info->callbacks->undefined_symbol)
Packit Service 706eca
		(info, name, input_bfd, input_section, rel->r_offset, TRUE);
Packit Service 706eca
	      break;
Packit Service 706eca
Packit Service 706eca
	    case bfd_reloc_outofrange:
Packit Service 706eca
	      msg = _("internal error: out of range error");
Packit Service 706eca
	      goto common_error;
Packit Service 706eca
Packit Service 706eca
	    case bfd_reloc_notsupported:
Packit Service 706eca
	      msg = _("internal error: unsupported relocation error");
Packit Service 706eca
	      goto common_error;
Packit Service 706eca
Packit Service 706eca
	    case bfd_reloc_dangerous:
Packit Service 706eca
	      msg = _("internal error: dangerous error");
Packit Service 706eca
	      goto common_error;
Packit Service 706eca
Packit Service 706eca
	    default:
Packit Service 706eca
	      msg = _("internal error: unknown error");
Packit Service 706eca
	      /* fall through */
Packit Service 706eca
Packit Service 706eca
	    common_error:
Packit Service 706eca
	      (*info->callbacks->warning) (info, msg, name, input_bfd,
Packit Service 706eca
					   input_section, rel->r_offset);
Packit Service 706eca
	      break;
Packit Service 706eca
	    }
Packit Service 706eca
	}
Packit Service 706eca
    }
Packit Service 706eca
Packit Service 706eca
  return TRUE;
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
/* CR16C ELF uses three common sections:
Packit Service 706eca
   One is for default common symbols (placed in usual common section).
Packit Service 706eca
   Second is for near common symbols (placed in "ncommon" section).
Packit Service 706eca
   Third is for far common symbols (placed in "fcommon" section).
Packit Service 706eca
   The following implementation is based on elf32-mips architecture */
Packit Service 706eca
Packit Service 706eca
static asection  cr16c_elf_fcom_section;
Packit Service 706eca
static asymbol   cr16c_elf_fcom_symbol;
Packit Service 706eca
static asymbol * cr16c_elf_fcom_symbol_ptr;
Packit Service 706eca
static asection  cr16c_elf_ncom_section;
Packit Service 706eca
static asymbol   cr16c_elf_ncom_symbol;
Packit Service 706eca
static asymbol * cr16c_elf_ncom_symbol_ptr;
Packit Service 706eca
Packit Service 706eca
/* Given a BFD section, try to locate the
Packit Service 706eca
   corresponding ELF section index.  */
Packit Service 706eca
Packit Service 706eca
static bfd_boolean
Packit Service 706eca
elf32_cr16c_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED,
Packit Service 706eca
				      asection *sec,
Packit Service 706eca
				      int *retval)
Packit Service 706eca
{
Packit Service 706eca
  if (strcmp (bfd_get_section_name (abfd, sec), ".fcommon") == 0)
Packit Service 706eca
    *retval = SHN_CR16C_FCOMMON;
Packit Service 706eca
  else if (strcmp (bfd_get_section_name (abfd, sec), ".ncommon") == 0)
Packit Service 706eca
    *retval = SHN_CR16C_NCOMMON;
Packit Service 706eca
  else
Packit Service 706eca
    return FALSE;
Packit Service 706eca
Packit Service 706eca
  return TRUE;
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
/* Handle the special CR16C section numbers that a symbol may use.  */
Packit Service 706eca
Packit Service 706eca
static void
Packit Service 706eca
elf32_cr16c_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED,
Packit Service 706eca
			       asymbol *asym)
Packit Service 706eca
{
Packit Service 706eca
  elf_symbol_type *elfsym = (elf_symbol_type *) asym;
Packit Service 706eca
  unsigned int indx;
Packit Service 706eca
Packit Service 706eca
  indx = elfsym->internal_elf_sym.st_shndx;
Packit Service 706eca
Packit Service 706eca
  switch (indx)
Packit Service 706eca
    {
Packit Service 706eca
    case SHN_CR16C_FCOMMON:
Packit Service 706eca
      if (cr16c_elf_fcom_section.name == NULL)
Packit Service 706eca
	{
Packit Service 706eca
	  /* Initialize the far common section.  */
Packit Service 706eca
	  cr16c_elf_fcom_section.name = ".fcommon";
Packit Service 706eca
	  cr16c_elf_fcom_section.flags = SEC_IS_COMMON | SEC_ALLOC;
Packit Service 706eca
	  cr16c_elf_fcom_section.output_section = &cr16c_elf_fcom_section;
Packit Service 706eca
	  cr16c_elf_fcom_section.symbol = &cr16c_elf_fcom_symbol;
Packit Service 706eca
	  cr16c_elf_fcom_section.symbol_ptr_ptr = &cr16c_elf_fcom_symbol_ptr;
Packit Service 706eca
	  cr16c_elf_fcom_symbol.name = ".fcommon";
Packit Service 706eca
	  cr16c_elf_fcom_symbol.flags = BSF_SECTION_SYM;
Packit Service 706eca
	  cr16c_elf_fcom_symbol.section = &cr16c_elf_fcom_section;
Packit Service 706eca
	  cr16c_elf_fcom_symbol_ptr = &cr16c_elf_fcom_symbol;
Packit Service 706eca
	}
Packit Service 706eca
      asym->section = &cr16c_elf_fcom_section;
Packit Service 706eca
      asym->value = elfsym->internal_elf_sym.st_size;
Packit Service 706eca
      break;
Packit Service 706eca
    case SHN_CR16C_NCOMMON:
Packit Service 706eca
      if (cr16c_elf_ncom_section.name == NULL)
Packit Service 706eca
	{
Packit Service 706eca
	  /* Initialize the far common section.  */
Packit Service 706eca
	  cr16c_elf_ncom_section.name = ".ncommon";
Packit Service 706eca
	  cr16c_elf_ncom_section.flags = SEC_IS_COMMON | SEC_ALLOC;
Packit Service 706eca
	  cr16c_elf_ncom_section.output_section = &cr16c_elf_ncom_section;
Packit Service 706eca
	  cr16c_elf_ncom_section.symbol = &cr16c_elf_ncom_symbol;
Packit Service 706eca
	  cr16c_elf_ncom_section.symbol_ptr_ptr = &cr16c_elf_ncom_symbol_ptr;
Packit Service 706eca
	  cr16c_elf_ncom_symbol.name = ".ncommon";
Packit Service 706eca
	  cr16c_elf_ncom_symbol.flags = BSF_SECTION_SYM;
Packit Service 706eca
	  cr16c_elf_ncom_symbol.section = &cr16c_elf_ncom_section;
Packit Service 706eca
	  cr16c_elf_ncom_symbol_ptr = &cr16c_elf_ncom_symbol;
Packit Service 706eca
	}
Packit Service 706eca
      asym->section = &cr16c_elf_ncom_section;
Packit Service 706eca
      asym->value = elfsym->internal_elf_sym.st_size;
Packit Service 706eca
      break;
Packit Service 706eca
    }
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
/* Hook called by the linker routine which adds symbols from an object
Packit Service 706eca
   file.  We must handle the special cr16c section numbers here.  */
Packit Service 706eca
Packit Service 706eca
static bfd_boolean
Packit Service 706eca
elf32_cr16c_add_symbol_hook (bfd *abfd,
Packit Service 706eca
			     struct bfd_link_info *info ATTRIBUTE_UNUSED,
Packit Service 706eca
			     Elf_Internal_Sym *sym,
Packit Service 706eca
			     const char **namep ATTRIBUTE_UNUSED,
Packit Service 706eca
			     flagword *flagsp ATTRIBUTE_UNUSED,
Packit Service 706eca
			     asection **secp,
Packit Service 706eca
			     bfd_vma *valp)
Packit Service 706eca
{
Packit Service 706eca
  unsigned int indx = sym->st_shndx;
Packit Service 706eca
Packit Service 706eca
  switch (indx)
Packit Service 706eca
    {
Packit Service 706eca
    case SHN_CR16C_FCOMMON:
Packit Service 706eca
      *secp = bfd_make_section_old_way (abfd, ".fcommon");
Packit Service 706eca
      (*secp)->flags |= SEC_IS_COMMON;
Packit Service 706eca
      *valp = sym->st_size;
Packit Service 706eca
      break;
Packit Service 706eca
    case SHN_CR16C_NCOMMON:
Packit Service 706eca
      *secp = bfd_make_section_old_way (abfd, ".ncommon");
Packit Service 706eca
      (*secp)->flags |= SEC_IS_COMMON;
Packit Service 706eca
      *valp = sym->st_size;
Packit Service 706eca
      break;
Packit Service 706eca
    }
Packit Service 706eca
Packit Service 706eca
  return TRUE;
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
static int
Packit Service 706eca
elf32_cr16c_link_output_symbol_hook (struct bfd_link_info *info ATTRIBUTE_UNUSED,
Packit Service 706eca
				     const char *name ATTRIBUTE_UNUSED,
Packit Service 706eca
				     Elf_Internal_Sym *sym,
Packit Service 706eca
				     asection *input_sec,
Packit Service 706eca
				     struct elf_link_hash_entry *h ATTRIBUTE_UNUSED)
Packit Service 706eca
{
Packit Service 706eca
  /* If we see a common symbol, which implies a relocatable link, then
Packit Service 706eca
     if a symbol was in a special common section in an input file, mark
Packit Service 706eca
     it as a special common in the output file.  */
Packit Service 706eca
Packit Service 706eca
  if (sym->st_shndx == SHN_COMMON)
Packit Service 706eca
    {
Packit Service 706eca
      if (strcmp (input_sec->name, ".fcommon") == 0)
Packit Service 706eca
	sym->st_shndx = SHN_CR16C_FCOMMON;
Packit Service 706eca
      else if (strcmp (input_sec->name, ".ncommon") == 0)
Packit Service 706eca
	sym->st_shndx = SHN_CR16C_NCOMMON;
Packit Service 706eca
    }
Packit Service 706eca
Packit Service 706eca
  return 1;
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
/* Definitions for setting CR16C target vector.  */
Packit Service 706eca
#define TARGET_LITTLE_SYM		cr16c_elf32_vec
Packit Service 706eca
#define TARGET_LITTLE_NAME		"elf32-cr16c"
Packit Service 706eca
#define ELF_ARCH			bfd_arch_cr16c
Packit Service 706eca
#define ELF_MACHINE_CODE		EM_CR
Packit Service 706eca
#define ELF_MAXPAGESIZE			0x1
Packit Service 706eca
#define elf_symbol_leading_char		'_'
Packit Service 706eca
Packit Service 706eca
#define bfd_elf32_bfd_reloc_type_lookup		elf_cr16c_reloc_type_lookup
Packit Service 706eca
#define bfd_elf32_bfd_reloc_name_lookup	elf_cr16c_reloc_name_lookup
Packit Service 706eca
#define elf_info_to_howto			elf_cr16c_info_to_howto
Packit Service 706eca
#define elf_info_to_howto_rel			elf_cr16c_info_to_howto_rel
Packit Service 706eca
#define elf_backend_relocate_section		elf32_cr16c_relocate_section
Packit Service 706eca
#define elf_backend_symbol_processing		elf32_cr16c_symbol_processing
Packit Service 706eca
#define elf_backend_section_from_bfd_section	elf32_cr16c_section_from_bfd_section
Packit Service 706eca
#define elf_backend_add_symbol_hook		elf32_cr16c_add_symbol_hook
Packit Service 706eca
#define elf_backend_link_output_symbol_hook	elf32_cr16c_link_output_symbol_hook
Packit Service 706eca
Packit Service 706eca
#define elf_backend_can_gc_sections     1
Packit Service 706eca
Packit Service 706eca
#include "elf32-target.h"