Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 2 Dec 2014 19:50:01 +0000 (UTC)
From:      Joerg Wunsch <joerg@FreeBSD.org>
To:        ports-committers@freebsd.org, svn-ports-all@freebsd.org, svn-ports-head@freebsd.org
Subject:   svn commit: r373781 - in head/devel/avr-binutils: . files
Message-ID:  <201412021950.sB2Jo1a6005422@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: joerg
Date: Tue Dec  2 19:50:00 2014
New Revision: 373781
URL: https://svnweb.freebsd.org/changeset/ports/373781
QAT: https://qat.redports.org/buildarchive/r373781/

Log:
  Reorganize the avr-binutils port to use the central binutils one
  (as the various arm*binutils ports are doing, too).
  
  Add a patch to recognize the "avrtiny" architecture MCUs (ATtiny10
  et al.), extracted from the Atmel AVR Toolchain 3.4.5 (they still
  didn't push it upstream, alas).

Added:
  head/devel/avr-binutils/files/
  head/devel/avr-binutils/files/patch-avrtiny   (contents, props changed)
Modified:
  head/devel/avr-binutils/Makefile
  head/devel/avr-binutils/pkg-plist

Modified: head/devel/avr-binutils/Makefile
==============================================================================
--- head/devel/avr-binutils/Makefile	Tue Dec  2 18:53:38 2014	(r373780)
+++ head/devel/avr-binutils/Makefile	Tue Dec  2 19:50:00 2014	(r373781)
@@ -1,33 +1,12 @@
-# Created by: Joerg Wunsch <joerg@FreeBSD.org>
 # $FreeBSD$
 
-PORTNAME=	binutils
-PORTVERSION=	2.24
-CATEGORIES=	devel
-MASTER_SITES=	${MASTER_SITE_SOURCEWARE}
-MASTER_SITE_SUBDIR=	binutils/releases
+PORTREVISION=	1
+COMMENT=	GNU binutils for AVR cross-development
 PKGNAMEPREFIX=	avr-
+BUTARGET=	avr
+PLIST=	${.CURDIR}/pkg-plist
 
-MAINTAINER=	joerg@FreeBSD.org
-COMMENT=	GNU binutils for Atmel AVR 8-bit RISC cross-development
+MASTERDIR=	${.CURDIR}/../binutils
+PATCHDIR=	${.CURDIR}/files
 
-WRKSRC=		${WRKDIR}/binutils-${PORTVERSION}
-
-USES=		gmake tar:bzip2
-CONFIGURE_ARGS=	--target=avr --disable-werror --disable-nls
-GNU_CONFIGURE=	yes
-LDFLAGS+=	-L${LOCALBASE}/lib
-CFLAGS+=	-I${LOCALBASE}/include
-.if (${MACHINE_ARCH} == "amd64")
-MACHINE_ARCH=	x86_64
-.endif
-
-INFO=		as binutils gprof ld bfd standards configure
-INFO_PATH=	${PKGNAMEPREFIX:S/-$//}/info
-
-add-plist-post:
-	@${ECHO_CMD} "@unexec rm %D/${INFO_PATH}/dir 2> /dev/null || true" >> ${TMPPLIST}
-	@${ECHO_CMD} "@unexec rmdir %D/${INFO_PATH} 2> /dev/null || true" >> ${TMPPLIST}
-	@${ECHO_CMD} "@unexec rmdir %D/${PKGNAMEPREFIX:S/-$//} 2> /dev/null || true" >> ${TMPPLIST}
-
-.include <bsd.port.mk>
+.include "${MASTERDIR}/Makefile"

Added: head/devel/avr-binutils/files/patch-avrtiny
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/devel/avr-binutils/files/patch-avrtiny	Tue Dec  2 19:50:00 2014	(r373781)
@@ -0,0 +1,1767 @@
+This patch has been extracted from the changes in Atmel's AVR Toolchain
+3.4.5, compared to stock binutils 2.24.
+
+diff -Nur ./bfd/archures.c ../avr-binutils-2.24/bfd/archures.c
+--- binutils-2.24.orig/bfd/archures.c	2014-12-02 17:48:34.784919055 +0100
++++ bfd/archures.c	2014-12-02 17:31:35.760899508 +0100
+@@ -398,6 +398,7 @@
+ .#define bfd_mach_avr5		5
+ .#define bfd_mach_avr51		51
+ .#define bfd_mach_avr6		6
++.#define bfd_mach_avrtiny   100
+ .#define bfd_mach_avrxmega1 101
+ .#define bfd_mach_avrxmega2 102
+ .#define bfd_mach_avrxmega3 103
+diff -Nur ./bfd/bfd-in2.h ../avr-binutils-2.24/bfd/bfd-in2.h
+--- binutils-2.24.orig/bfd/bfd-in2.h	2014-12-02 17:48:34.784919055 +0100
++++ bfd/bfd-in2.h	2014-12-02 17:31:35.760899508 +0100
+@@ -2153,6 +2153,7 @@
+ #define bfd_mach_avr5          5
+ #define bfd_mach_avr51         51
+ #define bfd_mach_avr6          6
++#define bfd_mach_avrtiny   100
+ #define bfd_mach_avrxmega1 101
+ #define bfd_mach_avrxmega2 102
+ #define bfd_mach_avrxmega3 103
+@@ -4251,6 +4252,20 @@
+ in .byte hlo8(symbol)  */
+   BFD_RELOC_AVR_8_HLO,
+ 
++/* AVR relocations to mark the difference of two local symbols.
++These are only needed to support linker relaxation and can be ignored
++when not relaxing.  The field is set to the value of the difference
++assuming no relaxation.  The relocation encodes the position of the
++second symbol so the linker can determine whether to adjust the field
++value.  */
++  BFD_RELOC_AVR_DIFF8,
++  BFD_RELOC_AVR_DIFF16,
++  BFD_RELOC_AVR_DIFF32,
++
++/* This is a 7 bit reloc for the AVR that stores SRAM address for 16bit
++lds and sts instructions supported only tiny core.  */
++  BFD_RELOC_AVR_LDS_STS_16,
++
+ /* Renesas RL78 Relocations.  */
+   BFD_RELOC_RL78_NEG8,
+   BFD_RELOC_RL78_NEG16,
+diff -Nur ./bfd/cpu-avr.c ../avr-binutils-2.24/bfd/cpu-avr.c
+--- binutils-2.24.orig/bfd/cpu-avr.c	2014-12-02 17:48:34.784919055 +0100
++++ bfd/cpu-avr.c	2014-12-02 17:31:35.764899508 +0100
+@@ -1,6 +1,5 @@
+ /* BFD library support routines for the AVR architecture.
+-   Copyright 1999, 2000, 2002, 2005, 2006, 2007, 2008
+-   Free Software Foundation, Inc.
++   Copyright (C) 1999-2014 Free Software Foundation, Inc.
+    Contributed by Denis Chertykov <denisc@overta.ru>
+ 
+    This file is part of BFD, the Binary File Descriptor library.
+@@ -68,7 +67,6 @@
+     return a;
+   if (a->mach == bfd_mach_avr31 && b->mach == bfd_mach_avr3)
+     return b;
+-
+   if (a->mach == bfd_mach_avr3 && b->mach == bfd_mach_avr35)
+     return a;
+   if (a->mach == bfd_mach_avr35 && b->mach == bfd_mach_avr3)
+@@ -79,7 +77,6 @@
+   if (a->mach == bfd_mach_avr51 && b->mach == bfd_mach_avr5)
+     return b;
+ 
+-
+   return NULL;
+ }
+ 
+@@ -136,25 +133,28 @@
+   /* 3-Byte PC.  */
+   N (22, bfd_mach_avr6, "avr:6", FALSE, & arch_info_struct[10]),
+ 
+-  /* Xmega 1 */
+-  N (24, bfd_mach_avrxmega1, "avr:101", FALSE, & arch_info_struct[11]),
+-
+-  /* Xmega 2 */
+-  N (24, bfd_mach_avrxmega2, "avr:102", FALSE, & arch_info_struct[12]),
+-
+-  /* Xmega 3 */
+-  N (24, bfd_mach_avrxmega3, "avr:103", FALSE, & arch_info_struct[13]),
+-
+-  /* Xmega 4 */
+-  N (24, bfd_mach_avrxmega4, "avr:104", FALSE, & arch_info_struct[14]),
+-
+-  /* Xmega 5 */
+-  N (24, bfd_mach_avrxmega5, "avr:105", FALSE, & arch_info_struct[15]),
++  /* Tiny core (AVR Tiny).  */
++  N (16, bfd_mach_avrtiny, "avr:100", FALSE, & arch_info_struct[11]),
+ 
+-  /* Xmega 6 */
+-  N (24, bfd_mach_avrxmega6, "avr:106", FALSE, & arch_info_struct[16]),
++  /* Xmega 1.  */
++  N (24, bfd_mach_avrxmega1, "avr:101", FALSE, & arch_info_struct[12]),
+ 
+-  /* Xmega 7 */
++  /* Xmega 2.  */
++  N (24, bfd_mach_avrxmega2, "avr:102", FALSE, & arch_info_struct[13]),
++  
++  /* Xmega 3.  */
++  N (24, bfd_mach_avrxmega3, "avr:103", FALSE, & arch_info_struct[14]),
++  
++  /* Xmega 4.  */
++  N (24, bfd_mach_avrxmega4, "avr:104", FALSE, & arch_info_struct[15]),
++  
++  /* Xmega 5.  */
++  N (24, bfd_mach_avrxmega5, "avr:105", FALSE, & arch_info_struct[16]),
++  
++  /* Xmega 6.  */
++  N (24, bfd_mach_avrxmega6, "avr:106", FALSE, & arch_info_struct[17]),
++  
++  /* Xmega 7.  */
+   N (24, bfd_mach_avrxmega7, "avr:107", FALSE, NULL)
+ 
+ };
+diff -Nur ./bfd/doc/archures.texi ../avr-binutils-2.24/bfd/doc/archures.texi
+--- binutils-2.24.orig/bfd/doc/archures.texi	2014-12-02 17:48:34.784919055 +0100
++++ bfd/doc/archures.texi	2014-12-02 17:33:33.048901758 +0100
+@@ -365,6 +365,7 @@
+ #define bfd_mach_avr5          5
+ #define bfd_mach_avr51         51
+ #define bfd_mach_avr6          6
++#define bfd_mach_avrtiny   100
+ #define bfd_mach_avrxmega1 101
+ #define bfd_mach_avrxmega2 102
+ #define bfd_mach_avrxmega3 103
+diff -Nur ./bfd/doc/reloc.texi ../avr-binutils-2.24/bfd/doc/reloc.texi
+--- binutils-2.24.orig/bfd/doc/reloc.texi	2014-12-02 17:48:34.792919056 +0100
++++ bfd/doc/reloc.texi	2014-12-02 17:33:33.100901759 +0100
+@@ -2233,6 +2233,20 @@
+ This is a 8 bit reloc for the AVR that stores bits 16..23 of a symbol
+ in .byte hlo8(symbol)
+ @end deffn
++@deffn {} BFD_RELOC_AVR_DIFF8
++@deffnx {} BFD_RELOC_AVR_DIFF16
++@deffnx {} BFD_RELOC_AVR_DIFF32
++AVR relocations to mark the difference of two local symbols.
++These are only needed to support linker relaxation and can be ignored
++when not relaxing.  The field is set to the value of the difference
++assuming no relaxation.  The relocation encodes the position of the
++second symbol so the linker can determine whether to adjust the field
++value.
++@end deffn
++@deffn {} BFD_RELOC_AVR_LDS_STS_16
++This is a 7 bit reloc for the AVR that stores SRAM address for 16bit
++lds and sts instructions supported only tiny core.
++@end deffn
+ @deffn {} BFD_RELOC_RL78_NEG8
+ @deffnx {} BFD_RELOC_RL78_NEG16
+ @deffnx {} BFD_RELOC_RL78_NEG24
+diff -Nur ./bfd/elf32-avr.c ../avr-binutils-2.24/bfd/elf32-avr.c
+--- binutils-2.24.orig/bfd/elf32-avr.c	2014-12-02 17:48:34.792919056 +0100
++++ bfd/elf32-avr.c	2014-12-02 17:31:35.764899508 +0100
+@@ -1,5 +1,5 @@
+ /* AVR-specific support for 32-bit ELF
+-   Copyright 1999-2013 Free Software Foundation, Inc.
++   Copyright (C) 1999-2014 Free Software Foundation, Inc.
+    Contributed by Denis Chertykov <denisc@overta.ru>
+ 
+    This file is part of BFD, the Binary File Descriptor library.
+@@ -32,6 +32,10 @@
+ /* Enable debugging printout at stdout with this variable.  */
+ static bfd_boolean debug_stubs = FALSE;
+ 
++static bfd_reloc_status_type
++bfd_elf_avr_diff_reloc (bfd *, arelent *, asymbol *, void *,
++			asection *, bfd *, char **);
++
+ /* Hash table initialization and handling.  Code is taken from the hppa port
+    and adapted to the needs of AVR.  */
+ 
+@@ -557,6 +561,59 @@
+ 	 0xffffff,		/* src_mask */
+ 	 0xffffff,		/* dst_mask */
+ 	 FALSE),		/* pcrel_offset */
++  HOWTO (R_AVR_DIFF8,		/* type */
++	 0,             	/* rightshift */
++	 0, 			/* size (0 = byte, 1 = short, 2 = long) */
++	 8, 			/* bitsize */
++	 FALSE,         	/* pc_relative */
++	 0,             	/* bitpos */
++	 complain_overflow_bitfield, /* complain_on_overflow */
++	 bfd_elf_avr_diff_reloc, /* special_function */
++	 "R_AVR_DIFF8",     	/* name */
++	 FALSE,         	/* partial_inplace */
++	 0,             	/* src_mask */
++	 0xff,          	/* dst_mask */
++	 FALSE),        	/* pcrel_offset */
++  HOWTO (R_AVR_DIFF16,  	/* type */
++	 0,             	/* rightshift */
++	 1,			/* size (0 = byte, 1 = short, 2 = long) */
++	 16,			/* bitsize */
++	 FALSE,         	/* pc_relative */
++	 0,             	/* bitpos */
++	 complain_overflow_bitfield, /* complain_on_overflow */
++	 bfd_elf_avr_diff_reloc,/* special_function */
++	 "R_AVR_DIFF16",     	/* name */
++	 FALSE,         	/* partial_inplace */
++	 0,             	/* src_mask */
++	 0xffff,        	/* dst_mask */
++	 FALSE),        	/* pcrel_offset */
++  HOWTO (R_AVR_DIFF32,  	/* type */
++	 0,             	/* rightshift */
++	 2,         		/* size (0 = byte, 1 = short, 2 = long) */
++	 32,        		/* bitsize */
++	 FALSE,         	/* pc_relative */
++	 0,             	/* bitpos */
++	 complain_overflow_bitfield, /* complain_on_overflow */
++	 bfd_elf_avr_diff_reloc,/* special_function */
++	 "R_AVR_DIFF32",     	/* name */
++	 FALSE,         	/* partial_inplace */
++	 0,             	/* src_mask */
++	 0xffffffff,    	/* dst_mask */
++	 FALSE),        	/* pcrel_offset */
++  /* 7 bit immediate for LDS/STS in Tiny core.  */
++  HOWTO (R_AVR_LDS_STS_16,  /* type */
++	 0,                     /* rightshift */
++	 1,                     /* size (0 = byte, 1 = short, 2 = long) */
++	 7,                     /* bitsize */
++	 FALSE,                 /* pc_relative */
++	 0,                     /* bitpos */
++	 complain_overflow_dont,/* complain_on_overflow */
++	 bfd_elf_generic_reloc, /* special_function */
++	 "R_AVR_LDS_STS_16",    /* name */
++	 FALSE,                 /* partial_inplace */
++	 0xffff,                /* src_mask */
++	 0xffff,                /* dst_mask */
++	 FALSE)		/* pcrel_offset */
+ };
+ 
+ /* Map BFD reloc types to AVR ELF reloc types.  */
+@@ -598,7 +655,11 @@
+   { 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_HLO,            R_AVR_8_HLO8 }
++  { BFD_RELOC_AVR_8_HLO,            R_AVR_8_HLO8 },
++  { BFD_RELOC_AVR_DIFF8,            R_AVR_DIFF8 },
++  { BFD_RELOC_AVR_DIFF16,           R_AVR_DIFF16 },
++  { BFD_RELOC_AVR_DIFF32,           R_AVR_DIFF32 },
++  { BFD_RELOC_AVR_LDS_STS_16,       R_AVR_LDS_STS_16}
+ };
+ 
+ /* Meant to be filled one day with the wrap around address for the
+@@ -797,6 +858,22 @@
+   return 0x020000;
+ }
+ 
++/* Perform a diff relocation. Nothing to do, as the difference value is already
++   written into the section's contents. */
++
++static bfd_reloc_status_type
++bfd_elf_avr_diff_reloc (bfd *abfd ATTRIBUTE_UNUSED,
++		      arelent *reloc_entry ATTRIBUTE_UNUSED,
++              asymbol *symbol ATTRIBUTE_UNUSED,
++              void *data ATTRIBUTE_UNUSED,
++              asection *input_section ATTRIBUTE_UNUSED,
++              bfd *output_bfd ATTRIBUTE_UNUSED,
++              char **error_message ATTRIBUTE_UNUSED)
++{
++  return bfd_reloc_ok;
++}
++
++
+ /* Perform a single relocation.  By default we use the standard BFD
+    routines, but a few relocs, we have to do them ourselves.  */
+ 
+@@ -1149,6 +1226,24 @@
+       bfd_put_16 (input_bfd, (bfd_vma) srel &0x00ffff, contents);
+       break;
+ 
++    case R_AVR_DIFF8:
++    case R_AVR_DIFF16:
++    case R_AVR_DIFF32:
++      /* Nothing to do here, as contents already contains the diff value. */
++      r = bfd_reloc_ok;
++      break;
++
++    case R_AVR_LDS_STS_16:
++      contents += rel->r_offset;
++      srel = (bfd_signed_vma) relocation + rel->r_addend;
++      if ((srel & 0xFFFF) < 0x40 || (srel & 0xFFFF) > 0xbf)
++        return bfd_reloc_outofrange;
++      srel = srel & 0x7f;
++      x = bfd_get_16 (input_bfd, contents);
++      x |= (srel & 0x0f) | ((srel & 0x30) << 5) | ((srel & 0x40) << 2);
++      bfd_put_16 (input_bfd, x, contents);
++      break;
++
+     default:
+       r = _bfd_final_link_relocate (howto, input_bfd, input_section,
+ 				    contents, rel->r_offset,
+@@ -1361,6 +1456,10 @@
+     case bfd_mach_avrxmega7:
+       val = E_AVR_MACH_XMEGA7;
+       break;
++
++   case bfd_mach_avrtiny:
++      val = E_AVR_MACH_AVRTINY;
++      break;
+     }
+ 
+   elf_elfheader (abfd)->e_machine = EM_AVR;
+@@ -1451,12 +1550,112 @@
+ 	case E_AVR_MACH_XMEGA7:
+ 	  e_set = bfd_mach_avrxmega7;
+ 	  break;
++
++    case E_AVR_MACH_AVRTINY:
++      e_set = bfd_mach_avrtiny;
++      break;
+ 	}
+     }
+   return bfd_default_set_arch_mach (abfd, bfd_arch_avr,
+ 				    e_set);
+ }
+ 
++/* Returns whether the relocation type passed is a diff reloc. */
++
++static bfd_boolean
++elf32_avr_is_diff_reloc (Elf_Internal_Rela *irel)
++{
++  return (ELF32_R_TYPE (irel->r_info) == R_AVR_DIFF8
++          ||ELF32_R_TYPE (irel->r_info) == R_AVR_DIFF16
++          || ELF32_R_TYPE (irel->r_info) == R_AVR_DIFF32);
++}
++
++/* Reduce the diff value written in the section by count if the shrinked
++   insn address happens to fall between the two symbols for which this
++   diff reloc was emitted.  */
++
++static void
++elf32_avr_adjust_diff_reloc_value (bfd *abfd,
++                                   struct bfd_section *isec,
++                                   Elf_Internal_Rela *irel,
++                                   bfd_vma symval,
++                                   bfd_vma shrinked_insn_address,
++                                   int count)
++{
++  unsigned char *isec_contents = elf_section_data (isec)->this_hdr.contents;
++  if (isec_contents == NULL)
++  {
++    if (! bfd_malloc_and_get_section (abfd, isec, &isec_contents))
++      return;
++  }
++
++  isec_contents += irel->r_offset;
++
++  /* Read value written in object file. */
++ bfd_vma x = 0;
++  switch (ELF32_R_TYPE (irel->r_info))
++  {
++  case R_AVR_DIFF8:
++    {
++      x = *isec_contents;
++      break;
++    }
++  case R_AVR_DIFF16:
++    {
++      x = bfd_get_16 (abfd, isec_contents);
++      break;
++    }
++  case R_AVR_DIFF32:
++    {
++      x = bfd_get_32 (abfd, isec_contents);
++      break;
++    }
++  default:
++    {
++      BFD_FAIL();
++    }
++  }
++
++  /* For a diff reloc sym1 - sym2 the diff at assembly time (x) is written
++     into the object file. sym2's value is represented as 
++     <start_of_section> + addend. Check if the shrinked insn falls between 
++     sym1 and sym2. */
++
++  bfd_vma end_address = symval + irel->r_addend;
++  bfd_vma start_address = end_address - x;
++
++  /* Reduce the diff value by count bytes and write it back into section
++    contents. */
++
++  if (shrinked_insn_address >= start_address
++      && shrinked_insn_address <= end_address)
++  {
++    switch (ELF32_R_TYPE (irel->r_info))
++    {
++    case R_AVR_DIFF8:
++      {
++        *isec_contents = (x - count);
++        break;
++      }
++    case R_AVR_DIFF16:
++      {
++        bfd_put_16 (abfd, (x - count) & 0xFFFF, isec_contents);
++        break;
++      }
++    case R_AVR_DIFF32:
++      {
++        bfd_put_32 (abfd, (x - count) & 0xFFFFFFFF, isec_contents);
++        break;
++      }
++    default:
++      {
++        BFD_FAIL();
++      }
++    }
++
++    elf_section_data (isec)->this_hdr.contents = isec_contents - irel->r_offset;
++  }
++}
+ 
+ /* Delete some bytes from a section while changing the size of an instruction.
+    The parameter "addr" denotes the section-relative offset pointing just
+@@ -1595,6 +1794,14 @@
+                    if (symval <= shrinked_insn_address
+                        && (symval + irel->r_addend) > shrinked_insn_address)
+                      {
++                       if (elf32_avr_is_diff_reloc (irel))
++                         {
++                           elf32_avr_adjust_diff_reloc_value (abfd, isec, irel,
++                                                         symval, 
++                                                         shrinked_insn_address,
++                                                        count);
++                         }
++
+                        irel->r_addend -= count;
+ 
+                        if (debug_relax)
+@@ -1765,8 +1972,8 @@
+       bfd_vma symval;
+ 
+       if (   ELF32_R_TYPE (irel->r_info) != R_AVR_13_PCREL
+-	     && ELF32_R_TYPE (irel->r_info) != R_AVR_7_PCREL
+-	     && ELF32_R_TYPE (irel->r_info) != R_AVR_CALL)
++	  && ELF32_R_TYPE (irel->r_info) != R_AVR_7_PCREL
++	  && ELF32_R_TYPE (irel->r_info) != R_AVR_CALL)
+         continue;
+ 
+       /* Get the section contents if we haven't done so already.  */
+diff -Nur ./bfd/libbfd.h ../avr-binutils-2.24/bfd/libbfd.h
+--- binutils-2.24.orig/bfd/libbfd.h	2014-12-02 17:48:34.792919056 +0100
++++ bfd/libbfd.h	2014-12-02 17:31:35.764899508 +0100
+@@ -1947,6 +1947,10 @@
+   "BFD_RELOC_AVR_8_LO",
+   "BFD_RELOC_AVR_8_HI",
+   "BFD_RELOC_AVR_8_HLO",
++  "BFD_RELOC_AVR_DIFF8",
++  "BFD_RELOC_AVR_DIFF16",
++  "BFD_RELOC_AVR_DIFF32",
++  "BFD_RELOC_AVR_LDS_STS_16",
+   "BFD_RELOC_RL78_NEG8",
+   "BFD_RELOC_RL78_NEG16",
+   "BFD_RELOC_RL78_NEG24",
+diff -Nur ./bfd/reloc.c ../avr-binutils-2.24/bfd/reloc.c
+--- binutils-2.24.orig/bfd/reloc.c	2014-12-02 17:48:34.792919056 +0100
++++ bfd/reloc.c	2014-12-02 17:31:35.764899508 +0100
+@@ -4510,7 +4510,24 @@
+ ENUMDOC
+   This is a 8 bit reloc for the AVR that stores bits 16..23 of a symbol
+   in .byte hlo8(symbol)
+-
++ENUM
++  BFD_RELOC_AVR_DIFF8
++ENUMX
++  BFD_RELOC_AVR_DIFF16
++ENUMX
++  BFD_RELOC_AVR_DIFF32
++ENUMDOC
++  AVR relocations to mark the difference of two local symbols.
++  These are only needed to support linker relaxation and can be ignored
++  when not relaxing.  The field is set to the value of the difference
++  assuming no relaxation.  The relocation encodes the position of the
++  second symbol so the linker can determine whether to adjust the field
++  value.
++ENUM
++  BFD_RELOC_AVR_LDS_STS_16
++ENUMDOC
++  This is a 7 bit reloc for the AVR that stores SRAM address for 16bit
++  lds and sts instructions supported only tiny core.
+ ENUM
+   BFD_RELOC_RL78_NEG8
+ ENUMX
+diff -Nur ./gas/config/tc-avr.c ../avr-binutils-2.24/gas/config/tc-avr.c
+--- binutils-2.24.orig/gas/config/tc-avr.c	2014-12-02 17:48:34.792919056 +0100
++++ gas/config/tc-avr.c	2014-12-02 17:31:35.788899509 +0100
+@@ -89,6 +89,7 @@
+   {"avrxmega5",  AVR_ISA_XMEGA,   bfd_mach_avrxmega5},
+   {"avrxmega6",  AVR_ISA_XMEGA,   bfd_mach_avrxmega6},
+   {"avrxmega7",  AVR_ISA_XMEGA,   bfd_mach_avrxmega7},
++  {"avrtiny",    AVR_ISA_AVRTINY, bfd_mach_avrtiny},
+   {"at90s1200",  AVR_ISA_1200,    bfd_mach_avr1},
+   {"attiny11",   AVR_ISA_AVR1,    bfd_mach_avr1},
+   {"attiny12",   AVR_ISA_AVR1,    bfd_mach_avr1},
+@@ -280,11 +281,19 @@
+   {"atxmega256d3", AVR_ISA_XMEGA, bfd_mach_avrxmega6},
+   {"atxmega128a1", AVR_ISA_XMEGA, bfd_mach_avrxmega7},
+   {"atxmega128a1u", AVR_ISA_XMEGAU, bfd_mach_avrxmega7},
++  {"attiny4",      AVR_ISA_AVRTINY, bfd_mach_avrtiny},
++  {"attiny5",      AVR_ISA_AVRTINY, bfd_mach_avrtiny},
++  {"attiny9",      AVR_ISA_AVRTINY, bfd_mach_avrtiny},
++  {"attiny10",     AVR_ISA_AVRTINY, bfd_mach_avrtiny},
++  {"attiny20",     AVR_ISA_AVRTINY, bfd_mach_avrtiny},
++  {"attiny40",     AVR_ISA_AVRTINY, bfd_mach_avrtiny},
+   {NULL, 0, 0}
+ };
+ 
++
+ /* Current MCU type.  */
+ static struct mcu_type_s   default_mcu = {"avr2", AVR_ISA_AVR2, bfd_mach_avr2};
++static struct mcu_type_s   specified_mcu;
+ static struct mcu_type_s * avr_mcu = & default_mcu;
+ 
+ /* AVR target-specific switches.  */
+@@ -293,9 +302,11 @@
+   int all_opcodes;  /* -mall-opcodes: accept all known AVR opcodes.  */
+   int no_skip_bug;  /* -mno-skip-bug: no warnings for skipping 2-word insns.  */
+   int no_wrap;      /* -mno-wrap: reject rjmp/rcall with 8K wrap-around.  */
++  int link_relax;   /* -mlink-relax: generate relocations for linker
++                       relaxation.  */
+ };
+ 
+-static struct avr_opt_s avr_opt = { 0, 0, 0 };
++static struct avr_opt_s avr_opt = { 0, 0, 0, 0 };
+ 
+ const char EXP_CHARS[] = "eE";
+ const char FLT_CHARS[] = "dD";
+@@ -353,17 +364,23 @@
+ #define OPTION_MMCU 'm'
+ enum options
+ {
+-  OPTION_ALL_OPCODES = OPTION_MD_BASE + 1,
++  OPTION_MLIST_DEVICES = OPTION_MD_BASE + 1,
++  OPTION_ALL_OPCODES,
+   OPTION_NO_SKIP_BUG,
+-  OPTION_NO_WRAP
++  OPTION_NO_WRAP,
++  OPTION_LINK_RELAX,
++  OPTION_RMW_ISA
+ };
+ 
+ struct option md_longopts[] =
+ {
+   { "mmcu",   required_argument, NULL, OPTION_MMCU        },
++  { "mlist-devices", no_argument, NULL, OPTION_MLIST_DEVICES },
+   { "mall-opcodes", no_argument, NULL, OPTION_ALL_OPCODES },
+   { "mno-skip-bug", no_argument, NULL, OPTION_NO_SKIP_BUG },
+   { "mno-wrap",     no_argument, NULL, OPTION_NO_WRAP     },
++  { "mlink-relax",  no_argument, NULL, OPTION_LINK_RELAX  },
++  { "mrmw",         no_argument, NULL, OPTION_RMW_ISA     },
+   { NULL, no_argument, NULL, 0 }
+ };
+ 
+@@ -462,14 +479,17 @@
+ 	"                   avrxmega5 - XMEGA, > 64K, <= 128K FLASH, > 64K RAM\n"
+ 	"                   avrxmega6 - XMEGA, > 128K, <= 256K FLASH, <= 64K RAM\n"
+ 	"                   avrxmega7 - XMEGA, > 128K, <= 256K FLASH, > 64K RAM\n"
+-	"                   or immediate microcontroller name.\n"));
++	"                   avrtiny   - AVR Tiny core with 16 gp registers\n"));
+   fprintf (stream,
+-      _("  -mall-opcodes    accept all AVR opcodes, even if not supported by MCU\n"
++       _("  -mlist-devices   list all supported devices\n"
++    "  -mall-opcodes    accept all AVR opcodes, even if not supported by MCU\n"
+ 	"  -mno-skip-bug    disable warnings for skipping two-word instructions\n"
+ 	"                   (default for avr4, avr5)\n"
+ 	"  -mno-wrap        reject rjmp/rcall instructions with 8K wrap-around\n"
+-	"                   (default for avr3, avr5)\n"));
+-  show_mcu_list (stream);
++	"                   (default for avr3, avr5)\n"
++    "  -mlink-relax     generate relocations for linker relaxation\n"
++    "  -mrmw            accept RMW instructions\n"
++    ));
+ }
+ 
+ static void
+@@ -515,12 +535,20 @@
+ 	   type - this for allows passing -mmcu=... via gcc ASM_SPEC as well
+ 	   as .arch ... in the asm output at the same time.  */
+ 	if (avr_mcu == &default_mcu || avr_mcu->mach == mcu_types[i].mach)
+-	  avr_mcu = &mcu_types[i];
++      {
++        specified_mcu.name = mcu_types[i].name;
++        specified_mcu.isa  |= mcu_types[i].isa;
++        specified_mcu.mach = mcu_types[i].mach;
++        avr_mcu = &specified_mcu;
++      }
+ 	else
+ 	  as_fatal (_("redefinition of mcu type `%s' to `%s'"),
+ 		    avr_mcu->name, mcu_types[i].name);
+ 	return 1;
+       }
++    case OPTION_MLIST_DEVICES:
++      show_mcu_list(stdout);
++      exit (EXIT_SUCCESS);
+     case OPTION_ALL_OPCODES:
+       avr_opt.all_opcodes = 1;
+       return 1;
+@@ -530,6 +558,12 @@
+     case OPTION_NO_WRAP:
+       avr_opt.no_wrap = 1;
+       return 1;
++    case OPTION_LINK_RELAX:
++      avr_opt.link_relax = 1;
++      return 1;
++    case OPTION_RMW_ISA:
++      specified_mcu.isa |= AVR_ISA_RMW;
++      return 1;
+     }
+ 
+   return 0;
+@@ -580,6 +614,7 @@
+     }
+ 
+   bfd_set_arch_mach (stdoutput, TARGET_ARCH, avr_mcu->mach);
++  linkrelax = avr_opt.link_relax;
+ }
+ 
+ /* Resolve STR as a constant expression and return the result.
+@@ -789,29 +824,40 @@
+     case 'a':
+     case 'v':
+       if (*str == 'r' || *str == 'R')
+-	{
+-	  char r_name[20];
+-
+-	  str = extract_word (str, r_name, sizeof (r_name));
+-	  op_mask = 0xff;
+-	  if (ISDIGIT (r_name[1]))
+-	    {
+-	      if (r_name[2] == '\0')
+-		op_mask = r_name[1] - '0';
+-	      else if (r_name[1] != '0'
+-		       && ISDIGIT (r_name[2])
+-		       && r_name[3] == '\0')
+-		op_mask = (r_name[1] - '0') * 10 + r_name[2] - '0';
+-	    }
+-	}
++        {
++          char r_name[20];
++          str = extract_word (str, r_name, sizeof (r_name));
++          op_mask = 0xff;
++          if (ISDIGIT (r_name[1]))
++            {
++              if (r_name[2] == '\0')
++                op_mask = r_name[1] - '0';
++              else if (r_name[1] != '0'
++                       && ISDIGIT (r_name[2])
++                       && r_name[3] == '\0')
++                op_mask = (r_name[1] - '0') * 10 + r_name[2] - '0';
++            }
++        }
+       else
+-	{
+-	  op_mask = avr_get_constant (str, 31);
+-	  str = input_line_pointer;
+-	}
++        {
++          op_mask = avr_get_constant (str, 31);
++          str = input_line_pointer;
++        }
++
++      if (avr_mcu->mach == bfd_mach_avrtiny)
++        {
++          if (op_mask < 16 || op_mask > 31)
++            {
++              as_bad (_("register name or number from 16 to 31 required"));
++              break;
++            }
++        }
++      else if (op_mask > 31)
++        {
++          as_bad (_("register name or number from 0 to 31 required"));
++          break;
++        }
+ 
+-      if (op_mask <= 31)
+-	{
+ 	  switch (*op)
+ 	    {
+ 	    case 'a':
+@@ -839,9 +885,6 @@
+ 	      break;
+ 	    }
+ 	  break;
+-	}
+-      as_bad (_("register name or number from 0 to 31 required"));
+-      break;
+ 
+     case 'e':
+       {
+@@ -948,6 +991,12 @@
+ 		   &op_expr, FALSE, BFD_RELOC_16);
+       break;
+ 
++    case 'j':
++      str = parse_exp (str, &op_expr);
++      fix_new_exp (frag_now, where, opcode->insn_size * 2,
++		   &op_expr, FALSE, BFD_RELOC_AVR_LDS_STS_16);
++      break;
++
+     case 'M':
+       {
+ 	bfd_reloc_code_real_type r_type;
+@@ -1143,6 +1192,53 @@
+   return fixp->fx_frag->fr_address + fixp->fx_where;
+ }
+ 
++static bfd_boolean
++relaxable_section (asection *sec)
++{
++  return (sec->flags & SEC_DEBUGGING) == 0;
++}
++
++/* Does whatever the xtensa port does. */
++int
++avr_validate_fix_sub (fixS *fix)
++{
++  segT add_symbol_segment, sub_symbol_segment;
++
++  /* The difference of two symbols should be resolved by the assembler when
++     linkrelax is not set.  If the linker may relax the section containing
++     the symbols, then an Xtensa DIFF relocation must be generated so that
++     the linker knows to adjust the difference value.  */
++  if (!linkrelax || fix->fx_addsy == NULL)
++    return 0;
++
++  /* Make sure both symbols are in the same segment, and that segment is
++     "normal" and relaxable.  If the segment is not "normal", then the
++     fix is not valid.  If the segment is not "relaxable", then the fix
++     should have been handled earlier.  */
++  add_symbol_segment = S_GET_SEGMENT (fix->fx_addsy);
++  if (! SEG_NORMAL (add_symbol_segment) ||
++      ! relaxable_section (add_symbol_segment))
++    return 0;
++
++  sub_symbol_segment = S_GET_SEGMENT (fix->fx_subsy);
++  return (sub_symbol_segment == add_symbol_segment);
++}
++
++/* TC_FORCE_RELOCATION hook */
++
++/* If linkrelax is turned on, and the symbol to relocate
++   against is in a relaxable segment, don't compute the value -
++   generate a relocation instead. */
++int
++avr_force_relocation (fixS *fix)
++{
++  if (linkrelax && fix->fx_addsy
++      && relaxable_section (S_GET_SEGMENT (fix->fx_addsy)))
++    return 1;
++
++  return generic_force_reloc (fix);
++}
++
+ /* GAS will call this for each fixup.  It should store the correct
+    value in the object file.  */
+ 
+@@ -1166,11 +1262,46 @@
+ 	  fixP->fx_done = 1;
+ 	}
+     }
++  else if (linkrelax && fixP->fx_subsy)
++    {
++      /* For a subtraction relocation expression, generate one
++         of the DIFF relocs, with the value being the difference.
++         Note that a sym1 - sym2 expression is adjusted into a 
++         section_start_sym + sym2_offset_from_section_start - sym1
++         expression. fixP->fx_addsy holds the section start symbol,
++         fixP->fx_offset holds sym2's offset, and fixP->fx_subsy
++         holds sym1. Calculate and write value, but leave fx_offset
++         as is - during relaxation, fx_offset - value gives sym1's value */
++
++       switch (fixP->fx_r_type)
++         {
++           case BFD_RELOC_8:
++             fixP->fx_r_type = BFD_RELOC_AVR_DIFF8;
++             break;
++           case BFD_RELOC_16:
++             fixP->fx_r_type = BFD_RELOC_AVR_DIFF16;
++             break;
++           case BFD_RELOC_32:
++             fixP->fx_r_type = BFD_RELOC_AVR_DIFF32;
++             break;
++           default:
++             as_bad_where (fixP->fx_file, fixP->fx_line, _("expression too complex"));
++             break;
++         }
+ 
++      value = S_GET_VALUE (fixP->fx_addsy) + 
++          fixP->fx_offset - S_GET_VALUE (fixP->fx_subsy);
++
++      fixP->fx_subsy = NULL;
++  }
+   /* We don't actually support subtracting a symbol.  */
+   if (fixP->fx_subsy != (symbolS *) NULL)
+     as_bad_where (fixP->fx_file, fixP->fx_line, _("expression too complex"));
+ 
++  /* For the DIFF relocs, write the value into the object file while still
++     keeping fx_done FALSE, as both the difference (recorded in the object file)
++     and the sym offset (part of fixP) are needed at link relax time */
++  where = (unsigned char *) fixP->fx_frag->fr_literal + fixP->fx_where;
+   switch (fixP->fx_r_type)
+     {
+     default:
+@@ -1180,6 +1311,19 @@
+     case BFD_RELOC_AVR_13_PCREL:
+     case BFD_RELOC_32:
+     case BFD_RELOC_16:
++      break;
++    case BFD_RELOC_AVR_DIFF8:
++      if (value > 255 || value < -128)
++        as_warn_where (fixP->fx_file, fixP->fx_line,
++                           _("operand out of range: %ld"), value);
++      *where = value;
++	  break;
++    case BFD_RELOC_AVR_DIFF16:
++      bfd_putl16 ((bfd_vma) value, where);
++      break;
++    case BFD_RELOC_AVR_DIFF32:
++      bfd_putl16 ((bfd_vma) value, where);
++      break;
+     case BFD_RELOC_AVR_CALL:
+       break;
+     }
+@@ -1256,11 +1400,21 @@
+ 	  bfd_putl16 ((bfd_vma) insn | LDI_IMMEDIATE (value), where);
+ 	  break;
+ 
++	case BFD_RELOC_AVR_LDS_STS_16:
++	  if ((value < 0x40) || (value > 0xBF))
++	    as_warn_where (fixP->fx_file, fixP->fx_line,
++			   _("operand out of range: 0x%lx"),
++			   (unsigned long)value);
++	  insn |= ((value & 0xF) | ((value & 0x30) << 5) | ((value & 0x40) << 2));
++	  bfd_putl16 ((bfd_vma) insn, where);
++	  break;
++
+ 	case BFD_RELOC_AVR_6:
+ 	  if ((value > 63) || (value < 0))
+ 	    as_bad_where (fixP->fx_file, fixP->fx_line,
+ 			  _("operand out of range: %ld"), value);
+-	  bfd_putl16 ((bfd_vma) insn | ((value & 7) | ((value & (3 << 3)) << 7) | ((value & (1 << 5)) << 8)), where);
++	  bfd_putl16 ((bfd_vma) insn | ((value & 7) | ((value & (3 << 3)) << 7)
++					| ((value & (1 << 5)) << 8)), where);
+ 	  break;
+ 
+ 	case BFD_RELOC_AVR_6_ADIW:
+@@ -1435,6 +1589,28 @@
+ 
+   opcode = (struct avr_opcodes_s *) hash_find (avr_hash, op);
+ 
++  if (opcode && !avr_opt.all_opcodes)
++    {
++      /* Check if the instruction's ISA bit is ON in the ISA bits of the part 
++         specified by the user. If not look for other instructions
++         specifications with same mnemonic who's ISA bits matches.
++
++         This requires include/opcode/avr.h to have the instructions with
++         same mnenomic to be specified in sequence.  */
++
++      while ((opcode->isa & avr_mcu->isa) != opcode->isa)
++        {
++          opcode++;
++     
++          if (opcode->name && strcmp(op, opcode->name))
++            {
++              as_bad (_("illegal opcode %s for mcu %s"), 
++                      opcode->name, avr_mcu->name);
++              return;
++            }
++        }
++    } 
++
+   if (opcode == NULL)
+     {
+       as_bad (_("unknown opcode `%s'"), op);
+@@ -1447,9 +1623,6 @@
+   if (*str && *opcode->constraints == '?')
+     ++opcode;
+ 
+-  if (!avr_opt.all_opcodes && (opcode->isa & avr_mcu->isa) != opcode->isa)
+-    as_bad (_("illegal opcode %s for mcu %s"), opcode->name, avr_mcu->name);
+-
+   dwarf2_emit_insn (0);
+ 
+   /* We used to set input_line_pointer to the result of get_operands,
+diff -Nur ./gas/config/tc-avr.h ../avr-binutils-2.24/gas/config/tc-avr.h
+--- binutils-2.24.orig/gas/config/tc-avr.h	2014-12-02 17:48:34.796919056 +0100
++++ gas/config/tc-avr.h	2014-12-02 17:31:35.788899509 +0100
+@@ -93,6 +93,18 @@
+    visible symbols can be overridden.  */
+ #define EXTERN_FORCE_RELOC 0
+ 
++/* If defined, this macro allows control over whether fixups for a
++   given section will be processed when the linkrelax variable is
++   set. Define it to zero and handle things in md_apply_fix instead.*/
++#define TC_LINKRELAX_FIXUP(SEG) 0
++
++/* If this macro returns non-zero, it guarantees that a relocation will be emitted
++   even when the value can be resolved locally. Do that if linkrelax is turned on */
++#define TC_FORCE_RELOCATION(fix)	avr_force_relocation (fix)
++#define TC_FORCE_RELOCATION_SUB_SAME(fix, seg) \
++  (! SEG_NORMAL (seg) || avr_force_relocation (fix))
++extern int avr_force_relocation (struct fix *);
++
+ /* Values passed to md_apply_fix don't include the symbol value.  */
+ #define MD_APPLY_SYM_VALUE(FIX) 0
+ 
+@@ -150,6 +162,12 @@
+       goto SKIP;					     \
+     }
+ 
++/* This macro is evaluated for any fixup with a fx_subsy that
++   fixup_segment cannot reduce to a number.  If the macro returns
++   false an error will be reported. */
++#define TC_VALIDATE_FIX_SUB(fix, seg)   avr_validate_fix_sub (fix)                                                                    
++extern int avr_validate_fix_sub (struct fix *);
++
+ /* This target is buggy, and sets fix size too large.  */
+ #define TC_FX_SIZE_SLACK(FIX) 2
+ 
+diff -Nur ./gas/doc/as.1 ../avr-binutils-2.24/gas/doc/as.1
+--- binutils-2.24.orig/gas/doc/as.1	2014-12-02 17:48:34.796919056 +0100
++++ gas/doc/as.1	2014-12-02 17:34:14.660902556 +0100
+@@ -1,4 +1,4 @@
+-.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.20)
++.\" Automatically generated by Pod::Man 2.27 (Pod::Simple 3.28)
+ .\"
+ .\" Standard preamble:
+ .\" ========================================================================
+@@ -38,6 +38,8 @@
+ .    ds PI \(*p
+ .    ds L" ``
+ .    ds R" ''
++.    ds C`
++.    ds C'
+ 'br\}
+ .\"
+ .\" Escape single quotes in literal strings from groff's Unicode transform.
+@@ -48,17 +50,24 @@
+ .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
+ .\" entries marked with X<> in POD.  Of course, you'll have to process the
+ .\" output yourself in some meaningful fashion.
+-.ie \nF \{\
+-.    de IX
+-.    tm Index:\\$1\t\\n%\t"\\$2"
++.\"
++.\" Avoid warning from groff about undefined register 'F'.

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201412021950.sB2Jo1a6005422>