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]

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


Georg-Johann Lay wrote:
> 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?

Hi, this is an updated patch that handles the new RELOCs in
gas/config/tc-avr.c:md_apply_fix()

        case BFD_RELOC_AVR_8_LO:
          *where = 0xff & value;
          break;

        case BFD_RELOC_AVR_8_HI:
          *where = 0xff & (value >> 8);
          break;

        case BFD_RELOC_AVR_8_HHI:
          *where = 0xff & (value >> 16);
          break;

> Up to now, I have no GPL copyright assignment on file.
> I requested the paperwork from FSF

I sent back the papers to the FSF and hope the paperwork it finished soon.

Johann

bfd/
	PR 13503
	* 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/
	PR 13503
	* 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.
	(md_apply_fix): Handle BFD_RELOC_AVR_8_LO, BFD_RELOC_AVR_8_HI,
	BFD_RELOC_AVR_8_HHI.
	
include/
	PR 13503
	* 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.566
diff -u -p -r1.566 bfd-in2.h
--- bfd/bfd-in2.h	26 Apr 2012 13:49:52 -0000	1.566
+++ bfd/bfd-in2.h	26 Apr 2012 17:28:47 -0000
@@ -4089,6 +4089,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.54
diff -u -p -r1.54 elf32-avr.c
--- bfd/elf32-avr.c	24 Apr 2012 05:12:31 -0000	1.54
+++ bfd/elf32-avr.c	26 Apr 2012 17:28:49 -0000
@@ -517,6 +517,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.  */
@@ -555,7 +597,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.272
diff -u -p -r1.272 libbfd.h
--- bfd/libbfd.h	26 Apr 2012 13:49:51 -0000	1.272
+++ bfd/libbfd.h	26 Apr 2012 17:28:51 -0000
@@ -1867,6 +1867,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.226
diff -u -p -r1.226 reloc.c
--- bfd/reloc.c	24 Apr 2012 05:12:39 -0000	1.226
+++ bfd/reloc.c	26 Apr 2012 17:28:54 -0000
@@ -4360,6 +4360,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.80
diff -u -p -r1.80 tc-avr.c
--- gas/config/tc-avr.c	17 Apr 2012 13:59:40 -0000	1.80
+++ gas/config/tc-avr.c	26 Apr 2012 17:28:55 -0000
@@ -1334,7 +1334,19 @@ md_apply_fix (fixS *fixP, valueT * valP,
 	  }
 	  break;
 
-	default:
+        case BFD_RELOC_AVR_8_LO:
+          *where = 0xff & value;
+          break;
+
+        case BFD_RELOC_AVR_8_HI:
+          *where = 0xff & (value >> 8);
+          break;
+
+        case BFD_RELOC_AVR_8_HHI:
+          *where = 0xff & (value >> 16);
+          break;
+
+        default:
 	  as_fatal (_("line %d: unknown relocation type: 0x%x"),
 		    fixP->fx_line, fixP->fx_r_type);
 	  break;
@@ -1465,40 +1477,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 +1553,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 +1574,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 +1586,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	26 Apr 2012 17:28:59 -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]