Various CR16 fixes

This commit is contained in:
Nick Clifton 2007-10-01 15:55:44 +00:00
parent fef8a650d0
commit 7fac7ff4ae
11 changed files with 751 additions and 496 deletions

View File

@ -1,3 +1,13 @@
2007-10-01 M R Swami Reddy <MR.Swami.Reddy@nsc.com>
* elf32-cr16.c: Fixed DISP8, DISP20 and IMM20 relocations at
final relocation phase.
Added the below relaxations: IMM32 -> IMM20/IM16 -> IMM4.
* reloc.c: Added 3 new relocations: R_CR16_SWITCH8,
R_CR16_SWITCH16, R_CR16_SWITCH32.
* libbfd.h: Regenerate.
* bfd-in2.h: Regenerate.
2007-09-30 Alan Modra <amodra@bigpond.net.au>
* elflink.c: Formatting.

View File

@ -4148,6 +4148,9 @@ This is the 5 bits of a value. */
BFD_RELOC_CR16_DISP20,
BFD_RELOC_CR16_DISP24,
BFD_RELOC_CR16_DISP24a,
BFD_RELOC_CR16_SWITCH8,
BFD_RELOC_CR16_SWITCH16,
BFD_RELOC_CR16_SWITCH32,
/* NS CRX Relocations. */
BFD_RELOC_CRX_REL4,

View File

