This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
[RFC] Additional V850 relocations
- From: Momchil Velikov <velco at fadata dot bg>
- To: binutils at sources dot redhat dot com
- Date: 18 Jul 2002 18:30:19 +0300
- Subject: [RFC] Additional V850 relocations
Hi there,
I'm trying to get the V850 assembler/linker to correctly process insns
like these:
movhi hi(foo), r0, r10
ld.bu lo(foo)[r10], r10
For the second insn I need a relocation containing the low 16 bits of
an address, placed non-contiguously. The rellocation should not check
for overflow.
So, I've invented a new reloc R_V850_LO16_SPLIT, and came to the
following patch, which seems to work fine so far.
Is this the right way to go ?
~velco
Index: bfd/elf32-v850.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-v850.c,v
retrieving revision 1.23
diff -u -d -p -r1.23 elf32-v850.c
--- bfd/elf32-v850.c 1 Jul 2002 08:06:44 -0000 1.23
+++ bfd/elf32-v850.c 18 Jul 2002 15:30:10 -0000
@@ -467,6 +467,20 @@ static reloc_howto_type v850_elf_howto_t
0, /* dst_mask */
false), /* pcrel_offset */
+ /* Low 16-bits of an addressr. */
+ HOWTO (R_V850_LO16_SPLIT, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ v850_elf_reloc, /* special_function */
+ "R_V850_LO16_SPLIT", /* name */
+ false, /* partial_inplace */
+ 0xfffe0020, /* src_mask */
+ 0xfffe0020, /* dst_mask */
+ false), /* pcrel_offset */
};
/* Map BFD reloc types to V850 ELF reloc types. */
@@ -506,7 +520,7 @@ static const struct v850_elf_reloc_map v
{ BFD_RELOC_V850_CALLT_16_16_OFFSET, R_V850_CALLT_16_16_OFFSET },
{ BFD_RELOC_VTABLE_INHERIT, R_V850_GNU_VTINHERIT },
{ BFD_RELOC_VTABLE_ENTRY, R_V850_GNU_VTENTRY },
-
+ { BFD_RELOC_V850_LO16_SPLIT, R_V850_LO16_SPLIT },
};
/* Map a bfd relocation into the appropriate howto structure. */
@@ -618,6 +632,7 @@ v850_elf_check_relocs (abfd, info, sec,
case R_V850_HI16_S:
case R_V850_HI16:
case R_V850_LO16:
+ case R_V850_LO16_SPLIT:
case R_V850_32:
case R_V850_16:
case R_V850_8:
@@ -1244,6 +1259,17 @@ v850_elf_perform_relocation (abfd, r_typ
case R_V850_GNU_VTENTRY:
return bfd_reloc_ok;
+ case R_V850_LO16_SPLIT:
+ insn = bfd_get_32 (abfd, address);
+ addend += ((insn & 0xfffe0000) >> 16) + ((insn & 0x20) >> 5);
+
+ insn &= 0x0001ffdf;
+ insn |= (addend & 1) << 5;
+ insn |= (addend &~ (bfd_vma) 1) << 16;
+
+ bfd_put_32 (abfd, (bfd_vma) insn, address);
+ return bfd_reloc_ok;
+
}
bfd_put_16 (abfd, (bfd_vma) insn, address);
@@ -1391,7 +1417,8 @@ v850_elf_final_link_relocate (howto, inp
case R_V850_HI16_S:
case R_V850_HI16:
case R_V850_LO16:
+ case R_V850_LO16_SPLIT:
case R_V850_16:
case R_V850_32:
case R_V850_8:
Index: bfd/reloc.c
===================================================================
RCS file: /cvs/src/src/bfd/reloc.c,v
retrieving revision 1.63
diff -u -d -p -r1.63 reloc.c
--- bfd/reloc.c 17 Jul 2002 14:15:49 -0000 1.63
+++ bfd/reloc.c 18 Jul 2002 15:30:11 -0000
@@ -2781,6 +2781,11 @@ ENUMDOC
This is a 16 bit offset from the zero data area pointer, with the
bits placed non-contigously in the instruction.
ENUM
+ BFD_RELOC_V850_LO16_SPLIT
+ENUMDOC
+ This is a 16 bit reloc containing the lower 16 bits of an address, with the
+ bits placed non-contigously in the instruction.
+ENUM
BFD_RELOC_V850_CALLT_6_7_OFFSET
ENUMDOC
This is a 6 bit offset from the call table base pointer.
cvs server: Diffing bfd/doc
cvs server: Diffing bfd/hosts
cvs server: Diffing bfd/po
cvs server: Diffing binutils
Index: gas/config/tc-v850.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-v850.c,v
retrieving revision 1.21
diff -u -d -p -r1.21 tc-v850.c
--- gas/config/tc-v850.c 8 Jun 2002 07:37:16 -0000 1.21
+++ gas/config/tc-v850.c 18 Jul 2002 15:30:14 -0000
@@ -1440,6 +1440,19 @@ handle_tdaoff (operand)
: BFD_RELOC_V850_TDA_7_7_OFFSET; /* sld.b/sst.b, opreand: D7 */
}
+static bfd_reloc_code_real_type handle_lo
+ PARAMS ((const struct v850_operand *));
+
+static bfd_reloc_code_real_type
+handle_lo (operand)
+ const struct v850_operand *operand;
+{
+ if (operand->bits == -1)
+ return BFD_RELOC_V850_LO16_SPLIT;
+ else
+ return BFD_RELOC_LO16;
+}
+
/* Warning: The code in this function relies upon the definitions
in the v850_operands[] array (defined in opcodes/v850-opc.c)
matching the hard coded values contained herein. */
@@ -1469,7 +1482,7 @@ v850_reloc_prefix (operand)
CHECK_ ("hi0", BFD_RELOC_HI16 );
CHECK_ ("hi", BFD_RELOC_HI16_S );
- CHECK_ ("lo", BFD_RELOC_LO16 );
+ CHECK_ ("lo", handle_lo (operand) );
CHECK_ ("sdaoff", handle_sdaoff (operand));
CHECK_ ("zdaoff", handle_zdaoff (operand));
CHECK_ ("tdaoff", handle_tdaoff (operand));
Index: include/elf/v850.h
===================================================================
RCS file: /cvs/src/src/include/elf/v850.h,v
retrieving revision 1.5
diff -u -d -p -r1.5 v850.h
--- include/elf/v850.h 14 Mar 2001 02:27:44 -0000 1.5
+++ include/elf/v850.h 18 Jul 2002 15:30:15 -0000
@@ -75,6 +75,7 @@ START_RELOC_NUMBERS (v850_reloc_type)
RELOC_NUMBER( R_V850_CALLT_16_16_OFFSET, 22) /* For callt */
RELOC_NUMBER (R_V850_GNU_VTINHERIT, 23)
RELOC_NUMBER (R_V850_GNU_VTENTRY, 24)
+ RELOC_NUMBER( R_V850_LO16_SPLIT, 25) /* For ld.bu, no overflow check */
END_RELOC_NUMBERS (R_V850_max)