This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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)
 
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]