@ -61,7 +61,10 @@ static const struct cr16_reloc_map cr16_reloc_map[R_CR16_MAX] =
{BFD_RELOC_CR16_DISP8, R_CR16_DISP8},
{BFD_RELOC_CR16_DISP16, R_CR16_DISP16},
{BFD_RELOC_CR16_DISP24, R_CR16_DISP24},
{BFD_RELOC_CR16_DISP24a, R_CR16_DISP24a}
{BFD_RELOC_CR16_DISP24a, R_CR16_DISP24a},
{BFD_RELOC_CR16_SWITCH8, R_CR16_SWITCH8},
{BFD_RELOC_CR16_SWITCH16, R_CR16_SWITCH16},
{BFD_RELOC_CR16_SWITCH32, R_CR16_SWITCH32}
};
static reloc_howto_type cr16_elf_howto_table[] =
@ -429,7 +432,58 @@ static reloc_howto_type cr16_elf_howto_table[] =
FALSE, /* partial_inplace */
0xffffff, /* src_mask */
0xffffff, /* dst_mask */
FALSE) /* pcrel_offset */
FALSE), /* pcrel_offset */
/* An 8 bit switch table entry. This is generated for an expression
such as ``.byte L1 - L2''. The offset holds the difference
between the reloc address and L2. */
HOWTO (R_CR16_SWITCH8, /* type */
0, /* rightshift */
0, /* size (0 = byte, 1 = short, 2 = long) */
8, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_unsigned, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_CR16_SWITCH8", /* name */
FALSE, /* partial_inplace */
0xff, /* src_mask */
0xff, /* dst_mask */
TRUE), /* pcrel_offset */
/* A 16 bit switch table entry. This is generated for an expression
such as ``.word L1 - L2''. The offset holds the difference
between the reloc address and L2. */
HOWTO (R_CR16_SWITCH16, /* type */
0, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_unsigned, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_CR16_SWITCH16", /* name */
FALSE, /* partial_inplace */
0xffff, /* src_mask */
0xffff, /* dst_mask */
TRUE), /* pcrel_offset */
/* A 32 bit switch table entry. This is generated for an expression
such as ``.long L1 - L2''. The offset holds the difference
between the reloc address and L2. */
HOWTO (R_CR16_SWITCH32, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_unsigned, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_CR16_SWITCH32", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
TRUE) /* pcrel_offset */
};
/* Retrieve a howto ptr using a BFD reloc_code. */
@ -478,13 +532,13 @@ elf_cr16_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr,
static bfd_reloc_status_type
cr16_elf_final_link_relocate (reloc_howto_type *howto,
bfd *input_bfd,
bfd *input_bfd,
bfd *output_bfd ATTRIBUTE_UNUSED,
asection *input_section,
bfd_byte *contents,
bfd_byte *contents,
bfd_vma offset,
bfd_vma Rvalue,
bfd_vma addend,
bfd_vma Rvalue,
bfd_vma addend,
struct bfd_link_info *info ATTRIBUTE_UNUSED,
asection *sec ATTRIBUTE_UNUSED,
int is_local ATTRIBUTE_UNUSED)
@ -496,9 +550,12 @@ cr16_elf_final_link_relocate (reloc_howto_type *howto,
switch (r_type)
{
case R_CR16_IMM4:
case R_CR16_IMM20:
case R_CR16_ABS20:
break;
case R_CR16_IMM8:
case R_CR16_IMM16:
case R_CR16_IMM20:
case R_CR16_IMM32:
case R_CR16_IMM32a:
case R_CR16_REGREL4:
@ -507,7 +564,6 @@ cr16_elf_final_link_relocate (reloc_howto_type *howto,
case R_CR16_REGREL14a:
case R_CR16_REGREL16:
case R_CR16_REGREL20:
case R_CR16_ABS20:
case R_CR16_ABS24:
case R_CR16_DISP16:
case R_CR16_DISP24:
@ -521,11 +577,22 @@ cr16_elf_final_link_relocate (reloc_howto_type *howto,
break;
case R_CR16_DISP4:
if (is_local)
Rvalue += -1;
break;
case R_CR16_DISP8:
case R_CR16_DISP24a:
if (is_local)
Rvalue -= -1;
break;
case R_CR16_SWITCH8:
case R_CR16_SWITCH16:
case R_CR16_SWITCH32:
/* We only care about the addend, where the difference between
expressions is kept. */
if (is_local) Rvalue -= -1;
Rvalue = 0;
default:
break;
@ -563,7 +630,7 @@ cr16_elf_final_link_relocate (reloc_howto_type *howto,
{
check |= ((bfd_vma) - 1
& ~((bfd_vma) - 1
>> howto->rightshift));
>> howto->rightshift));
if (((bfd_vma) check & ~reloc_bits)
!= (-(bfd_vma) 1 & ~reloc_bits))
@ -582,14 +649,29 @@ cr16_elf_final_link_relocate (reloc_howto_type *howto,
switch (howto->size)
{
case 0:
if ((r_type == R_CR16_IMM4)
|| (r_type == R_CR16_DISP4)
|| (r_type == R_CR16_DISP8))
if (r_type == R_CR16_DISP8)
{
Rvalue1 = bfd_get_16 (input_bfd, hit_data);
Rvalue = ((Rvalue1 & 0xf000) | ((Rvalue << 4) & 0xf00)
| (Rvalue1 & 0x00f0) | (Rvalue & 0xf));
bfd_put_16 (input_bfd, Rvalue, hit_data);
| (Rvalue1 & 0x00f0) | (Rvalue & 0xf));
bfd_put_16 (input_bfd, Rvalue, hit_data);
}
else if (r_type == R_CR16_IMM4)
{
Rvalue1 = bfd_get_16 (input_bfd, hit_data);
Rvalue = (((Rvalue1 & 0xff) << 8) | ((Rvalue << 4) & 0xf0)
| ((Rvalue1 & 0x0f00) >> 8));
bfd_put_16 (input_bfd, Rvalue, hit_data);
}
else if (r_type == R_CR16_DISP4)
{
Rvalue1 = bfd_get_16 (input_bfd, hit_data);
Rvalue = (Rvalue1 | ((Rvalue & 0xf) << 4));
bfd_put_16 (input_bfd, Rvalue, hit_data);
}
else
{
bfd_put_8 (input_bfd, (unsigned char) Rvalue, hit_data);
}
break;
@ -598,65 +680,49 @@ cr16_elf_final_link_relocate (reloc_howto_type *howto,
{
Rvalue |= (bfd_get_16 (input_bfd, hit_data));
Rvalue = ((Rvalue & 0xfffe) | ((Rvalue >> 16) & 0x1));
bfd_put_16 (input_bfd, Rvalue, hit_data);
}
bfd_put_16 (input_bfd, Rvalue, hit_data);
break;
case 2:
if (r_type == R_CR16_ABS20)
if ((r_type == R_CR16_ABS20) || (r_type == R_CR16_IMM20))
{
Rvalue |= (((bfd_get_16 (input_bfd, hit_data) << 16)
| (bfd_get_16 (input_bfd, hit_data + 2)))
& ~howto->dst_mask);
Rvalue |= (bfd_get_16 (input_bfd, hit_data + 2) << 16);
/* Relocation on INSTRUCTIONS is different : Instructions are
word-addressable, that is, each word itself is arranged according
to little-endian convention, whereas the words are arranged with
respect to one another in BIG ENDIAN fashion.
When there is an immediate value that spans a word boundary,
it is split in a big-endian way with respect to the words. */
bfd_put_16 (input_bfd, (Rvalue) & 0xffff, hit_data);
bfd_put_16 (input_bfd, (Rvalue >> 16)& 0xffff, hit_data + 2);
bfd_put_16 (input_bfd, (bfd_get_16 (input_bfd, hit_data))
| ((Rvalue >> 16) & 0xf), hit_data);
bfd_put_16 (input_bfd, (Rvalue) & 0xffff, hit_data + 2);
}
else if (r_type == R_CR16_ABS24)
else
{
Rvalue = ((((Rvalue >> 20)& 0xf)
| (((Rvalue >> 16) & 0xf) << 8)
| (bfd_get_16 (input_bfd, hit_data)))
| ((Rvalue & 0xffff) << 16));
if (r_type == R_CR16_ABS24)
{
Rvalue = ((((Rvalue >> 20)& 0xf) | (((Rvalue >> 16) & 0xf) << 8)
| (bfd_get_16 (input_bfd, hit_data)))
| ((Rvalue & 0xffff) << 16));
}
if (r_type == R_CR16_DISP24)
{
Rvalue = ((((Rvalue >> 20)& 0xf) | (((Rvalue >>16) & 0xf) << 8)
| (bfd_get_16 (input_bfd, hit_data)))
| (((Rvalue & 0xfffe)
| ((Rvalue >> 24) & 0x1)) << 16));
}
else if ((r_type == R_CR16_IMM32) ||(r_type == R_CR16_IMM32a))
{
Rvalue = (((Rvalue >> 16)& 0xffff)
| (bfd_get_16 (input_bfd, hit_data)))
| ((Rvalue & 0xffff) << 16);
}
else if (r_type == R_CR16_DISP24a)
{
Rvalue = (((Rvalue & 0xfffffe) | (Rvalue >> 23)));
Rvalue = ((Rvalue >> 16) & 0xff) | ((Rvalue & 0xffff) << 16)
| (bfd_get_32 (input_bfd, hit_data));
}
bfd_put_32 (input_bfd, Rvalue, hit_data);
}
else if (r_type == R_CR16_DISP24)
{
Rvalue = ((((Rvalue >> 20)& 0xf) | (((Rvalue >> 16) & 0xf)<<8)
| (bfd_get_16 (input_bfd, hit_data)))
| (((Rvalue & 0xfffE) | ((Rvalue >> 24) & 0x1)) << 16));
bfd_put_32 (input_bfd, Rvalue, hit_data);
}
else if ((r_type == R_CR16_IMM32) || (r_type == R_CR16_IMM32a))
{
Rvalue = (((Rvalue >> 16)& 0xffff)
| (bfd_get_16 (input_bfd, hit_data)))
| ((Rvalue & 0xffff) << 16);
bfd_put_32 (input_bfd, Rvalue, hit_data);
}
else if (r_type == R_CR16_DISP24a)
{
Rvalue = (((Rvalue & 0xfffffe) | (Rvalue >> 23)));
Rvalue = ((Rvalue >> 16) & 0xff) | ((Rvalue & 0xffff) << 16)
| (bfd_get_32 (input_bfd, hit_data));
bfd_put_32 (input_bfd, Rvalue, hit_data);
}
else if ((r_type == R_CR16_NUM32) || (r_type == R_CR16_NUM32a))
{
bfd_put_32 (input_bfd, Rvalue, hit_data);
}
break;
break;
default:
return bfd_reloc_notsupported;
@ -705,7 +771,7 @@ elf32_cr16_relax_delete_bytes (struct bfd_link_info *link_info, bfd *abfd,
for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
/* Get the new reloc address. */
if ((irel->r_offset > addr && irel->r_offset < toaddr))
irel->r_offset -= count;
irel->r_offset -= count;
/* Adjust the local symbols defined in this section. */
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
@ -724,6 +790,12 @@ elf32_cr16_relax_delete_bytes (struct bfd_link_info *link_info, bfd *abfd,
Elf_Internal_Sym *rsym;
bfd_vma addsym, subsym;
/* Skip if not a SWITCH relocation. */
if (ELF32_R_TYPE (irel->r_info) != (int) R_CR16_SWITCH8
&& ELF32_R_TYPE (irel->r_info) != (int) R_CR16_SWITCH16
&& ELF32_R_TYPE (irel->r_info) != (int) R_CR16_SWITCH32)
continue;
r_symndx = ELF32_R_SYM (irel->r_info);
rsym = (Elf_Internal_Sym *) symtab_hdr->contents + r_symndx;
@ -769,10 +841,10 @@ elf32_cr16_relax_delete_bytes (struct bfd_link_info *link_info, bfd *abfd,
/* Loop only over the symbols whom been already checked. */
for (cur_sym_hashes = start_hashes; cur_sym_hashes < sym_hashes;
cur_sym_hashes++)
/* If the current symbol is identical to 'sym_hash', that means
the symbol was already adjusted (or at least checked). */
if (*cur_sym_hashes == sym_hash)
break;
/* If the current symbol is identical to 'sym_hash', that means
the symbol was already adjusted (or at least checked). */
if (*cur_sym_hashes == sym_hash)
break;
/* Don't adjust the symbol again. */
if (cur_sym_hashes < sym_hashes)
@ -794,10 +866,10 @@ elf32_cr16_relax_delete_bytes (struct bfd_link_info *link_info, bfd *abfd,
static bfd_boolean
elf32_cr16_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
bfd *input_bfd, asection *input_section,
bfd_byte *contents, Elf_Internal_Rela *relocs,
Elf_Internal_Sym *local_syms,
asection **local_sections)
bfd *input_bfd, asection *input_section,
bfd_byte *contents, Elf_Internal_Rela *relocs,
Elf_Internal_Sym *local_syms,
asection **local_sections)
{
Elf_Internal_Shdr *symtab_hdr;
struct elf_link_hash_entry **sym_hashes;
@ -953,7 +1025,7 @@ elf32_cr16_get_relocated_section_contents (bfd *output_bfd,
bfd_size_type amt;
internal_relocs = _bfd_elf_link_read_relocs (input_bfd, input_section,
NULL, NULL, FALSE);
NULL, NULL, FALSE);
if (internal_relocs == NULL)
goto error_return;
@ -1024,8 +1096,9 @@ elf32_cr16_get_relocated_section_contents (bfd *output_bfd,
There's quite a few relaxing opportunites available on the CR16:
* bcond:24 -> bcond:16 2 bytes
* bcond:16 -> bcond:8 2 bytes
* arithmetic imm32 -> arithmetic imm16 2 bytes
* bcond:16 -> bcond:8 2 bytes
* arithmetic imm32 -> arithmetic imm20/imm16 2 bytes
* arithmetic imm20/imm16 -> arithmetic imm4 2 bytes
Symbol- and reloc-reading infrastructure copied from elf-m10200.c. */
@ -1055,7 +1128,7 @@ elf32_cr16_relax_section (bfd *abfd, asection *sec,
/* Get a copy of the native relocations. */
internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
link_info->keep_memory);
link_info->keep_memory);
if (internal_relocs == NULL)
goto error_return;
@ -1068,7 +1141,10 @@ elf32_cr16_relax_section (bfd *abfd, asection *sec,
/* If this isn't something that can be relaxed, then ignore
this reloc. */
if (ELF32_R_TYPE (irel->r_info) != (int) R_CR16_DISP16
&& ELF32_R_TYPE (irel->r_info) != (int) R_CR16_DISP24)
&& ELF32_R_TYPE (irel->r_info) != (int) R_CR16_DISP24
&& ELF32_R_TYPE (irel->r_info) != (int) R_CR16_IMM32
&& ELF32_R_TYPE (irel->r_info) != (int) R_CR16_IMM20
&& ELF32_R_TYPE (irel->r_info) != (int) R_CR16_IMM16)
continue;
/* Get the section contents if we haven't done so already. */
@ -1145,7 +1221,7 @@ elf32_cr16_relax_section (bfd *abfd, asection *sec,
the linker is run. */
/* Try to turn a 24 branch/call into a 16bit relative
* branch/call. */
branch/call. */
if (ELF32_R_TYPE (irel->r_info) == (int) R_CR16_DISP24)
{
bfd_vma value = symval;
@ -1168,8 +1244,8 @@ elf32_cr16_relax_section (bfd *abfd, asection *sec,
/* Verify it's a 'bcond' and fix the opcode. */
if ((code & 0xffff) == 0x0010)
{
bfd_put_16 (abfd, 0x1800 | ((0xf & (code >>20))<<4), contents + irel->r_offset);
bfd_put_16 (abfd, value, contents + irel->r_offset+2);
bfd_put_16 (abfd, 0x1800 | ((0xf & (code >> 20)) << 4), contents + irel->r_offset);
bfd_put_16 (abfd, value, contents + irel->r_offset + 2);
}
else
continue;
@ -1194,8 +1270,8 @@ elf32_cr16_relax_section (bfd *abfd, asection *sec,
}
}
/* Try to turn a 16bit pc-relative branch into an
8bit pc-relative branch. */
/* Try to turn a 16-bit pc-relative branch into an
8-bit pc-relative branch. */
if (ELF32_R_TYPE (irel->r_info) == (int) R_CR16_DISP16)
{
bfd_vma value = symval;
@ -1218,8 +1294,8 @@ elf32_cr16_relax_section (bfd *abfd, asection *sec,
/* Verify it's a 'bcond' opcode. */
if ((code & 0xff00) == 0x1800)
{
bfd_put_8 (abfd, 0x1 | ((0xf & (code>>4))<<4), contents + irel->r_offset);
bfd_put_8 (abfd, value, contents + irel->r_offset+2);
bfd_put_8 (abfd, 0x1 | ((0xf & (code >> 4)) << 4), contents + irel->r_offset);
bfd_put_8 (abfd, value, contents + irel->r_offset + 2);
}
else
continue;
@ -1244,65 +1320,63 @@ elf32_cr16_relax_section (bfd *abfd, asection *sec,
}
}
#if 0 // REVISIT: To support IMM relaxation in CR16 target
/* Try to turn a 32bit immediate address into
a 20bit immediate address. */
a 20/16bit immediate address. */
if (ELF32_R_TYPE (irel->r_info) == (int) R_CR16_IMM32)
{
bfd_vma value = symval;
unsigned short is_add_mov = 0;
/* See if the value will fit in 20 bits. */
if ((long) value < 0x7ffff && (long) value > -0x80000)
if ((long) value < 0xfffff && (long) value > 0)
{
unsigned short code;
/* Get the opcode. */
code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
/* Verify it's a 'arithmetic double'. */
if ((code & 0xfff0) != 0x0070)
continue;
/* Verify it's a arithmetic ADDD or MOVD instruction.
For ADDD and MOVD only, convert to IMM32 -> IMM20. */
if (((code & 0xfff0) != 0x0070) || ((code & 0xfff0) != 0x0020))
is_add_mov = 1;
/* Note that we've changed the relocs, section contents, etc. */
elf_section_data (sec)->relocs = internal_relocs;
elf_section_data (sec)->this_hdr.contents = contents;
symtab_hdr->contents = (unsigned char *) isymbuf;
if (is_add_mov)
{
/* Note that we've changed the relocs, section contents,
etc. */
elf_section_data (sec)->relocs = internal_relocs;
elf_section_data (sec)->this_hdr.contents = contents;
symtab_hdr->contents = (unsigned char *) isymbuf;
/* Fix the opcode. */
bfd_put_8 (abfd, (code & 0xff) - 0x10, contents + irel->r_offset);
/* Fix the opcode. */
if ((code & 0xfff0) == 0x0070) /* For movd. */
bfd_put_8 (abfd, 0x05, contents + irel->r_offset + 1);
else /* code == 0x0020 for addd. */
bfd_put_8 (abfd, 0x04, contents + irel->r_offset + 1);
bfd_put_8 (abfd, (code & 0xf) << 4, contents + irel->r_offset);
/* Fix the relocation's type. */
irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
R_CR16_IMM20);
/* Delete two bytes of data. */
if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec,
irel->r_offset + 2, 2))
goto error_return;
/* Fix the relocation's type. */
irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
R_CR16_IMM20);
/* Delete two bytes of data. */
if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec,
irel->r_offset + 2, 2))
goto error_return;
/* That will change things, so, we should relax again.
Note that this is not required, and it may be slow. */
*again = TRUE;
/* That will change things, so, we should relax again.
Note that this is not required, and it may be slow. */
*again = TRUE;
}
}
}
/* Try to turn a 20bit/16bit immediate address into
a 4bit immediate address. */
if ((ELF32_R_TYPE (irel->r_info) == (int) R_CR16_IMM20)
|| (ELF32_R_TYPE (irel->r_info) == (int) R_CR16_IMM16))
{
bfd_vma value = symval;
/* See if the value will fit in 4 bits. */
if ((long) value < 0x7 && (long) value > -0x8)
/* See if the value will fit in 16 bits. */
if ((!is_add_mov) && ((long) value < 0x7fff && (long) value > 0))
{
unsigned short code;
/* Get the opcode. */
code = (unsigned short) bfd_get_8 (abfd, contents + irel->r_offset);
/* Verify it's a 'arithmetic double'. */
if (((code & 0xff) != 0x50) || ((code & 0xff) != 0x45))
continue;
code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
/* Note that we've changed the relocs, section contents, etc. */
elf_section_data (sec)->relocs = internal_relocs;
@ -1310,7 +1384,92 @@ elf32_cr16_relax_section (bfd *abfd, asection *sec,
symtab_hdr->contents = (unsigned char *) isymbuf;
/* Fix the opcode. */
bfd_put_8 (abfd, (code & 0xff) - 0x10, contents + irel->r_offset);
if ((code & 0xf0) == 0x70) /* For movd. */
bfd_put_8 (abfd, 0x54, contents + irel->r_offset + 1);
else if ((code & 0xf0) == 0x20) /* For addd. */
bfd_put_8 (abfd, 0x60, contents + irel->r_offset + 1);
else if ((code & 0xf0) == 0x90) /* For cmpd. */
bfd_put_8 (abfd, 0x56, contents + irel->r_offset + 1);
else
continue;
bfd_put_8 (abfd, 0xb0 | (code & 0xf), contents + irel->r_offset);
/* Fix the relocation's type. */
irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
R_CR16_IMM16);
/* Delete two bytes of data. */
if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec,
irel->r_offset + 2, 2))
goto error_return;
/* That will change things, so, we should relax again.
Note that this is not required, and it may be slow. */
*again = TRUE;
}
}
/* Try to turn a 20/16bit immediate address into
a 4bit immediate address. */
if ((ELF32_R_TYPE (irel->r_info) == (int) R_CR16_IMM20)
|| (ELF32_R_TYPE (irel->r_info) == (int) R_CR16_IMM16))
{
bfd_vma value = symval;
/* See if the value will fit in 4 bits. */
if ((long) value < 0xf && (long) value > 0)
{
unsigned short code;
/* Get the opcode. */
code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
/* Note that we've changed the relocs, section contents, etc. */
elf_section_data (sec)->relocs = internal_relocs;
elf_section_data (sec)->this_hdr.contents = contents;
symtab_hdr->contents = (unsigned char *) isymbuf;
/* Fix the opcode. */
if (((code & 0x0f00) == 0x0400) || ((code & 0x0f00) == 0x0500))
{
if ((code & 0x0f00) == 0x0400) /* For movd imm20. */
bfd_put_8 (abfd, 0x60, contents + irel->r_offset);
else /* For addd imm20. */
bfd_put_8 (abfd, 0x54, contents + irel->r_offset);
bfd_put_8 (abfd, (code & 0xf0) >> 4, contents + irel->r_offset + 1);
}
else
{
if ((code & 0xfff0) == 0x56b0) /* For cmpd imm16. */
bfd_put_8 (abfd, 0x56, contents + irel->r_offset);
else if ((code & 0xfff0) == 0x54b0) /* For movd imm16. */
bfd_put_8 (abfd, 0x54, contents + irel->r_offset);
else if ((code & 0xfff0) == 0x58b0) /* For movb imm16. */
bfd_put_8 (abfd, 0x58, contents + irel->r_offset);
else if ((code & 0xfff0) == 0x5Ab0) /* For movw imm16. */
bfd_put_8 (abfd, 0x5A, contents + irel->r_offset);
else if ((code & 0xfff0) == 0x60b0) /* For addd imm16. */
bfd_put_8 (abfd, 0x60, contents + irel->r_offset);
else if ((code & 0xfff0) == 0x30b0) /* For addb imm16. */
bfd_put_8 (abfd, 0x30, contents + irel->r_offset);
else if ((code & 0xfff0) == 0x2Cb0) /* For addub imm16. */
bfd_put_8 (abfd, 0x2C, contents + irel->r_offset);
else if ((code & 0xfff0) == 0x32b0) /* For adduw imm16. */
bfd_put_8 (abfd, 0x32, contents + irel->r_offset);
else if ((code & 0xfff0) == 0x38b0) /* For subb imm16. */
bfd_put_8 (abfd, 0x38, contents + irel->r_offset);
else if ((code & 0xfff0) == 0x3Ab0) /* For subw imm16. */
bfd_put_8 (abfd, 0x3A, contents + irel->r_offset);
else if ((code & 0xfff0) == 0x50b0) /* For cmpb imm16. */
bfd_put_8 (abfd, 0x50, contents + irel->r_offset);
else if ((code & 0xfff0) == 0x52b0) /* For cmpw imm16. */
bfd_put_8 (abfd, 0x52, contents + irel->r_offset);
else
continue;
bfd_put_8 (abfd, (code & 0xf), contents + irel->r_offset + 1);
}
/* Fix the relocation's type. */
irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
@ -1318,7 +1477,7 @@ elf32_cr16_relax_section (bfd *abfd, asection *sec,
/* Delete two bytes of data. */
if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec,
irel->r_offset + 2, 2))
irel->r_offset + 2, 2))
goto error_return;
/* That will change things, so, we should relax again.
@ -1326,7 +1485,6 @@ elf32_cr16_relax_section (bfd *abfd, asection *sec,
*again = TRUE;
}
}
#endif
}
if (isymbuf != NULL
@ -1335,10 +1493,8 @@ elf32_cr16_relax_section (bfd *abfd, asection *sec,
if (! link_info->keep_memory)
free (isymbuf);
else
{
/* Cache the symbols for elf_link_input_bfd. */
symtab_hdr->contents = (unsigned char *) isymbuf;
}
/* Cache the symbols for elf_link_input_bfd. */
symtab_hdr->contents = (unsigned char *) isymbuf;
}
if (contents != NULL
@ -1347,10 +1503,8 @@ elf32_cr16_relax_section (bfd *abfd, asection *sec,
if (! link_info->keep_memory)
free (contents);
else
{
/* Cache the section contents for elf_link_input_bfd. */
elf_section_data (sec)->this_hdr.contents = contents;
}
/* Cache the section contents for elf_link_input_bfd. */
elf_section_data (sec)->this_hdr.contents = contents;
}
if (internal_relocs != NULL
@ -1375,10 +1529,10 @@ elf32_cr16_relax_section (bfd *abfd, asection *sec,
static asection *
elf32_cr16_gc_mark_hook (asection *sec,
struct bfd_link_info *info ATTRIBUTE_UNUSED,
Elf_Internal_Rela *rel ATTRIBUTE_UNUSED,
struct elf_link_hash_entry *h,
Elf_Internal_Sym *sym)
struct bfd_link_info *info ATTRIBUTE_UNUSED,
Elf_Internal_Rela *rel ATTRIBUTE_UNUSED,
struct elf_link_hash_entry *h,
Elf_Internal_Sym *sym)
{
if (h == NULL)
return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
@ -1401,9 +1555,9 @@ elf32_cr16_gc_mark_hook (asection *sec,
static bfd_boolean
elf32_cr16_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED,
struct bfd_link_info *info ATTRIBUTE_UNUSED,
asection *sec ATTRIBUTE_UNUSED,
const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED)
struct bfd_link_info *info ATTRIBUTE_UNUSED,
asection *sec ATTRIBUTE_UNUSED,
const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED)
{
/* We don't support garbage collection of GOT and PLT relocs yet. */
return TRUE;

View File

@ -1833,6 +1833,9 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
"BFD_RELOC_CR16_DISP20",
"BFD_RELOC_CR16_DISP24",
"BFD_RELOC_CR16_DISP24a",
"BFD_RELOC_CR16_SWITCH8",
"BFD_RELOC_CR16_SWITCH16",
"BFD_RELOC_CR16_SWITCH32",
"BFD_RELOC_CRX_REL4",
"BFD_RELOC_CRX_REL8",
"BFD_RELOC_CRX_REL8_CMP",

View File

@ -4570,6 +4570,12 @@ ENUMX
BFD_RELOC_CR16_DISP24
ENUMX
BFD_RELOC_CR16_DISP24a
ENUMX
BFD_RELOC_CR16_SWITCH8
ENUMX
BFD_RELOC_CR16_SWITCH16
ENUMX
BFD_RELOC_CR16_SWITCH32
ENUMDOC
NS CR16 Relocations.

View File

@ -1,3 +1,8 @@
2007-10-01 M R Swami Reddy <MR.Swami.Reddy@nsc.com>
* config/tc-cr16.c: Replaced 'tabs' with white spaces and
added R_CR16_DISP8 as default reloc type for b<cc> instructions.
2007-09-30 H.J. Lu <hongjiu.lu@intel.com>
PR gas/5080

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,7 @@
2007-10-01 M R Swami Reddy <MR.Swami.Reddy@nsc.com>
* cr16.h: Updated with new relocaction macros.
2007-09-17 H.J. Lu <hongjiu.lu@intel.com>
PR binutils/3281

View File

@ -51,6 +51,9 @@ START_RELOC_NUMBERS(elf_cr16_reloc_type)
RELOC_NUMBER (R_CR16_DISP16, 23)
RELOC_NUMBER (R_CR16_DISP24, 24)
RELOC_NUMBER (R_CR16_DISP24a, 25)
RELOC_NUMBER (R_CR16_SWITCH8, 26)
RELOC_NUMBER (R_CR16_SWITCH16, 27)
RELOC_NUMBER (R_CR16_SWITCH32, 28)
END_RELOC_NUMBERS(R_CR16_MAX)
#endif /* _ELF_CR16_H */

View File

@ -1,3 +1,8 @@
2007-10-01 M R Swami Reddy <MR.Swami.Reddy@nsc.com>
* cr16-opc.c: Updated the branch on condition instructions with
RELAXABLE flag.
2007-09-30 H.J. Lu <hongjiu.lu@intel.com>
* 386-dis.c (prefix_table): Reformat comment.

View File

@ -160,11 +160,11 @@ const inst cr16_instruction[] =
/* Create a conditional branch instruction. */
#define BRANCH_INST(NAME, OPC) \
/* opc4 c4 dispe9 */ \
{NAME, 1, OPC, 28, BRANCH_INS, {{cc,20}, {dispe9,16}}}, \
{NAME, 1, OPC, 28, BRANCH_INS | RELAXABLE, {{cc,20}, {dispe9,16}}},\
/* opc4 c4 disps17 */ \
{NAME, 2, ((OPC<<4)+0x8), 24, BRANCH_INS, {{cc,20}, {disps17,0}}}, \
{NAME, 2, ((OPC<<4)+0x8), 24, BRANCH_INS | RELAXABLE, {{cc,20}, {disps17,0}}},\
/* opc4 c4 disps25 */ \
{NAME, 3, (OPC<<4), 16 , BRANCH_INS, {{cc,4}, {disps25,16}}}
{NAME, 3, (OPC<<4), 16 , BRANCH_INS | RELAXABLE, {{cc,4}, {disps25,16}}}
BRANCH_INST ("b", 0x1),