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>