From c322f1b5236d358a8b592b900f6878fb5ce43bc8 Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Wed, 23 Oct 1996 04:10:41 +0000 Subject: [PATCH] * elf32-v850.c (elf_v850_howto_table): Fix ordering of R_V850_ZDAOFFSET and R_V850_TDAOFFSET. Fix various fields in R_V850_TDAOFFSET. (elf32_v850_bfd_final_link_relocate): Tweak pc-relative relocs to work more like other relocs. Handle R_V850_TDAOFF relocations. v850 tda, sda & zda stuff. --- bfd/ChangeLog | 7 ++++ bfd/elf32-v850.c | 91 ++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 79 insertions(+), 19 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 9a3b3dad26..2b8fdcc827 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,6 +1,13 @@ start-sanitize-v850 Tue Oct 22 19:20:38 1996 Jeffrey A Law (law@cygnus.com) + * elf32-v850.c (elf_v850_howto_table): Fix ordering of + R_V850_ZDAOFFSET and R_V850_TDAOFFSET. Fix various + fields in R_V850_TDAOFFSET. + (elf32_v850_bfd_final_link_relocate): Tweak pc-relative + relocs to work more like other relocs. Handle R_V850_TDAOFF + relocations. + * elf32-v850.c: Include bfdlink.h. (bfd_elf32_v850_reloc): Return an error if we get a reloc we can't handle. diff --git a/bfd/elf32-v850.c b/bfd/elf32-v850.c index 4079da0f27..8e66789e39 100644 --- a/bfd/elf32-v850.c +++ b/bfd/elf32-v850.c @@ -193,7 +193,7 @@ static reloc_howto_type elf_v850_howto_table[] = /* Offset from the short data area pointer. */ HOWTO (R_V850_SDA_OFFSET, /* type */ 0, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ @@ -205,8 +205,8 @@ static reloc_howto_type elf_v850_howto_table[] = 0xffff, /* dst_mask */ false), /* pcrel_offset */ - /* Offset from the tiny data area pointer. */ - HOWTO (R_V850_TDA_OFFSET, /* type */ + /* Offset from the zero data area pointer. */ + HOWTO (R_V850_ZDA_OFFSET, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ @@ -214,25 +214,25 @@ static reloc_howto_type elf_v850_howto_table[] = 0, /* bitpos */ complain_overflow_dont,/* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ - "R_V850_TDA_OFFSET", /* name */ + "R_V850_ZDA_OFFSET", /* name */ true, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ false), /* pcrel_offset */ - /* Offset from the zero data area pointer. */ - HOWTO (R_V850_ZDA_OFFSET, /* type */ + /* Offset from the tiny data area pointer. */ + HOWTO (R_V850_TDA_OFFSET, /* type */ 0, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ - 16, /* bitsize */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 8, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont,/* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ - "R_V850_ZDA_OFFSET", /* name */ + "R_V850_TDA_OFFSET", /* name */ true, /* partial_inplace */ - 0xffff, /* src_mask */ - 0xffff, /* dst_mask */ + 0xff, /* src_mask */ + 0xff, /* dst_mask */ false), /* pcrel_offset */ }; @@ -458,7 +458,7 @@ elf32_v850_bfd_final_link_relocate (howto, input_bfd, output_bfd, return bfd_reloc_dangerous; insn = bfd_get_16 (input_bfd, hit_data); - insn &= 0xf870; + insn &= 0x078f; insn |= ((value & 0x1f0) << 7) | ((value & 0x0e) << 3); bfd_put_16 (input_bfd, insn, hit_data); return bfd_reloc_ok; @@ -475,7 +475,7 @@ elf32_v850_bfd_final_link_relocate (howto, input_bfd, output_bfd, return bfd_reloc_dangerous; insn = bfd_get_32 (input_bfd, hit_data); - insn &= ~0xfffe003f; + insn &= 0x1ffc0; insn |= (((value & 0xfffe) << 16) | ((value & 0x3f0000) >> 16)); bfd_put_32 (input_bfd, insn, hit_data); return bfd_reloc_ok; @@ -562,7 +562,7 @@ elf32_v850_bfd_final_link_relocate (howto, input_bfd, output_bfd, unsigned long ep; struct bfd_link_hash_entry *h; - value += bfd_get_16 (input_bfd, hit_data); + insn = bfd_get_16 (input_bfd, hit_data); /* Get the value of __ep. */ h = bfd_link_hash_lookup (info->hash, "__ep", false, @@ -577,11 +577,64 @@ elf32_v850_bfd_final_link_relocate (howto, input_bfd, output_bfd, value -= ep; - if ((long)value > 0x7fff || (long)value < -0x8000) - return bfd_reloc_overflow; - - bfd_put_16 (input_bfd, value, hit_data); - return bfd_reloc_ok; + /* Overflow computation and operand insertion is complicated + by valid offsets and insertions changing depending on the + instruction being used! */ + if ((insn & 0x0780) == 0x0500) + { + value += ((insn & 0x7f) << 2); + + /* Handle sld.w and sst.w -- 8 bit unsigned offset */ + if ((long) value > 0xff || (long) value < 0) + return bfd_reloc_overflow; + + if ((value % 4) != 0) + return bfd_reloc_dangerous; + + insn &= 0xff81; + insn |= (value >> 1); + bfd_put_16 (input_bfd, insn, hit_data); + return bfd_reloc_ok; + } + + if ((insn & 0x0780) == 0x0400 || (insn & 0x0780) == 0x0480) + { + value += ((insn & 0x7f) << 1); + + /* Handle sld.h and sst.h -- 8 bit unsigned offset */ + if ((long) value > 0xff || (long) value < 0) + return bfd_reloc_overflow; + + if ((value % 2) != 0) + return bfd_reloc_dangerous; + + insn &= 0xff80; + insn |= (value >> 1); + bfd_put_16 (input_bfd, insn, hit_data); + return bfd_reloc_ok; + } + + if ((insn & 0x0780) == 0x0300 || (insn & 0x0780) == 0x0380) + { + value += (insn & 0x7f); + + /* Handle sld.b and sst.b -- 7 bit unsigned offset */ + if ((long) value > 0x7f || (long) value < 0) + return bfd_reloc_overflow; + insn &= 0xff80; + insn |= value; + bfd_put_16 (input_bfd, insn, hit_data); + return bfd_reloc_ok; + } + + /* Guess (XXX) that it's a movea instruction or something + similar. */ + value += insn; + if ((long)value > 0x7fff || (long)value < -0x8000) + return bfd_reloc_overflow; + + bfd_put_16 (input_bfd, value, hit_data); + return bfd_reloc_ok; } case R_V850_NONE: -- 2.34.1