From patchwork Tue Feb 14 18:52:13 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Georg-Johann Lay X-Patchwork-Id: 141167 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id C46B81007D1 for ; Wed, 15 Feb 2012 05:53:29 +1100 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1329850410; h=Comment: DomainKey-Signature:Received:Received:Received:Received: Message-ID:Date:From:User-Agent:MIME-Version:To:CC:Subject: Content-Type:Mailing-List:Precedence:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:Sender:Delivered-To; bh=fz8r4Bo Azm0fYJSISoPDdnzLJU4=; b=N7b0b3R677YywHzMNmeB4Mv+aZxegI7UB4H/7tI 9ue75a4mcpnpCBBydgeYvabZe2MJ++TL9lkDuRdxUfSjqpmofSh5ZTqJfNvOBAL2 59IHHdoYvV1KcvcwuS2rG99dJ0k1fbnb+4mNunHaDCUESLTMPgeqwrnvDkpp3ItW 1nB4= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:X-RZG-AUTH:X-RZG-CLASS-ID:Received:Message-ID:Date:From:User-Agent:MIME-Version:To:CC:Subject:Content-Type:X-IsSubscribed:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=NpW3AUnLe9DrQYiA5mpmgZLdzQkUR2my5mJ67sbiipNMINghof9G/W9u6RBTML 3x8mxoMK/EES9fHfvKMc+J9lztX6d7rnWmF55EmxaOXOBWkJpeSz+8OfgwgZv6/E UZ8EFa2ZoQKStaQOwEOupQRWD13PitakmyxYmt/eJ3/5U=; Received: (qmail 28636 invoked by alias); 14 Feb 2012 18:53:24 -0000 Received: (qmail 28602 invoked by uid 22791); 14 Feb 2012 18:53:19 -0000 X-SWARE-Spam-Status: No, hits=-1.3 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, RCVD_IN_DNSWL_NONE, TW_OV, TW_RX, TW_TX, TW_VH, TW_VQ, TW_VR X-Spam-Check-By: sourceware.org Received: from mo-p00-ob.rzone.de (HELO mo-p00-ob.rzone.de) (81.169.146.160) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 14 Feb 2012 18:53:01 +0000 X-RZG-AUTH: :LXoWVUeid/7A29J/hMvvT2k715jHQaJercGObUOFkj18odoYNahU4Q== X-RZG-CLASS-ID: mo00 Received: from [192.168.0.22] (business-188-111-022-002.static.arcor-ip.net [188.111.22.2]) by smtp.strato.de (klopstock mo20) (RZmta 27.6 AUTH) with ESMTPA id z036aeo1EIkJb4 ; Tue, 14 Feb 2012 19:52:13 +0100 (MET) Message-ID: <4F3AAD5D.2080103@gjlay.de> Date: Tue, 14 Feb 2012 19:52:13 +0100 From: Georg-Johann Lay User-Agent: Thunderbird 2.0.0.24 (X11/20100302) MIME-Version: 1.0 To: gcc-patches@gcc.gnu.org CC: Eric Weddington , Denis Chertykov , Anatoly Sokolov Subject: [Patch,AVR] Add xmega support X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org This patch adds support for xmega cores and does the following: * Add architectures avrxmega2/4/5/6/7 to avr-devices.c * Add some xmega MCUs to avr-mcus.def * Add new function avr.c:avr_out_movhi_mr_r_xmega that works similar to out_movhi_mr_r except that the low byte is output first. Rationale is that writing SP_L triggers an atomic block of 4 ticks so that no IRQ-disabling is needed when setting SP. * Similar rationale behind changes to __prologue_saves__ and __epilogue_restores__ from libgcc. * ISR pro- and epilogue save/restore RAMPD/X/Y/Z as needed. * At file start, definitions for CCP/RAMPD/X/Y are printed. * While printing asm, RAMPD/X/Y are detected and printed by their name instead of by their I/O address. * Some built-in defines are added The architecture names and MCU assignments follow binutils ./gas/config/tc-avr.c so that the compiler is in sync with binutils. I don't see a reason to have both avrxmega2 and avrxmega4 because from the compiler's perspective they are the same; but that's obviously how things are implemented. There is no native support for big-RAM devices and I can hardly image GCC (in particular IRA/reload) can cope with a modelling of 3-byte RAM pointers. But that's a different story... It might be easier for the compiler if crucial SFRs are not modelled by MEM but as REG instead, but for that change I don't know enough about debugging formats and impact on gdb. Maybe Richard can comment on that? Ok for trunk? Johann libgcc/ Anatoly Sokolov Eric Weddington * config/avr/lib1funcs.S (__prologue_saves__): Handle AVR_XMEGA (__epilogue_restores__): Ditto. gcc/ Anatoly Sokolov Eric Weddington * config/avr/avr-devices.c (avr_arch_types): Add avrxmega2, avrxmega4, avrxmega5, avrxmega6, avrxmega7. Rewrite initializers for .macro. * config/avr/avr-mcus.def (AVR_MCU): Add known MCUs: avrxmega2: atxmega16a4, atxmega16d4, atxmega16x1, atxmega32a4 atxmega32d4, atxmega32x1. avrxmega4: atxmega64a3, atxmega64d3. avrxmega5: atxmega64a1, atxmega64a1u. avrxmega6: atxmega128a3, atxmega128d3, atxmega192a3, atxmega192d3, atxmega256a3, atxmega256a3b, atxmega256a3bu, atxmega256d3. avrxmega7: atxmega128a1, atxmega128a1u. * config/avr/multilib.h: Regenerate. * config/avr/t-multilib: Regenerate. * config/avr/avr-tables.opt: Regenerate. * config/avr/avr.h (enum avr_arch): Add: ARCH_AVRXMEGA2, ARCH_AVRXMEGA4, ARCH_AVRXMEGA5, ARCH_AVRXMEGA6, ARCH_AVRXMEGA7. (struct base_arch_s): Rename reserved to xmega_p. Rename reserved2 to have_rampd. (AVR_XMEGA): New define. (AVR_HAVE_RAMPD, AVR_HAVE_RAMPX, AVR_HAVE_RAMPY): New defines. (AVR_HAVE_RAMPZ): Change definition to fit xmega. * config/avr/predicates.md (io_address_operand): Take into account SFR offset. (low_io_address_operand): Ditto. (high_io_address_operand): Ditto. * config/avr/avr.md (isa): Add alternatives no_xmega, xmega. (enabled, movhi_sp_r): Use them. * config/avr/avr-c.c (avr_cpu_cpp_builtins): Use cpp_define_formatted to built-in define __AVR_ARCH__. (__AVR_XMEGA__): New built-in define. (__AVR_HAVE_RAMPD__): New built-in define. (__AVR_HAVE_RAMPX__): New built-in define. (__AVR_HAVE_RAMPY__): New built-in define. (__AVR_HAVE_RAMPZ__): Change condition when to built-in define it. * config/avr/avr.c (avr_addr_t): Add ccp, rampd, rampx, rampy. (avr_option_override): Initialize them. (sreg_rtx, rampd_rtx, rampx_rtx, rampy_rtx): New GTY rtx. (avr_init_expanders): Initialize them. No more block several calls. (emit_push_sfr): New static function. (avr_prologue_setup_frame): Use it to push SREG, RAMPD/X/Y/Z as needed. Handle AVR_XMEGA. (expand_epilogue): Handle AVR_XMEGA. Pop RAMPD/X/Y/Z as needed. (avr_print_operand): Print addreeses as symbols for RAMPX, RAMPY, RAMPD, CCP. (output_movhi): Handle AVR_XMEGA when writing to SP. (avr_out_movhi_mr_r_xmega): New static function. (out_movhi_mr_r): Forward to avr_out_movhi_mr_r_xmega for AVR_XMEGA. (avr_file_start): Print symbol defines for __RAMPX__, __RAMPY__, __RAMPD__, __CCP__ as needed. Index: libgcc/config/avr/lib1funcs.S =================================================================== --- libgcc/config/avr/lib1funcs.S (revision 183939) +++ libgcc/config/avr/lib1funcs.S (working copy) @@ -1696,6 +1696,13 @@ DEFUN __prologue_saves__ sub r28,r26 out __SP_L__,r28 clr r29 +#elif defined (__AVR__XMEGA__) + in r28,__SP_L__ + in r29,__SP_H__ + sub r28,r26 + sbc r29,r27 + out __SP_L__,r28 + out __SP_H__,r29 #else in r28,__SP_L__ in r29,__SP_H__ @@ -1745,6 +1752,13 @@ DEFUN __epilogue_restores__ add r28,r30 out __SP_L__,r28 mov r28, r26 +#elif defined (__AVR__XMEGA__) + ldd r27,Y+1 + add r28,r30 + adc r29,__zero_reg__ + out __SP_L__,r28 + out __SP_H__,r29 + wmov 28, 26 #else ldd r27,Y+1 add r28,r30 Index: gcc/config/avr/predicates.md =================================================================== --- gcc/config/avr/predicates.md (revision 184156) +++ gcc/config/avr/predicates.md (working copy) @@ -45,17 +45,20 @@ (define_predicate "stack_register_operan ;; Return true if OP is a valid address for lower half of I/O space. (define_predicate "low_io_address_operand" (and (match_code "const_int") - (match_test "IN_RANGE((INTVAL (op)), 0x20, 0x3F)"))) + (match_test "IN_RANGE (INTVAL (op) - avr_current_arch->sfr_offset, + 0, 0x1f)"))) ;; Return true if OP is a valid address for high half of I/O space. (define_predicate "high_io_address_operand" (and (match_code "const_int") - (match_test "IN_RANGE((INTVAL (op)), 0x40, 0x5F)"))) + (match_test "IN_RANGE (INTVAL (op) - avr_current_arch->sfr_offset, + 0x20, 0x3F)"))) ;; Return true if OP is a valid address of I/O space. (define_predicate "io_address_operand" (and (match_code "const_int") - (match_test "IN_RANGE((INTVAL (op)), 0x20, (0x60 - GET_MODE_SIZE(mode)))"))) + (match_test "IN_RANGE (INTVAL (op) - avr_current_arch->sfr_offset, + 0, 0x40 - GET_MODE_SIZE (mode))"))) ;; Return 1 if OP is a general operand not in flash memory (define_predicate "nop_general_operand" Index: gcc/config/avr/t-multilib =================================================================== --- gcc/config/avr/t-multilib (revision 184156) +++ gcc/config/avr/t-multilib (working copy) @@ -21,9 +21,9 @@ # along with GCC; see the file COPYING3. If not see # . -MULTILIB_OPTIONS = mmcu=avr2/mmcu=avr25/mmcu=avr3/mmcu=avr31/mmcu=avr35/mmcu=avr4/mmcu=avr5/mmcu=avr51/mmcu=avr6 mtiny-stack +MULTILIB_OPTIONS = mmcu=avr2/mmcu=avr25/mmcu=avr3/mmcu=avr31/mmcu=avr35/mmcu=avr4/mmcu=avr5/mmcu=avr51/mmcu=avr6/mmcu=avrxmega2/mmcu=avrxmega4/mmcu=avrxmega5/mmcu=avrxmega6/mmcu=avrxmega7 mtiny-stack -MULTILIB_DIRNAMES = avr2 avr25 avr3 avr31 avr35 avr4 avr5 avr51 avr6 tiny-stack avr25/tiny-stack +MULTILIB_DIRNAMES = avr2 avr25 avr3 avr31 avr35 avr4 avr5 avr51 avr6 avrxmega2 avrxmega4 avrxmega5 avrxmega6 avrxmega7 tiny-stack avr25/tiny-stack MULTILIB_EXCEPTIONS = \ mmcu=avr3/mtiny-stack \ @@ -32,7 +32,12 @@ MULTILIB_EXCEPTIONS = \ mmcu=avr4/mtiny-stack \ mmcu=avr5/mtiny-stack \ mmcu=avr51/mtiny-stack \ - mmcu=avr6/mtiny-stack + mmcu=avr6/mtiny-stack \ + mmcu=avrxmega2/mtiny-stack \ + mmcu=avrxmega4/mtiny-stack \ + mmcu=avrxmega5/mtiny-stack \ + mmcu=avrxmega6/mtiny-stack \ + mmcu=avrxmega7/mtiny-stack MULTILIB_MATCHES = \ mmcu?at90s2313=mmcu?at90s2313 \ @@ -189,4 +194,24 @@ MULTILIB_MATCHES = \ mmcu?avr51=mmcu?at90usb1286 \ mmcu?avr51=mmcu?at90usb1287 \ mmcu?avr6=mmcu?atmega2560 \ - mmcu?avr6=mmcu?atmega2561 + mmcu?avr6=mmcu?atmega2561 \ + mmcu?avrxmega2=mmcu?atxmega16a4 \ + mmcu?avrxmega2=mmcu?atxmega16d4 \ + mmcu?avrxmega2=mmcu?atxmega16x1 \ + mmcu?avrxmega2=mmcu?atxmega32a4 \ + mmcu?avrxmega2=mmcu?atxmega32d4 \ + mmcu?avrxmega2=mmcu?atxmega32x1 \ + mmcu?avrxmega4=mmcu?atxmega64a3 \ + mmcu?avrxmega4=mmcu?atxmega64d3 \ + mmcu?avrxmega5=mmcu?atxmega64a1 \ + mmcu?avrxmega5=mmcu?atxmega64a1u \ + mmcu?avrxmega6=mmcu?atxmega128a3 \ + mmcu?avrxmega6=mmcu?atxmega128d3 \ + mmcu?avrxmega6=mmcu?atxmega192a3 \ + mmcu?avrxmega6=mmcu?atxmega192d3 \ + mmcu?avrxmega6=mmcu?atxmega256a3 \ + mmcu?avrxmega6=mmcu?atxmega256a3b \ + mmcu?avrxmega6=mmcu?atxmega256a3bu \ + mmcu?avrxmega6=mmcu?atxmega256d3 \ + mmcu?avrxmega7=mmcu?atxmega128a1 \ + mmcu?avrxmega7=mmcu?atxmega128a1u Index: gcc/config/avr/avr.md =================================================================== --- gcc/config/avr/avr.md (revision 184156) +++ gcc/config/avr/avr.md (working copy) @@ -155,9 +155,10 @@ (define_attr "adjust_len" ;; ijmp : ISA has no EICALL/EIJMP eijmp : ISA has EICALL/EIJMP ;; lpm : ISA has no LPMX lpmx : ISA has LPMX ;; elpm : ISA has ELPM but no ELPMX elpmx : ISA has ELPMX +;; no_xmega: non-XMEGA core xmega : XMEGA core (define_attr "isa" - "mov,movw, rjmp,jmp, ijmp,eijmp, lpm,lpmx, elpm,elpmx, + "mov,movw, rjmp,jmp, ijmp,eijmp, lpm,lpmx, elpm,elpmx, no_xmega,xmega, standard" (const_string "standard")) @@ -204,6 +205,14 @@ (define_attr "enabled" "" (and (eq_attr "isa" "elpmx") (match_test "AVR_HAVE_ELPMX")) (const_int 1) + + (and (eq_attr "isa" "xmega") + (match_test "AVR_XMEGA")) + (const_int 1) + + (and (eq_attr "isa" "no_xmega") + (match_test "!AVR_XMEGA")) + (const_int 1) ] (const_int 0))) @@ -580,15 +589,17 @@ (define_peephole2 ;; handled by generic movhi insn. (define_insn "movhi_sp_r" - [(set (match_operand:HI 0 "stack_register_operand" "=q,q") - (unspec_volatile:HI [(match_operand:HI 1 "register_operand" "r,r") - (match_operand:HI 2 "const_int_operand" "L,P")] + [(set (match_operand:HI 0 "stack_register_operand" "=q,q,q") + (unspec_volatile:HI [(match_operand:HI 1 "register_operand" "r,r,r") + (match_operand:HI 2 "const_int_operand" "L,P,LP")] UNSPECV_WRITE_SP))] "!AVR_HAVE_8BIT_SP" "@ out __SP_H__,%B1\;out __SP_L__,%A1 - cli\;out __SP_H__,%B1\;sei\;out __SP_L__,%A1" - [(set_attr "length" "2,4") + cli\;out __SP_H__,%B1\;sei\;out __SP_L__,%A1 + out __SP_L__,%A1\;out __SP_H__,%B1" + [(set_attr "length" "2,4,2") + (set_attr "isa" "no_xmega,no_xmega,xmega") (set_attr "cc" "none")]) (define_peephole2 Index: gcc/config/avr/avr-c.c =================================================================== --- gcc/config/avr/avr-c.c (revision 184156) +++ gcc/config/avr/avr-c.c (working copy) @@ -77,23 +77,21 @@ avr_cpu_cpp_builtins (struct cpp_reader builtin_define_std ("AVR"); if (avr_current_arch->macro) - cpp_define (pfile, avr_current_arch->macro); + cpp_define_formatted (pfile, "__AVR_ARCH__=%s", avr_current_arch->macro); if (avr_extra_arch_macro) cpp_define (pfile, avr_extra_arch_macro); - if (avr_current_arch->have_elpm) - cpp_define (pfile, "__AVR_HAVE_RAMPZ__"); - if (avr_current_arch->have_elpm) - cpp_define (pfile, "__AVR_HAVE_ELPM__"); - if (avr_current_arch->have_elpmx) - cpp_define (pfile, "__AVR_HAVE_ELPMX__"); - if (avr_current_arch->have_movw_lpmx) - { - cpp_define (pfile, "__AVR_HAVE_MOVW__"); - cpp_define (pfile, "__AVR_HAVE_LPMX__"); - } + if (AVR_HAVE_RAMPD) cpp_define (pfile, "__AVR_HAVE_RAMPD__"); + if (AVR_HAVE_RAMPX) cpp_define (pfile, "__AVR_HAVE_RAMPX__"); + if (AVR_HAVE_RAMPY) cpp_define (pfile, "__AVR_HAVE_RAMPY__"); + if (AVR_HAVE_RAMPZ) cpp_define (pfile, "__AVR_HAVE_RAMPZ__"); + if (AVR_HAVE_ELPM) cpp_define (pfile, "__AVR_HAVE_ELPM__"); + if (AVR_HAVE_ELPMX) cpp_define (pfile, "__AVR_HAVE_ELPMX__"); + if (AVR_HAVE_MOVW) cpp_define (pfile, "__AVR_HAVE_MOVW__"); + if (AVR_HAVE_LPMX) cpp_define (pfile, "__AVR_HAVE_LPMX__"); + if (avr_current_arch->asm_only) cpp_define (pfile, "__AVR_ASM_ONLY__"); - if (avr_current_arch->have_mul) + if (AVR_HAVE_MUL) { cpp_define (pfile, "__AVR_ENHANCED__"); cpp_define (pfile, "__AVR_HAVE_MUL__"); @@ -103,6 +101,8 @@ avr_cpu_cpp_builtins (struct cpp_reader cpp_define (pfile, "__AVR_MEGA__"); cpp_define (pfile, "__AVR_HAVE_JMP_CALL__"); } + if (AVR_XMEGA) + cpp_define (pfile, "__AVR_XMEGA__"); if (avr_current_arch->have_eijmp_eicall) { cpp_define (pfile, "__AVR_HAVE_EIJMP_EICALL__"); Index: gcc/config/avr/avr-devices.c =================================================================== --- gcc/config/avr/avr-devices.c (revision 184156) +++ gcc/config/avr/avr-devices.c (working copy) @@ -32,21 +32,27 @@ avr_arch_types[] = /* unknown device specified */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 32, 1, NULL, "avr2" }, /* - A M J LM E E E d S S O # F - S U M PO L L I a t F ff 6 l - M L P MV P P J - - t a R s 4 a - XW M M M a r e s - X P t t k h */ - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 32, 1, "__AVR_ARCH__=1", "avr1" }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 32, 1, "__AVR_ARCH__=2", "avr2" }, - { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0x0060, 32, 1, "__AVR_ARCH__=25", "avr25" }, - { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0x0060, 32, 1, "__AVR_ARCH__=3", "avr3" }, - { 0, 0, 1, 0, 1, 0, 0, 0, 0, 0x0060, 32, 2, "__AVR_ARCH__=31", "avr31" }, - { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0x0060, 32, 1, "__AVR_ARCH__=35", "avr35" }, - { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0x0060, 32, 1, "__AVR_ARCH__=4", "avr4" }, - { 0, 1, 1, 1, 0, 0, 0, 0, 0, 0x0060, 32, 1, "__AVR_ARCH__=5", "avr5" }, - { 0, 1, 1, 1, 1, 1, 0, 0, 0, 0x0060, 32, 2, "__AVR_ARCH__=51", "avr51" }, - { 0, 1, 1, 1, 1, 1, 1, 0, 0, 0x0060, 32, 4, "__AVR_ARCH__=6", "avr6" } + A M J LM E E E X R d S S O # F A + S U M PO L L I M A a t F ff 6 l r + M L P MV P P J E M t a R s 4 a c + XW M M M G P a r e s h + X P A D t t k h ID */ + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 32, 1, "1", "avr1" }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 32, 1, "2", "avr2" }, + { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0x0060, 32, 1, "25", "avr25" }, + { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0x0060, 32, 1, "3", "avr3" }, + { 0, 0, 1, 0, 1, 0, 0, 0, 0, 0x0060, 32, 2, "31", "avr31" }, + { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0x0060, 32, 1, "35", "avr35" }, + { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0x0060, 32, 1, "4", "avr4" }, + { 0, 1, 1, 1, 0, 0, 0, 0, 0, 0x0060, 32, 1, "5", "avr5" }, + { 0, 1, 1, 1, 1, 1, 0, 0, 0, 0x0060, 32, 2, "51", "avr51" }, + { 0, 1, 1, 1, 1, 1, 1, 0, 0, 0x0060, 32, 4, "6", "avr6" }, + + { 0, 1, 1, 1, 0, 0, 0, 1, 0, 0x2000, 0, 1, "102", "avrxmega2" }, + { 0, 1, 1, 1, 0, 0, 0, 1, 0, 0x2000, 0, 1, "104", "avrxmega4" }, /* Same */ + { 0, 1, 1, 1, 0, 0, 0, 1, 1, 0x2000, 0, 1, "105", "avrxmega5" }, + { 0, 1, 1, 1, 1, 1, 1, 1, 0, 0x2000, 0, 4, "106", "avrxmega6" }, + { 0, 1, 1, 1, 1, 1, 1, 1, 1, 0x2000, 0, 4, "107", "avrxmega7" } }; const struct mcu_type_s avr_mcu_types[] = { Index: gcc/config/avr/avr-mcus.def =================================================================== --- gcc/config/avr/avr-mcus.def (revision 184156) +++ gcc/config/avr/avr-mcus.def (working copy) @@ -201,6 +201,36 @@ AVR_MCU ("at90usb1287", ARCH_AV AVR_MCU ("avr6", ARCH_AVR6, NULL, 0, 0, 0x0200, "m2561") AVR_MCU ("atmega2560", ARCH_AVR6, "__AVR_ATmega2560__", 0, 0, 0x0200, "m2560") AVR_MCU ("atmega2561", ARCH_AVR6, "__AVR_ATmega2561__", 0, 0, 0x0200, "m2561") +/* Xmega, 16K <= Flash < 64K, RAM <= 64K */ +AVR_MCU ("avrxmega2", ARCH_AVRXMEGA2, NULL, 0, 0, 0x2000, "x32a4") +AVR_MCU ("atxmega16a4", ARCH_AVRXMEGA2, "__AVR_ATxmega16A4__", 0, 0, 0x2000, "x16a4") +AVR_MCU ("atxmega16d4", ARCH_AVRXMEGA2, "__AVR_ATxmega16D4__", 0, 0, 0x2000, "x16d4") +AVR_MCU ("atxmega16x1", ARCH_AVRXMEGA2, "__AVR_ATxmega16X1__", 0, 0, 0x2000, "x16x1") +AVR_MCU ("atxmega32a4", ARCH_AVRXMEGA2, "__AVR_ATxmega32A4__", 0, 0, 0x2000, "x32a4") +AVR_MCU ("atxmega32d4", ARCH_AVRXMEGA2, "__AVR_ATxmega32D4__", 0, 0, 0x2000, "x32d4") +AVR_MCU ("atxmega32x1", ARCH_AVRXMEGA2, "__AVR_ATxmega32X1__", 0, 0, 0x2000, "x32x1") +/* Xmega, Flash == 64K, RAM <= 64K */ +AVR_MCU ("avrxmega4", ARCH_AVRXMEGA4, NULL, 0, 0, 0x2000, "x64a4") +AVR_MCU ("atxmega64a3", ARCH_AVRXMEGA4, "__AVR_ATxmega64A3__", 0, 0, 0x2000, "x64a3") +AVR_MCU ("atxmega64d3", ARCH_AVRXMEGA4, "__AVR_ATxmega64D3__", 0, 0, 0x2000, "x64d3") +/* Xmega, Flash == 64K, RAM > 64K */ +AVR_MCU ("avrxmega5", ARCH_AVRXMEGA5, NULL, 0, 0, 0x2000, "x64a1") +AVR_MCU ("atxmega64a1", ARCH_AVRXMEGA5, "__AVR_ATxmega64A1__", 0, 0, 0x2000, "x64a1") +AVR_MCU ("atxmega64a1u", ARCH_AVRXMEGA5, "__AVR_ATxmega64A1U__", 0, 0, 0x2000, "x64a1u") +/* Xmega, 128K <= Flash <= 256K, RAM <= 64K */ +AVR_MCU ("avrxmega6", ARCH_AVRXMEGA6, NULL, 0, 0, 0x2000, "x128a3") +AVR_MCU ("atxmega128a3", ARCH_AVRXMEGA6, "__AVR_ATxmega128A3__", 0, 0, 0x2000, "x128a3") +AVR_MCU ("atxmega128d3", ARCH_AVRXMEGA6, "__AVR_ATxmega128D3__", 0, 0, 0x2000, "x128d3") +AVR_MCU ("atxmega192a3", ARCH_AVRXMEGA6, "__AVR_ATxmega192A3__", 0, 0, 0x2000, "x192a3") +AVR_MCU ("atxmega192d3", ARCH_AVRXMEGA6, "__AVR_ATxmega192D3__", 0, 0, 0x2000, "x192d3") +AVR_MCU ("atxmega256a3", ARCH_AVRXMEGA6, "__AVR_ATxmega256A3__", 0, 0, 0x2000, "x256a3") +AVR_MCU ("atxmega256a3b", ARCH_AVRXMEGA6, "__AVR_ATxmega256A3B__", 0, 0, 0x2000, "x256a3b") +AVR_MCU ("atxmega256a3bu", ARCH_AVRXMEGA6, "__AVR_ATxmega256A3BU__", 0, 0, 0x2000, "x256a3bu") +AVR_MCU ("atxmega256d3", ARCH_AVRXMEGA6, "__AVR_ATxmega256D3__", 0, 0, 0x2000, "x256d3") +/* Xmega, 128K <= Flash <= 256K, RAM > 64K RAM. */ +AVR_MCU ("avrxmega7", ARCH_AVRXMEGA7, NULL, 0, 0, 0x2000, "x128a1") +AVR_MCU ("atxmega128a1", ARCH_AVRXMEGA7, "__AVR_ATxmega128A1__", 0, 0, 0x2000, "x128a1") +AVR_MCU ("atxmega128a1u", ARCH_AVRXMEGA7, "__AVR_ATxmega128A1U__", 0, 0, 0x2000, "x128a1u") /* Assembler only. */ AVR_MCU ("avr1", ARCH_AVR1, NULL, 0, 0, 0x0060, "s1200") AVR_MCU ("at90s1200", ARCH_AVR1, "__AVR_AT90S1200__", 0, 0, 0x0060, "s1200") Index: gcc/config/avr/avr-tables.opt =================================================================== --- gcc/config/avr/avr-tables.opt (revision 184156) +++ gcc/config/avr/avr-tables.opt (working copy) @@ -504,20 +504,95 @@ EnumValue Enum(avr_mcu) String(atmega2561) Value(159) EnumValue -Enum(avr_mcu) String(avr1) Value(160) +Enum(avr_mcu) String(avrxmega2) Value(160) EnumValue -Enum(avr_mcu) String(at90s1200) Value(161) +Enum(avr_mcu) String(atxmega16a4) Value(161) EnumValue -Enum(avr_mcu) String(attiny11) Value(162) +Enum(avr_mcu) String(atxmega16d4) Value(162) EnumValue -Enum(avr_mcu) String(attiny12) Value(163) +Enum(avr_mcu) String(atxmega16x1) Value(163) EnumValue -Enum(avr_mcu) String(attiny15) Value(164) +Enum(avr_mcu) String(atxmega32a4) Value(164) EnumValue -Enum(avr_mcu) String(attiny28) Value(165) +Enum(avr_mcu) String(atxmega32d4) Value(165) + +EnumValue +Enum(avr_mcu) String(atxmega32x1) Value(166) + +EnumValue +Enum(avr_mcu) String(avrxmega4) Value(167) + +EnumValue +Enum(avr_mcu) String(atxmega64a3) Value(168) + +EnumValue +Enum(avr_mcu) String(atxmega64d3) Value(169) + +EnumValue +Enum(avr_mcu) String(avrxmega5) Value(170) + +EnumValue +Enum(avr_mcu) String(atxmega64a1) Value(171) + +EnumValue +Enum(avr_mcu) String(atxmega64a1u) Value(172) + +EnumValue +Enum(avr_mcu) String(avrxmega6) Value(173) + +EnumValue +Enum(avr_mcu) String(atxmega128a3) Value(174) + +EnumValue +Enum(avr_mcu) String(atxmega128d3) Value(175) + +EnumValue +Enum(avr_mcu) String(atxmega192a3) Value(176) + +EnumValue +Enum(avr_mcu) String(atxmega192d3) Value(177) + +EnumValue +Enum(avr_mcu) String(atxmega256a3) Value(178) + +EnumValue +Enum(avr_mcu) String(atxmega256a3b) Value(179) + +EnumValue +Enum(avr_mcu) String(atxmega256a3bu) Value(180) + +EnumValue +Enum(avr_mcu) String(atxmega256d3) Value(181) + +EnumValue +Enum(avr_mcu) String(avrxmega7) Value(182) + +EnumValue +Enum(avr_mcu) String(atxmega128a1) Value(183) + +EnumValue +Enum(avr_mcu) String(atxmega128a1u) Value(184) + +EnumValue +Enum(avr_mcu) String(avr1) Value(185) + +EnumValue +Enum(avr_mcu) String(at90s1200) Value(186) + +EnumValue +Enum(avr_mcu) String(attiny11) Value(187) + +EnumValue +Enum(avr_mcu) String(attiny12) Value(188) + +EnumValue +Enum(avr_mcu) String(attiny15) Value(189) + +EnumValue +Enum(avr_mcu) String(attiny28) Value(190) Index: gcc/config/avr/multilib.h =================================================================== --- gcc/config/avr/multilib.h (revision 184156) +++ gcc/config/avr/multilib.h (working copy) @@ -44,19 +44,24 @@ static const char* const avr_multilib_ra "avr25/tiny-stack mmcu=attiny261;", "avr25/tiny-stack mmcu=attiny261a;", - ". !mmcu=avr2 !mmcu=avr25 !mmcu=avr3 !mmcu=avr31 !mmcu=avr35 !mmcu=avr4 !mmcu=avr5 !mmcu=avr51 !mmcu=avr6 !mtiny-stack !mmcu=at90s2313 !mmcu=at90s2323 !mmcu=at90s2333 !mmcu=at90s2343 !mmcu=attiny22 !mmcu=attiny26 !mmcu=at90s4433 !mmcu=attiny13 !mmcu=attiny13a !mmcu=attiny2313 !mmcu=attiny2313a !mmcu=attiny24 !mmcu=attiny24a !mmcu=attiny25 !mmcu=attiny261 !mmcu=attiny261a;", - "avr2 mmcu=avr2 !mmcu=avr25 !mmcu=avr3 !mmcu=avr31 !mmcu=avr35 !mmcu=avr4 !mmcu=avr5 !mmcu=avr51 !mmcu=avr6 !mtiny-stack;", - "avr25 !mmcu=avr2 mmcu=avr25 !mmcu=avr3 !mmcu=avr31 !mmcu=avr35 !mmcu=avr4 !mmcu=avr5 !mmcu=avr51 !mmcu=avr6 !mtiny-stack;", - "avr3 !mmcu=avr2 !mmcu=avr25 mmcu=avr3 !mmcu=avr31 !mmcu=avr35 !mmcu=avr4 !mmcu=avr5 !mmcu=avr51 !mmcu=avr6;", - "avr31 !mmcu=avr2 !mmcu=avr25 !mmcu=avr3 mmcu=avr31 !mmcu=avr35 !mmcu=avr4 !mmcu=avr5 !mmcu=avr51 !mmcu=avr6;", - "avr35 !mmcu=avr2 !mmcu=avr25 !mmcu=avr3 !mmcu=avr31 mmcu=avr35 !mmcu=avr4 !mmcu=avr5 !mmcu=avr51 !mmcu=avr6;", - "avr4 !mmcu=avr2 !mmcu=avr25 !mmcu=avr3 !mmcu=avr31 !mmcu=avr35 mmcu=avr4 !mmcu=avr5 !mmcu=avr51 !mmcu=avr6;", - "avr5 !mmcu=avr2 !mmcu=avr25 !mmcu=avr3 !mmcu=avr31 !mmcu=avr35 !mmcu=avr4 mmcu=avr5 !mmcu=avr51 !mmcu=avr6;", - "avr51 !mmcu=avr2 !mmcu=avr25 !mmcu=avr3 !mmcu=avr31 !mmcu=avr35 !mmcu=avr4 !mmcu=avr5 mmcu=avr51 !mmcu=avr6;", - "avr6 !mmcu=avr2 !mmcu=avr25 !mmcu=avr3 !mmcu=avr31 !mmcu=avr35 !mmcu=avr4 !mmcu=avr5 !mmcu=avr51 mmcu=avr6;", - "tiny-stack !mmcu=avr2 !mmcu=avr25 !mmcu=avr3 !mmcu=avr31 !mmcu=avr35 !mmcu=avr4 !mmcu=avr5 !mmcu=avr51 !mmcu=avr6 mtiny-stack;", - "avr2/tiny-stack mmcu=avr2 !mmcu=avr25 !mmcu=avr3 !mmcu=avr31 !mmcu=avr35 !mmcu=avr4 !mmcu=avr5 !mmcu=avr51 !mmcu=avr6 mtiny-stack;", - "avr25/tiny-stack !mmcu=avr2 mmcu=avr25 !mmcu=avr3 !mmcu=avr31 !mmcu=avr35 !mmcu=avr4 !mmcu=avr5 !mmcu=avr51 !mmcu=avr6 mtiny-stack;", + ". !mmcu=avr2 !mmcu=avr25 !mmcu=avr3 !mmcu=avr31 !mmcu=avr35 !mmcu=avr4 !mmcu=avr5 !mmcu=avr51 !mmcu=avr6 !mmcu=avrxmega2 !mmcu=avrxmega4 !mmcu=avrxmega5 !mmcu=avrxmega6 !mmcu=avrxmega7 !mtiny-stack !mmcu=at90s2313 !mmcu=at90s2323 !mmcu=at90s2333 !mmcu=at90s2343 !mmcu=attiny22 !mmcu=attiny26 !mmcu=at90s4433 !mmcu=attiny13 !mmcu=attiny13a !mmcu=attiny2313 !mmcu=attiny2313a !mmcu=attiny24 !mmcu=attiny24a !mmcu=attiny25 !mmcu=attiny261 !mmcu=attiny261a;", + "avr2 mmcu=avr2 !mmcu=avr25 !mmcu=avr3 !mmcu=avr31 !mmcu=avr35 !mmcu=avr4 !mmcu=avr5 !mmcu=avr51 !mmcu=avr6 !mmcu=avrxmega2 !mmcu=avrxmega4 !mmcu=avrxmega5 !mmcu=avrxmega6 !mmcu=avrxmega7 !mtiny-stack;", + "avr25 !mmcu=avr2 mmcu=avr25 !mmcu=avr3 !mmcu=avr31 !mmcu=avr35 !mmcu=avr4 !mmcu=avr5 !mmcu=avr51 !mmcu=avr6 !mmcu=avrxmega2 !mmcu=avrxmega4 !mmcu=avrxmega5 !mmcu=avrxmega6 !mmcu=avrxmega7 !mtiny-stack;", + "avr3 !mmcu=avr2 !mmcu=avr25 mmcu=avr3 !mmcu=avr31 !mmcu=avr35 !mmcu=avr4 !mmcu=avr5 !mmcu=avr51 !mmcu=avr6 !mmcu=avrxmega2 !mmcu=avrxmega4 !mmcu=avrxmega5 !mmcu=avrxmega6 !mmcu=avrxmega7;", + "avr31 !mmcu=avr2 !mmcu=avr25 !mmcu=avr3 mmcu=avr31 !mmcu=avr35 !mmcu=avr4 !mmcu=avr5 !mmcu=avr51 !mmcu=avr6 !mmcu=avrxmega2 !mmcu=avrxmega4 !mmcu=avrxmega5 !mmcu=avrxmega6 !mmcu=avrxmega7;", + "avr35 !mmcu=avr2 !mmcu=avr25 !mmcu=avr3 !mmcu=avr31 mmcu=avr35 !mmcu=avr4 !mmcu=avr5 !mmcu=avr51 !mmcu=avr6 !mmcu=avrxmega2 !mmcu=avrxmega4 !mmcu=avrxmega5 !mmcu=avrxmega6 !mmcu=avrxmega7;", + "avr4 !mmcu=avr2 !mmcu=avr25 !mmcu=avr3 !mmcu=avr31 !mmcu=avr35 mmcu=avr4 !mmcu=avr5 !mmcu=avr51 !mmcu=avr6 !mmcu=avrxmega2 !mmcu=avrxmega4 !mmcu=avrxmega5 !mmcu=avrxmega6 !mmcu=avrxmega7;", + "avr5 !mmcu=avr2 !mmcu=avr25 !mmcu=avr3 !mmcu=avr31 !mmcu=avr35 !mmcu=avr4 mmcu=avr5 !mmcu=avr51 !mmcu=avr6 !mmcu=avrxmega2 !mmcu=avrxmega4 !mmcu=avrxmega5 !mmcu=avrxmega6 !mmcu=avrxmega7;", + "avr51 !mmcu=avr2 !mmcu=avr25 !mmcu=avr3 !mmcu=avr31 !mmcu=avr35 !mmcu=avr4 !mmcu=avr5 mmcu=avr51 !mmcu=avr6 !mmcu=avrxmega2 !mmcu=avrxmega4 !mmcu=avrxmega5 !mmcu=avrxmega6 !mmcu=avrxmega7;", + "avr6 !mmcu=avr2 !mmcu=avr25 !mmcu=avr3 !mmcu=avr31 !mmcu=avr35 !mmcu=avr4 !mmcu=avr5 !mmcu=avr51 mmcu=avr6 !mmcu=avrxmega2 !mmcu=avrxmega4 !mmcu=avrxmega5 !mmcu=avrxmega6 !mmcu=avrxmega7;", + "avrxmega2 !mmcu=avr2 !mmcu=avr25 !mmcu=avr3 !mmcu=avr31 !mmcu=avr35 !mmcu=avr4 !mmcu=avr5 !mmcu=avr51 !mmcu=avr6 mmcu=avrxmega2 !mmcu=avrxmega4 !mmcu=avrxmega5 !mmcu=avrxmega6 !mmcu=avrxmega7;", + "avrxmega4 !mmcu=avr2 !mmcu=avr25 !mmcu=avr3 !mmcu=avr31 !mmcu=avr35 !mmcu=avr4 !mmcu=avr5 !mmcu=avr51 !mmcu=avr6 !mmcu=avrxmega2 mmcu=avrxmega4 !mmcu=avrxmega5 !mmcu=avrxmega6 !mmcu=avrxmega7;", + "avrxmega5 !mmcu=avr2 !mmcu=avr25 !mmcu=avr3 !mmcu=avr31 !mmcu=avr35 !mmcu=avr4 !mmcu=avr5 !mmcu=avr51 !mmcu=avr6 !mmcu=avrxmega2 !mmcu=avrxmega4 mmcu=avrxmega5 !mmcu=avrxmega6 !mmcu=avrxmega7;", + "avrxmega6 !mmcu=avr2 !mmcu=avr25 !mmcu=avr3 !mmcu=avr31 !mmcu=avr35 !mmcu=avr4 !mmcu=avr5 !mmcu=avr51 !mmcu=avr6 !mmcu=avrxmega2 !mmcu=avrxmega4 !mmcu=avrxmega5 mmcu=avrxmega6 !mmcu=avrxmega7;", + "avrxmega7 !mmcu=avr2 !mmcu=avr25 !mmcu=avr3 !mmcu=avr31 !mmcu=avr35 !mmcu=avr4 !mmcu=avr5 !mmcu=avr51 !mmcu=avr6 !mmcu=avrxmega2 !mmcu=avrxmega4 !mmcu=avrxmega5 !mmcu=avrxmega6 mmcu=avrxmega7;", + "tiny-stack !mmcu=avr2 !mmcu=avr25 !mmcu=avr3 !mmcu=avr31 !mmcu=avr35 !mmcu=avr4 !mmcu=avr5 !mmcu=avr51 !mmcu=avr6 !mmcu=avrxmega2 !mmcu=avrxmega4 !mmcu=avrxmega5 !mmcu=avrxmega6 !mmcu=avrxmega7 mtiny-stack;", + "avr2/tiny-stack mmcu=avr2 !mmcu=avr25 !mmcu=avr3 !mmcu=avr31 !mmcu=avr35 !mmcu=avr4 !mmcu=avr5 !mmcu=avr51 !mmcu=avr6 !mmcu=avrxmega2 !mmcu=avrxmega4 !mmcu=avrxmega5 !mmcu=avrxmega6 !mmcu=avrxmega7 mtiny-stack;", + "avr25/tiny-stack !mmcu=avr2 mmcu=avr25 !mmcu=avr3 !mmcu=avr31 !mmcu=avr35 !mmcu=avr4 !mmcu=avr5 !mmcu=avr51 !mmcu=avr6 !mmcu=avrxmega2 !mmcu=avrxmega4 !mmcu=avrxmega5 !mmcu=avrxmega6 !mmcu=avrxmega7 mtiny-stack;", NULL }; Index: gcc/config/avr/avr.c =================================================================== --- gcc/config/avr/avr.c (revision 184156) +++ gcc/config/avr/avr.c (working copy) @@ -112,6 +112,12 @@ typedef struct /* SREG: The pocessor status */ int sreg; + /* RAMPX, RAMPY, RAMPD and CCP of XMEGA */ + int ccp; + int rampd; + int rampx; + int rampy; + /* RAMPZ: The high byte of 24-bit address used with ELPM */ int rampz; @@ -177,8 +183,18 @@ rtx zero_reg_rtx; extern GTY(()) rtx all_regs_rtx[32]; rtx all_regs_rtx[32]; -/* RAMPZ special function register */ +/* SREG, the processor status */ +extern GTY(()) rtx sreg_rtx; +rtx sreg_rtx; + +/* RAMP* special function registers */ +extern GTY(()) rtx rampd_rtx; +extern GTY(()) rtx rampx_rtx; +extern GTY(()) rtx rampy_rtx; extern GTY(()) rtx rampz_rtx; +rtx rampd_rtx; +rtx rampx_rtx; +rtx rampy_rtx; rtx rampz_rtx; /* RTX containing the strings "" and "e", respectively */ @@ -421,6 +437,11 @@ avr_option_override (void) /* RAMPZ: Address' high part when loading via ELPM */ avr_addr.rampz = 0x3B + avr_current_arch->sfr_offset; + avr_addr.rampy = 0x3A + avr_current_arch->sfr_offset; + avr_addr.rampx = 0x39 + avr_current_arch->sfr_offset; + avr_addr.rampd = 0x38 + avr_current_arch->sfr_offset; + avr_addr.ccp = 0x34 + avr_current_arch->sfr_offset; + /* SP: Stack Pointer (SP_H:SP_L) */ avr_addr.sp_l = 0x3D + avr_current_arch->sfr_offset; avr_addr.sp_h = avr_addr.sp_l + 1; @@ -447,13 +468,6 @@ avr_init_expanders (void) { int regno; - static bool done = false; - - if (done) - return; - else - done = true; - for (regno = 0; regno < 32; regno ++) all_regs_rtx[regno] = gen_rtx_REG (QImode, regno); @@ -463,6 +477,10 @@ avr_init_expanders (void) lpm_addr_reg_rtx = gen_rtx_REG (HImode, REG_Z); + sreg_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.sreg)); + rampd_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampd)); + rampx_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampx)); + rampy_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampy)); rampz_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampz)); xstring_empty = gen_rtx_CONST_STRING (VOIDmode, ""); @@ -900,6 +918,35 @@ emit_push_byte (unsigned regno, bool fra cfun->machine->stack_usage++; } + +/* Helper for expand_prologue. Emit a push of a SFR via tmp_reg. + SFR is a MEM representing the memory location of the SFR. + If CLR_P then clear the SFR after the push using zero_reg. */ + +static void +emit_push_sfr (rtx sfr, bool frame_related_p, bool clr_p) +{ + rtx insn; + + gcc_assert (MEM_P (sfr)); + + /* IN __tmp_reg__, IO(SFR) */ + insn = emit_move_insn (tmp_reg_rtx, sfr); + if (frame_related_p) + RTX_FRAME_RELATED_P (insn) = 1; + + /* PUSH __tmp_reg__ */ + emit_push_byte (TMP_REGNO, frame_related_p); + + if (clr_p) + { + /* OUT IO(SFR), __zero_reg__ */ + insn = emit_move_insn (sfr, const0_rtx); + if (frame_related_p) + RTX_FRAME_RELATED_P (insn) = 1; + } +} + static void avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set) { @@ -1058,7 +1105,7 @@ avr_prologue_setup_frame (HOST_WIDE_INT changed the CFA to the frame pointer this operation need not be annotated if frame pointer is needed. */ - if (AVR_HAVE_8BIT_SP) + if (AVR_HAVE_8BIT_SP || AVR_XMEGA) { insn = emit_move_insn (stack_pointer_rtx, fp); } @@ -1163,26 +1210,42 @@ expand_prologue (void) /* Push SREG. */ /* ??? There's no dwarf2 column reserved for SREG. */ - emit_move_insn (tmp_reg_rtx, - gen_rtx_MEM (QImode, GEN_INT (avr_addr.sreg))); - emit_push_byte (TMP_REGNO, false); + emit_push_sfr (sreg_rtx, false, false /* clr */); - /* Push RAMPZ. */ - /* ??? There's no dwarf2 column reserved for RAMPZ. */ - if (AVR_HAVE_RAMPZ - && TEST_HARD_REG_BIT (set, REG_Z) - && TEST_HARD_REG_BIT (set, REG_Z + 1)) - { - emit_move_insn (tmp_reg_rtx, rampz_rtx); - emit_push_byte (TMP_REGNO, false); - } - /* Clear zero reg. */ emit_move_insn (zero_reg_rtx, const0_rtx); /* Prevent any attempt to delete the setting of ZERO_REG! */ emit_use (zero_reg_rtx); - } + + /* Push and clear RAMPD/X/Y/Z if present and low-part register is used. + ??? There are no dwarf2 columns reserved for RAMPD/X/Y/Z. */ + + if (AVR_HAVE_RAMPD) + emit_push_sfr (rampd_rtx, false /* frame-related */, true /* clr */); + + if (AVR_HAVE_RAMPX + && TEST_HARD_REG_BIT (set, REG_X) + && TEST_HARD_REG_BIT (set, REG_X + 1)) + { + emit_push_sfr (rampx_rtx, false /* frame-related */, true /* clr */); + } + + if (AVR_HAVE_RAMPY + && (frame_pointer_needed + || (TEST_HARD_REG_BIT (set, REG_Y) + && TEST_HARD_REG_BIT (set, REG_Y + 1)))) + { + emit_push_sfr (rampy_rtx, false /* frame-related */, true /* clr */); + } + + if (AVR_HAVE_RAMPZ + && TEST_HARD_REG_BIT (set, REG_Z) + && TEST_HARD_REG_BIT (set, REG_Z + 1)) + { + emit_push_sfr (rampz_rtx, false /* frame-related */, true /* clr */); + } + } /* is_interrupt is_signal */ avr_prologue_setup_frame (size, set); @@ -1341,7 +1404,7 @@ expand_epilogue (bool sibcall_p) /* Copy to stack pointer. */ - if (AVR_HAVE_8BIT_SP) + if (AVR_HAVE_8BIT_SP || AVR_XMEGA) { emit_move_insn (stack_pointer_rtx, fp); } @@ -1404,9 +1467,27 @@ expand_epilogue (bool sibcall_p) if (isr_p) { - /* Restore RAMPZ using tmp reg as scratch. */ + /* Restore RAMPZ/Y/X/D using tmp_reg as scratch. + The conditions to restore them must be tha same as in prologue. */ - if (AVR_HAVE_RAMPZ + if (AVR_HAVE_RAMPX + && TEST_HARD_REG_BIT (set, REG_X) + && TEST_HARD_REG_BIT (set, REG_X + 1)) + { + emit_pop_byte (TMP_REGNO); + emit_move_insn (rampx_rtx, tmp_reg_rtx); + } + + if (AVR_HAVE_RAMPY + && (frame_pointer_needed + || (TEST_HARD_REG_BIT (set, REG_Y) + && TEST_HARD_REG_BIT (set, REG_Y + 1)))) + { + emit_pop_byte (TMP_REGNO); + emit_move_insn (rampy_rtx, tmp_reg_rtx); + } + + if (AVR_HAVE_RAMPZ && TEST_HARD_REG_BIT (set, REG_Z) && TEST_HARD_REG_BIT (set, REG_Z + 1)) { @@ -1414,11 +1495,16 @@ expand_epilogue (bool sibcall_p) emit_move_insn (rampz_rtx, tmp_reg_rtx); } - /* Restore SREG using tmp reg as scratch. */ + if (AVR_HAVE_RAMPD) + { + emit_pop_byte (TMP_REGNO); + emit_move_insn (rampd_rtx, tmp_reg_rtx); + } + + /* Restore SREG using tmp_reg as scratch. */ emit_pop_byte (TMP_REGNO); - emit_move_insn (gen_rtx_MEM (QImode, GEN_INT (avr_addr.sreg)), - tmp_reg_rtx); + emit_move_insn (sreg_rtx, tmp_reg_rtx); /* Restore tmp REG. */ emit_pop_byte (TMP_REGNO); @@ -1900,7 +1986,16 @@ avr_print_operand (FILE *file, rtx x, in else if (low_io_address_operand (x, VOIDmode) || high_io_address_operand (x, VOIDmode)) { - if (ival == avr_addr.rampz) fprintf (file, "__RAMPZ__"); + if (AVR_HAVE_RAMPZ && ival == avr_addr.rampz) + fprintf (file, "__RAMPZ__"); + else if (AVR_HAVE_RAMPY && ival == avr_addr.rampy) + fprintf (file, "__RAMPY__"); + else if (AVR_HAVE_RAMPX && ival == avr_addr.rampx) + fprintf (file, "__RAMPX__"); + else if (AVR_HAVE_RAMPD && ival == avr_addr.rampd) + fprintf (file, "__RAMPD__"); + else if (AVR_XMEGA && ival == avr_addr.ccp) + fprintf (file, "__CCP__"); else if (ival == avr_addr.sreg) fprintf (file, "__SREG__"); else if (ival == avr_addr.sp_l) fprintf (file, "__SP_L__"); else if (ival == avr_addr.sp_h) fprintf (file, "__SP_H__"); @@ -2898,6 +2993,10 @@ output_movhi (rtx insn, rtx xop[], int * { if (AVR_HAVE_8BIT_SP) return avr_asm_len ("out __SP_L__,%A1", xop, plen, -1); + + if (AVR_XMEGA) + return avr_asm_len ("out __SP_L__,%A1" CR_TAB + "out __SP_H__,%B1", xop, plen, -2); /* Use simple load of SP if no interrupts are used. */ @@ -3872,6 +3971,118 @@ out_movqi_mr_r (rtx insn, rtx op[], int return avr_asm_len ("st %0,%1", op, plen, -1); } + +/* Helper for the next function for XMEGA. It does the same + but with low byte first. */ + +static const char* +avr_out_movhi_mr_r_xmega (rtx insn, rtx op[], int *plen) +{ + rtx dest = op[0]; + rtx src = op[1]; + rtx base = XEXP (dest, 0); + int reg_base = true_regnum (base); + int reg_src = true_regnum (src); + /* "volatile" forces writing high byte first, even if less efficient, + for correct operation with 16-bit I/O registers. */ + int mem_volatile_p = MEM_VOLATILE_P (dest); + + if (CONSTANT_ADDRESS_P (base)) + return optimize > 0 && io_address_operand (base, HImode) + ? avr_asm_len ("out %i0,%A1" CR_TAB + "out %i0+1,%B1", op, plen, -2) + + : avr_asm_len ("sts %m0,%A1" CR_TAB + "sts %m0+1,%B1", op, plen, -4); + + if (reg_base > 0) + { + if (reg_base != REG_X) + return avr_asm_len ("st %0,%A1" CR_TAB + "std %0+1,%B1", op, plen, -2); + + if (reg_src == REG_X) + /* "st X+,r26" and "st -X,r26" are undefined. */ + avr_asm_len ("mov __tmp_reg__,r27" CR_TAB + "st X,r26" CR_TAB + "adiw r26,1" CR_TAB + "st X,__tmp_reg__", op, plen, -4); + else + avr_asm_len ("st X+,%A1" CR_TAB + "st X,%B1", op, plen, -2); + + return reg_unused_after (insn, src) + ? "" + : avr_asm_len ("sbiw r26,1", op, plen, 1); + } + else if (GET_CODE (base) == PLUS) + { + int disp = INTVAL (XEXP (base, 1)); + reg_base = REGNO (XEXP (base, 0)); + if (disp > MAX_LD_OFFSET (GET_MODE (dest))) + { + if (reg_base != REG_Y) + fatal_insn ("incorrect insn:",insn); + + return disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)) + ? avr_asm_len ("adiw r28,%o0-62" CR_TAB + "std Y+62,%A1" CR_TAB + "std Y+63,%B1" CR_TAB + "sbiw r28,%o0-62", op, plen, -4) + + : avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB + "sbci r29,hi8(-%o0)" CR_TAB + "st Y,%A1" CR_TAB + "std Y+1,%B1" CR_TAB + "subi r28,lo8(%o0)" CR_TAB + "sbci r29,hi8(%o0)", op, plen, -6); + } + + if (reg_base != REG_X) + return avr_asm_len ("std %A0,%A1" CR_TAB + "std %B0,%B1", op, plen, -2); + /* (X + d) = R */ + return reg_src == REG_X + ? avr_asm_len ("mov __tmp_reg__,r26" CR_TAB + "mov __zero_reg__,r27" CR_TAB + "adiw r26,%o0" CR_TAB + "st X+,__tmp_reg__" CR_TAB + "st X,__zero_reg__" CR_TAB + "clr __zero_reg__" CR_TAB + "sbiw r26,%o0+1", op, plen, -7) + + : avr_asm_len ("adiw r26,%o0" CR_TAB + "st X+,%A1" CR_TAB + "st X,%B1" CR_TAB + "sbiw r26,%o0+1", op, plen, -4); + } + else if (GET_CODE (base) == PRE_DEC) /* (--R) */ + { + if (!mem_volatile_p) + return avr_asm_len ("st %0,%B1" CR_TAB + "st %0,%A1", op, plen, -2); + + return REGNO (XEXP (base, 0)) == REG_X + ? avr_asm_len ("sbiw r26,2" CR_TAB + "st X+,%A1" CR_TAB + "st X,%B1" CR_TAB + "sbiw r26,1", op, plen, -4) + + : avr_asm_len ("sbiw %r0,2" CR_TAB + "st %p0,%A1" CR_TAB + "std %p0+1,%B1", op, plen, -3); + } + else if (GET_CODE (base) == POST_INC) /* (R++) */ + { + return avr_asm_len ("st %0,%A1" CR_TAB + "st %0,%B1", op, plen, -2); + + } + fatal_insn ("unknown move insn:",insn); + return ""; +} + + static const char* out_movhi_mr_r (rtx insn, rtx op[], int *plen) { @@ -3884,6 +4095,9 @@ out_movhi_mr_r (rtx insn, rtx op[], int for correct operation with 16-bit I/O registers. */ int mem_volatile_p = MEM_VOLATILE_P (dest); + if (AVR_XMEGA) + return avr_out_movhi_mr_r_xmega (insn, op, plen); + if (CONSTANT_ADDRESS_P (base)) return optimize > 0 && io_address_operand (base, HImode) ? avr_asm_len ("out %i0+1,%B1" CR_TAB @@ -7329,7 +7543,16 @@ avr_file_start (void) fprintf (asm_out_file, "__SP_L__ = 0x%02x\n", avr_addr.sp_l - sfr_offset); fprintf (asm_out_file, "__SREG__ = 0x%02x\n", avr_addr.sreg - sfr_offset); - fprintf (asm_out_file, "__RAMPZ__ = 0x%02x\n", avr_addr.rampz - sfr_offset); + if (AVR_HAVE_RAMPZ) + fprintf (asm_out_file, "__RAMPZ__ = 0x%02x\n", avr_addr.rampz - sfr_offset); + if (AVR_HAVE_RAMPY) + fprintf (asm_out_file, "__RAMPY__ = 0x%02x\n", avr_addr.rampy - sfr_offset); + if (AVR_HAVE_RAMPX) + fprintf (asm_out_file, "__RAMPX__ = 0x%02x\n", avr_addr.rampx - sfr_offset); + if (AVR_HAVE_RAMPD) + fprintf (asm_out_file, "__RAMPD__ = 0x%02x\n", avr_addr.rampd - sfr_offset); + if (AVR_XMEGA) + fprintf (asm_out_file, "__CCP__ = 0x%02x\n", avr_addr.ccp - sfr_offset); fprintf (asm_out_file, "__tmp_reg__ = %d\n", TMP_REGNO); fprintf (asm_out_file, "__zero_reg__ = %d\n", ZERO_REGNO); } Index: gcc/config/avr/avr.h =================================================================== --- gcc/config/avr/avr.h (revision 184156) +++ gcc/config/avr/avr.h (working copy) @@ -46,11 +46,12 @@ struct base_arch_s /* Core have 'EICALL' and 'EIJMP' instructions. */ int have_eijmp_eicall; - /* Reserved for xmega architecture. */ - int reserved; + /* This is an XMEGA core. */ + int xmega_p; - /* Reserved for xmega architecture. */ - int reserved2; + /* This core has the RAMPD special function register + and thus also the RAMPX, RAMPY and RAMPZ registers. */ + int have_rampd; /* Default start of data section address for architecture. */ int default_data_section_start; @@ -62,6 +63,7 @@ struct base_arch_s /* Number of 64k segments in the flash. */ int n_segments; + /* Architecture id to built-in define __AVR_ARCH__ (NULL -> no macro) */ const char *const macro; /* Architecture name. */ @@ -83,7 +85,12 @@ enum avr_arch ARCH_AVR4, ARCH_AVR5, ARCH_AVR51, - ARCH_AVR6 + ARCH_AVR6, + ARCH_AVRXMEGA2, + ARCH_AVRXMEGA4, + ARCH_AVRXMEGA5, + ARCH_AVRXMEGA6, + ARCH_AVRXMEGA7 }; struct mcu_type_s { @@ -175,13 +182,19 @@ enum #define AVR_HAVE_LPMX (avr_current_arch->have_movw_lpmx) #define AVR_HAVE_ELPM (avr_current_arch->have_elpm) #define AVR_HAVE_ELPMX (avr_current_arch->have_elpmx) -#define AVR_HAVE_RAMPZ (avr_current_arch->have_elpm) +#define AVR_HAVE_RAMPD (avr_current_arch->have_rampd) +#define AVR_HAVE_RAMPX (avr_current_arch->have_rampd) +#define AVR_HAVE_RAMPY (avr_current_arch->have_rampd) +#define AVR_HAVE_RAMPZ (avr_current_arch->have_elpm \ + || avr_current_arch->have_rampd) #define AVR_HAVE_EIJMP_EICALL (avr_current_arch->have_eijmp_eicall) #define AVR_HAVE_8BIT_SP (avr_current_device->short_sp || TARGET_TINY_STACK) #define AVR_2_BYTE_PC (!AVR_HAVE_EIJMP_EICALL) #define AVR_3_BYTE_PC (AVR_HAVE_EIJMP_EICALL) +#define AVR_XMEGA (avr_current_arch->xmega_p) + #define BITS_BIG_ENDIAN 0 #define BYTES_BIG_ENDIAN 0 #define WORDS_BIG_ENDIAN 0