This is the mail archive of the binutils@sourceware.org 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]

[Patch,AVR]: PR13503: Add expression modifiers/RELOCs for data.


This patch adds new expression modifiers for 1-byte data
to get sub-bytes of byte addresses like in:

.byte lo8(expr)
.byte hi8(expr)
.byte hhi8(expr)
.byte hh8(expr)

The semantics of these new modifiers is the same as the semantics of
respective modifiers that are already allowed in instruction operands.
hh8 is just an alias for hhi8.

These modifiers are needed to support the __memx address space of avr-gcc:

extern const __memx char foo;
const __memx void *pfoo = &foo;

&foo and pfoo are 24-bit values.
Currently, avr-gcc emits an assembler warning for the code above to
hint that the feature is not supported by binutils.


This is my first patch to binutils so I am unsure about its completeness
and correctness; in particular:

* I don't understand the documentation of 'dst_mask' and 'pcrel_offset'
  from ./bfd/reloc.c and if their initialization in the new HOWTOs in
  ./bfd/elf32-avr.c is correct.

* If there is anything missing, like extra processing in
  ./gas/config/tc-avr.c:md_apply_fix() or in other places.
  Or does it work out of the box by HOWTO descriptions?

Up to now, I have no GPL copyright assignment on file.
I requested the paperwork from FSF and hope it will not take
as long as with GCC, which was about 1 1/2 years.

Johann

bfd/
	* reloc.c: Add new ENUM for BFD_RELOC_AVR_8_LO,
	BFD_RELOC_AVR_8_HI, BFD_RELOC_AVR_8_HHI.
	* bfd-in2.h: Regenerate.
	* libbfd.h: Regenrate.
	* elf32-avr.c (elf_avr_howto_table): Add entries for
	R_AVR_8_LO8, R_AVR_8_HI8, R_AVR_8_HHI8.
	(avr_reloc_map): Add RELOC mappings for R_AVR_8_LO8, R_AVR_8_HI8,
	R_AVR_8_HHI8.

gas/
	* config/tc-avr.c (exp_mod_pm): Remove variable.
	(exp_mod_data_t): New typedef.
	(pexp_mod_data, exp_mod_data): New variables.
	(avr_parse_cons_expression): Scan through exp_mod_data[] to find
	data expression modifiers "pm", "gs", "lo8", hi8", "hhi8", "hh8"
	and set pexp_mod_data accordingly to be used in avr_cons_fix_new.
	(avr_cons_fix_new): Handle new data expression modifiers shipped
	in pexp_mod_data.

include/
	* elf/avr.h (RELOC_NUMBERS): Add values for R_AVR_8_LO8,
	R_AVR_8_HI8, R_AVR_8_HHI8.

Index: bfd/bfd-in2.h
===================================================================
RCS file: /cvs/src/src/bfd/bfd-in2.h,v
retrieving revision 1.562
diff -u -p -r1.562 bfd-in2.h
--- bfd/bfd-in2.h	23 Mar 2012 09:27:42 -0000	1.562
+++ bfd/bfd-in2.h	24 Apr 2012 18:04:36 -0000
@@ -4093,6 +4093,18 @@ instructions  */
 instructions  */
   BFD_RELOC_AVR_6_ADIW,
 
+/* This is a 8 bit reloc for the AVR that stores bits 0..7 of a symbol
+in .byte lo8(symbol)  */
+  BFD_RELOC_AVR_8_LO,
+
+/* This is a 8 bit reloc for the AVR that stores bits 8..15 of a symbol
+in .byte hi8(symbol)  */
+  BFD_RELOC_AVR_8_HI,
+
+/* This is a 8 bit reloc for the AVR that stores bits 16..23 of a symbol
+in .byte hhi8(symbol)  */
+  BFD_RELOC_AVR_8_HHI,
+
 /* Renesas RL78 Relocations.  */
   BFD_RELOC_RL78_NEG8,
   BFD_RELOC_RL78_NEG16,
