svn commit: r373781 - in head/devel/avr-binutils: . files
Joerg Wunsch
joerg at FreeBSD.org
Tue Dec 2 19:50:02 UTC 2014
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 at 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 at 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 at 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
++ at deffn {} BFD_RELOC_AVR_DIFF8
++ at deffnx {} BFD_RELOC_AVR_DIFF16
++ at 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.
++ at end deffn
++ at 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.
++ at 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 at 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 ***
More information about the svn-ports-head
mailing list