Index: bfd/elf32-avr.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-avr.c,v
retrieving revision 1.53
diff -u -p -r1.53 elf32-avr.c
--- bfd/elf32-avr.c	2 Feb 2012 18:02:10 -0000	1.53
+++ bfd/elf32-avr.c	24 Apr 2012 18:04:36 -0000
@@ -516,6 +516,48 @@ static reloc_howto_type elf_avr_howto_ta
 	 0x000000ff,		/* src_mask */
 	 0x000000ff,		/* dst_mask */
 	 FALSE),		/* pcrel_offset */
+  /* lo8-part to use in  .byte lo8(sym).  */
+  HOWTO (R_AVR_8_LO8,		/* type */
+	 0,			/* rightshift */
+	 0,			/* 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_AVR_8_LO8",		/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffffff,		/* src_mask */
+	 0xffffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+  /* hi8-part to use in  .byte hi8(sym).  */
+  HOWTO (R_AVR_8_HI8,		/* type */
+	 8,			/* rightshift */
+	 0,			/* 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_AVR_8_HI8",		/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffffff,		/* src_mask */
+	 0xffffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+  /* hhi8-part to use in  .byte hhi8(sym).  */
+  HOWTO (R_AVR_8_HHI8,		/* type */
+	 16,			/* rightshift */
+	 0,			/* 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_AVR_8_HHI8",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffffff,		/* src_mask */
+	 0xffffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
 };
 
 /* Map BFD reloc types to AVR ELF reloc types.  */
@@ -554,7 +596,10 @@ static const struct avr_reloc_map avr_re
   { BFD_RELOC_AVR_LDI,              R_AVR_LDI  },
   { BFD_RELOC_AVR_6,                R_AVR_6    },
   { BFD_RELOC_AVR_6_ADIW,           R_AVR_6_ADIW },
-  { BFD_RELOC_8,                    R_AVR_8 }
+  { BFD_RELOC_8,                    R_AVR_8 },
+  { BFD_RELOC_AVR_8_LO,             R_AVR_8_LO8 },
+  { BFD_RELOC_AVR_8_HI,             R_AVR_8_HI8 },
+  { BFD_RELOC_AVR_8_HHI,            R_AVR_8_HHI8 }
 };
 
 /* Meant to be filled one day with the wrap around address for the
Index: bfd/libbfd.h
===================================================================
RCS file: /cvs/src/src/bfd/libbfd.h,v
retrieving revision 1.270
diff -u -p -r1.270 libbfd.h
--- bfd/libbfd.h	7 Mar 2012 17:51:58 -0000	1.270
+++ bfd/libbfd.h	24 Apr 2012 18:04:37 -0000
@@ -1862,6 +1862,9 @@ static const char *const bfd_reloc_code_
   "BFD_RELOC_AVR_LDI",
   "BFD_RELOC_AVR_6",
   "BFD_RELOC_AVR_6_ADIW",
+  "BFD_RELOC_AVR_8_LO",
+  "BFD_RELOC_AVR_8_HI",
+  "BFD_RELOC_AVR_8_HHI",
   "BFD_RELOC_RL78_NEG8",
   "BFD_RELOC_RL78_NEG16",
   "BFD_RELOC_RL78_NEG24",
Index: bfd/reloc.c
===================================================================
RCS file: /cvs/src/src/bfd/reloc.c,v
retrieving revision 1.224
diff -u -p -r1.224 reloc.c
--- bfd/reloc.c	7 Mar 2012 17:51:59 -0000	1.224
+++ bfd/reloc.c	24 Apr 2012 18:04:38 -0000
@@ -4351,6 +4351,21 @@ ENUM
 ENUMDOC
   This is a 6 bit reloc for the AVR that stores offset for adiw/sbiw
   instructions
+ENUM
+  BFD_RELOC_AVR_8_LO
+ENUMDOC
+  This is a 8 bit reloc for the AVR that stores bits 0..7 of a symbol
+  in .byte lo8(symbol)
+ENUM
+  BFD_RELOC_AVR_8_HI
+ENUMDOC
+  This is a 8 bit reloc for the AVR that stores bits 8..15 of a symbol
+  in .byte hi8(symbol)
+ENUM
+  BFD_RELOC_AVR_8_HHI
+ENUMDOC
+  This is a 8 bit reloc for the AVR that stores bits 16..23 of a symbol
+  in .byte hhi8(symbol)
 
 ENUM
   BFD_RELOC_RL78_NEG8
Index: gas/config/tc-avr.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-avr.c,v
retrieving revision 1.79
diff -u -p -r1.79 tc-avr.c
--- gas/config/tc-avr.c	29 Mar 2011 18:16:15 -0000	1.79
+++ gas/config/tc-avr.c	24 Apr 2012 18:04:40 -0000
@@ -1465,40 +1465,75 @@ md_assemble (char *str)
   }
 }
 
-/* Flag to pass `pm' mode between `avr_parse_cons_expression' and
-   `avr_cons_fix_new'.  */
-static int exp_mod_pm = 0;
-
-/* Parse special CONS expression: pm (expression)
-   or alternatively: gs (expression).
-   These are used for addressing program memory.
-   Relocation: BFD_RELOC_AVR_16_PM.  */
+typedef struct
+{
+  /* Name of the expression modifier allowed with .byte, .word, etc.  */
+  const char *name;
+
+  /* Only allowed with n bytes of data.  */
+  int nbytes;
+
+  /* Associated RELOC.  */
+  bfd_reloc_code_real_type reloc;
+
+  /* Part of the error message.  */
+  const char *error;
+} exp_mod_data_t;
+
+static const exp_mod_data_t exp_mod_data[] =
+{
+  /* Default, must be first.  */
+  { "", 0, BFD_RELOC_16, "" },
+  /* Divides by 2 to get word address.  Generate Stub.  */
+  { "gs", 2, BFD_RELOC_AVR_16_PM, "`gs' " },
+  { "pm", 2, BFD_RELOC_AVR_16_PM, "`pm' " },
+  /* The following are used together with avr-gcc's __memx address space
+     in order to initialize a 24-bit pointer variable with a 24-bit address.
+     For address in flash, hhi8 will contain the flash segment if the
+     symbol is located in flash. If the symbol is located in RAM; hhi8
+     will contain 0x80 which matches avr-gcc's notion of how 24-bit RAM/flash
+     addresses linearize address space.  */
+  { "lo8",  1, BFD_RELOC_AVR_8_LO,  "`lo8' "  },
+  { "hi8",  1, BFD_RELOC_AVR_8_HI,  "`hi8' "  },
+  { "hhi8", 1, BFD_RELOC_AVR_8_HHI, "`hhi8' " },
+  { "hh8",  1, BFD_RELOC_AVR_8_HHI, "`hh8' "  },
+  /* End of list.  */
+  { NULL, 0, 0, NULL }
+};
+
+/* Data to pass between `avr_parse_cons_expression' and `avr_cons_fix_new'.  */
+static const exp_mod_data_t *pexp_mod_data = &exp_mod_data[0];
+
+/* Parse special CONS expression: pm (expression) or alternatively
+   gs (expression).  These are used for addressing program memory.  Moreover,
+   define lo8 (expression), hi8 (expression) and hhi8 (expression). */
 
 void
 avr_parse_cons_expression (expressionS *exp, int nbytes)
 {
+  const exp_mod_data_t *pexp = &exp_mod_data[0];
   char *tmp;
 
-  exp_mod_pm = 0;
+  pexp_mod_data = pexp;
 
   tmp = input_line_pointer = skip_space (input_line_pointer);
 
-  if (nbytes == 2)
+  /* The first entry of exp_mod_data[] contains an entry if no
+     expression modifier is present.  Skip it.  */
+
+  for (pexp++; pexp->name; pexp++)
     {
-      char *pm_name1 = "pm";
-      char *pm_name2 = "gs";
-      int len = strlen (pm_name1);
-      /* len must be the same for both pm identifiers.  */
+      int len = strlen (pexp->name);
 
-      if (strncasecmp (input_line_pointer, pm_name1, len) == 0
-          || strncasecmp (input_line_pointer, pm_name2, len) == 0)
+      if (nbytes == pexp->nbytes
+          && strncasecmp (input_line_pointer, pexp->name, len) == 0)
 	{
 	  input_line_pointer = skip_space (input_line_pointer + len);
 
 	  if (*input_line_pointer == '(')
 	    {
 	      input_line_pointer = skip_space (input_line_pointer + 1);
-	      exp_mod_pm = 1;
+	      pexp_mod_data = pexp;
 	      expression (exp);
 
 	      if (*input_line_pointer == ')')
@@ -1506,13 +1541,15 @@ avr_parse_cons_expression (expressionS *
 	      else
 		{
 		  as_bad (_("`)' required"));
-		  exp_mod_pm = 0;
+		  pexp_mod_data = &exp_mod_data[0];
 		}
 
 	      return;
 	    }
 
 	  input_line_pointer = tmp;
+
+          break;
 	}
     }
 
@@ -1525,8 +1562,11 @@ avr_cons_fix_new (fragS *frag,
 		  int nbytes,
 		  expressionS *exp)
 {
-  if (exp_mod_pm == 0)
+  int bad = 0;
+  
+  switch (pexp_mod_data->reloc)
     {
+    default:
       if (nbytes == 1)
 	fix_new_exp (frag, where, nbytes, exp, FALSE, BFD_RELOC_8);
       else if (nbytes == 2)
@@ -1534,16 +1574,24 @@ avr_cons_fix_new (fragS *frag,
       else if (nbytes == 4)
 	fix_new_exp (frag, where, nbytes, exp, FALSE, BFD_RELOC_32);
       else
-	as_bad (_("illegal %srelocation size: %d"), "", nbytes);
-    }
-  else
-    {
-      if (nbytes == 2)
-	fix_new_exp (frag, where, nbytes, exp, FALSE, BFD_RELOC_AVR_16_PM);
+	bad = 1;
+      break;
+
+    case BFD_RELOC_AVR_16_PM:
+    case BFD_RELOC_AVR_8_LO:
+    case BFD_RELOC_AVR_8_HI:
+    case BFD_RELOC_AVR_8_HHI:
+      if (nbytes == pexp_mod_data->nbytes)
+        fix_new_exp (frag, where, nbytes, exp, FALSE, pexp_mod_data->reloc);
       else
-	as_bad (_("illegal %srelocation size: %d"), "`pm' ", nbytes);
-      exp_mod_pm = 0;
+        bad = 1;
+      break;
     }
+
+  if (bad)
+    as_bad (_("illegal %srelocation size: %d"), pexp_mod_data->error, nbytes);
+
+  pexp_mod_data = &exp_mod_data[0];
 }
 
 void
Index: include/elf/avr.h
===================================================================
RCS file: /cvs/src/src/include/elf/avr.h,v
retrieving revision 1.12
diff -u -p -r1.12 avr.h
--- include/elf/avr.h	22 Mar 2011 18:10:44 -0000	1.12
+++ include/elf/avr.h	24 Apr 2012 18:04:45 -0000
@@ -77,6 +77,9 @@ START_RELOC_NUMBERS (elf_avr_reloc_type)
      RELOC_NUMBER (R_AVR_LO8_LDI_GS,	       24)
      RELOC_NUMBER (R_AVR_HI8_LDI_GS,	       25)
      RELOC_NUMBER (R_AVR_8, 		       26)
+     RELOC_NUMBER (R_AVR_8_LO8,                27)
+     RELOC_NUMBER (R_AVR_8_HI8,                28)
+     RELOC_NUMBER (R_AVR_8_HHI8,               29)
 END_RELOC_NUMBERS (R_AVR_max)
 
 #endif /* _ELF_AVR_H */

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