avr-gcc-list
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[avr-gcc-list] C++ for AVR


From: Peter Jansen
Subject: [avr-gcc-list] C++ for AVR
Date: Mon, 04 Feb 2002 17:03:56 +1100

Hi All,

Attached is a start on putting C++ support into gcc for the avr (for the
atmega128 at the moment).

This requires a new gcrt1.S, changes the the linker script and changes
to gcc (libgcc.S) etc.

Attached are a linker script for the ATmega128 with some changes, a new
gcrt1.S and a patch for gcc. I have not done the mods for the exit
function yet and have discarded the destructor section using the linker
script as Im assuming destructors are not needed for an embedded AVR,
athough I will include someway of putting this in latter.

I still have the destructor functions (not the tables) in the code which
I can see how to get rid of at this stage.

Have a look and see what you think any comments welcome.

Regards

-- 
Peter Jansen
Smart Container
Level 1, NIC Building
Eveleigh
NSW       1430
AUSTRALIA
diff -c3pr gcc-3.0.2-patch-0.1/gcc/ChangeLog gcc-3.0.2-patch-0.4/gcc/ChangeLog
*** gcc-3.0.2-patch-0.1/gcc/ChangeLog   Wed Nov  7 14:57:55 2001
--- gcc-3.0.2-patch-0.4/gcc/ChangeLog   Thu Jan 10 09:57:38 2002
***************
*** 1,7 ****
  2001-11-07 Peter Jansen <address@hidden>
  
        * gcc/config/avr/avr.c - added mega128 to list of avr5 types
!       * gcc/config/avr/avr/h - Ditto
  
  
  2001-10-23  Release Manager
--- 1,9 ----
  2001-11-07 Peter Jansen <address@hidden>
  
        * gcc/config/avr/avr.c - added mega128 to list of avr5 types
!       * gcc/config/avr/avr.h - Ditto, Added C++ constructor stuff
!       * gcc/config/avr/libgcc.S - added C++ constructor functions
!       * gcc/config/avr/t-avr - added C++ object compile
  
  
  2001-10-23  Release Manager
diff -c3pr gcc-3.0.2-patch-0.1/gcc/config/avr/avr.h 
gcc-3.0.2-patch-0.4/gcc/config/avr/avr.h
*** gcc-3.0.2-patch-0.1/gcc/config/avr/avr.h    Tue Nov  6 17:59:26 2001
--- gcc-3.0.2-patch-0.4/gcc/config/avr/avr.h    Mon Feb  4 16:10:34 2002
*************** do {                                                            
            \
*** 1981,2003 ****
     scheduling priorities of insns.  */
  
  
! #define TEXT_SECTION_ASM_OP "\t.text"
  /* A C expression whose value is a string containing the assembler
     operation that should precede instructions and read-only data.
     Normally `"\t.text"' is right.  */
  
  #define DATA_SECTION_ASM_OP "\t.data"
  /* A C expression whose value is a string containing the assembler
     operation to identify the following data as writable initialized
     data.  Normally `"\t.data"' is right.  */
  
! #define EXTRA_SECTIONS in_progmem
  /* A list of names for sections other than the standard two, which are
     `in_text' and `in_data'.  You need not define this macro on a
     system with no other sections (that GCC needs to use).  */
  
! #define EXTRA_SECTION_FUNCTIONS                                               
      \
!                                                                             \
  void                                                                        \
  progmem_section (void)                                                        
      \
  {                                                                           \
--- 1981,2065 ----
     scheduling priorities of insns.  */
  
  
! #define TEXT_SECTION_ASM_OP "\t.text\t"
! 
  /* A C expression whose value is a string containing the assembler
     operation that should precede instructions and read-only data.
     Normally `"\t.text"' is right.  */
  
  #define DATA_SECTION_ASM_OP "\t.data"
+ 
  /* A C expression whose value is a string containing the assembler
     operation to identify the following data as writable initialized
     data.  Normally `"\t.data"' is right.  */
  
! #define CONST_SECTION_ASM_OP  "\t.section\t.rodata"
! 
! #define BSS_SECTION_ASM_OP    "\t.section\t.bss"
! 
! /* Define the pseudo-ops used to switch to the .ctors and .dtors sections.
! 
!    Note that we want to give these sections the SHF_WRITE attribute
!    because these sections will actually contain data (i.e. tables of
!    addresses of functions in the current root executable or shared library
!    file) and, in the case of a shared library, the relocatable addresses
!    will have to be properly resolved/relocated (and then written into) by
!    the dynamic linker when it actually attaches the given shared library
!    to the executing process.  (Note that on SVR4, you may wish to use the
!    `-z text' option to the ELF linker, when building a shared library, as
!    an additional check that you are doing everything right.  But if you do
!    use the `-z text' option when building a shared library, you will get
!    errors unless the .ctors and .dtors sections are marked as writable
!    via the SHF_WRITE attribute.)  */
! 
! #define CTORS_SECTION_ASM_OP  "\t.section\t.ctors,\"aw\""
! #define DTORS_SECTION_ASM_OP  "\t.section\t.dtors,\"aw\""
! 
! /* On svr4, we *do* have support for the .init and .fini sections, and we
!    can put stuff in there to be executed before and after `main'.  We let
!    crtstuff.c and other files know this by defining the following symbols.
!    The definitions say how to change sections to the .init and .fini
!    sections.  This is the same for all known svr4 assemblers.  */
! 
! #define INIT_SECTION_ASM_OP   "\t.section\t.init"
! #define FINI_SECTION_ASM_OP   "\t.section\t.fini"
! 
! #define CTORS_SECTION_FUNCTION                                        \
! void                                                          \
! ctors_section ()                                              \
! {                                                             \
!   if (in_section != in_ctors)                                 \
!     {                                                         \
!       fprintf (asm_out_file, "\t.globl\t__do_global_ctors\n");  \
!       fprintf (asm_out_file, "%s\n", CTORS_SECTION_ASM_OP);   \
!       in_section = in_ctors;                                  \
!     }                                                         \
! }
! 
! #define DTORS_SECTION_FUNCTION                                        \
! void                                                          \
! dtors_section ()                                              \
! {                                                             \
!   if (in_section != in_dtors)                                 \
!     {                                                         \
!       fprintf (asm_out_file, "\t.globl\t__do_global_dtors\n");  \
!       fprintf (asm_out_file, "%s\n", DTORS_SECTION_ASM_OP);   \
!       in_section = in_dtors;                                  \
!     }                                                         \
! }
! 
! #define EXTRA_SECTIONS in_progmem, in_ctors, in_dtors
  /* A list of names for sections other than the standard two, which are
     `in_text' and `in_data'.  You need not define this macro on a
     system with no other sections (that GCC needs to use).  */
  
! #undef  EXTRA_SECTION_FUNCTIONS
! #define EXTRA_SECTION_FUNCTIONS \
!       PROGMEM_SECTION_FUNCTION \
!       CTORS_SECTION_FUNCTION \
!       DTORS_SECTION_FUNCTION
! 
! #define PROGMEM_SECTION_FUNCTION                                            \
  void                                                                        \
  progmem_section (void)                                                        
      \
  {                                                                           \
*************** progmem_section (void)                                          
              \
*** 2011,2016 ****
--- 2073,2117 ----
        in_section = in_progmem;                                                
      \
      }                                                                       \
  }
+ 
+ /* This is the pseudo-op used to generate a reference to a specific
+    symbol in some section.  It is only used in machine-specific
+    configuration files, typically only in ASM_OUTPUT_CONSTRUCTOR and
+    ASM_OUTPUT_DESTRUCTOR.  This is the same for all known svr4
+    assemblers, except those in targets that don't use 32-bit pointers.
+    Those should override INT_ASM_OP.  Yes, the name of the macro is
+    misleading.  */
+ 
+ #ifndef INT_ASM_OP
+ #define INT_ASM_OP            "\t.short\t"
+ #endif
+ 
+ 
+ /* A C statement (sans semicolon) to output an
+    element in the table of global constructors.  */
+ #define ASM_OUTPUT_CONSTRUCTOR(FILE, NAME)                    \
+   do                                                          \
+     {                                                         \
+       ctors_section ();                                               \
+       fprintf (FILE, "%spm(", INT_ASM_OP);                            \
+       assemble_name (FILE, NAME);                             \
+       fprintf (FILE, ")\t;; constructor is a word address\n");        \
+     }                                                         \
+   while (0)
+ 
+ /* A C statement (sans semicolon) to output an
+    element in the table of global destructors.  */
+ #define ASM_OUTPUT_DESTRUCTOR(FILE,NAME)                              \
+   do                                                          \
+     {                                                         \
+       dtors_section ();                                       \
+       fprintf (FILE, "%spm(", INT_ASM_OP);                            \
+       assemble_name (FILE, NAME);                                     \
+       fprintf (FILE, ")\t;; destructor is a word address\n");         \
+     }                                                         \
+   while (0)
+ 
+ 
  /* `EXTRA_SECTION_FUNCTIONS'
     One or more functions to be defined in `varasm.c'.  These
     functions should do jobs analogous to those of `text_section' and
*************** progmem_section (void)                                          
              \
*** 2244,2249 ****
--- 2345,2365 ----
     These macros are provided by `real.h' for writing the definitions of
     `ASM_OUTPUT_DOUBLE' and the like:  */
  
+ #define ASM_OUTPUT_BSS(STREAM, DECL, NAME, SIZE, ROUNDED)                \
+     asm_output_bss(STREAM, DECL, NAME, SIZE, ROUNDED)
+ 
+ /* A C statement (sans semicolon) to output to the stdio stream
+    STREAM the assembler definition of a bss named NAME whose
+    size is SIZE bytes.  The variable ROUNDED is the size rounded up
+    to whatever alignment the caller wants.
+ 
+    Use the expression `assemble_name (STREAM, NAME)' to output the
+    name itself; before and after that, output the additional
+    assembler syntax for defining the name, and a newline.
+ 
+    This macro controls how the assembler definitions of uninitialized
+    global variables are output.  */
+ 
  #define ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED)                        
   \
  do {                                                                     \
       fputs ("\t.comm ", (STREAM));                                       \
diff -c3pr gcc-3.0.2-patch-0.1/gcc/config/avr/libgcc.S 
gcc-3.0.2-patch-0.4/gcc/config/avr/libgcc.S
*** gcc-3.0.2-patch-0.1/gcc/config/avr/libgcc.S Sun Apr  1 02:36:08 2001
--- gcc-3.0.2-patch-0.4/gcc/config/avr/libgcc.S Mon Feb  4 15:28:41 2002
*************** Boston, MA 02111-1307, USA.  */
*** 31,36 ****
--- 31,37 ----
  #define __SREG__ 0x3f
  #define __SP_H__ 0x3e
  #define __SP_L__ 0x3d
+ #define __RAMPZ__ 0x3b
  
  /* Most of the functions here are called directly from avr.md
     patterns, instead of using the standard libcall mechanisms.
*************** __mulqi3_loop:
*** 75,90 ****
        add     r_res,r_arg2
        add     r_arg2,r_arg2   ; shift multiplicand
        breq    __mulqi3_exit   ; while multiplicand != 0
!       lsr     r_arg1          ; 
        brne    __mulqi3_loop   ; exit if multiplier = 0
! __mulqi3_exit:        
        mov     r_arg1,r_res    ; result to return register
        ret
  
! #undef r_arg2  
! #undef r_arg1  
! #undef r_res   
!       
  .endfunc
  #endif        /* defined (L_mulqi3) */
  
--- 76,91 ----
        add     r_res,r_arg2
        add     r_arg2,r_arg2   ; shift multiplicand
        breq    __mulqi3_exit   ; while multiplicand != 0
!       lsr     r_arg1          ;
        brne    __mulqi3_loop   ; exit if multiplier = 0
! __mulqi3_exit:
        mov     r_arg1,r_res    ; result to return register
        ret
  
! #undef r_arg2
! #undef r_arg1
! #undef r_res
! 
  .endfunc
  #endif        /* defined (L_mulqi3) */
  
*************** __mulhi3_loop:
*** 133,139 ****
        rjmp    __mulhi3_skip1
        add     r_resL,r_arg2L  ; result + multiplicand
        adc     r_resH,r_arg2H
! __mulhi3_skip1:       
        add     r_arg2L,r_arg2L ; shift multiplicand
        adc     r_arg2H,r_arg2H
  
--- 134,140 ----
        rjmp    __mulhi3_skip1
        add     r_resL,r_arg2L  ; result + multiplicand
        adc     r_resH,r_arg2H
! __mulhi3_skip1:
        add     r_arg2L,r_arg2L ; shift multiplicand
        adc     r_arg2H,r_arg2H
  
*************** __mulhi3_exit:
*** 154,161 ****
  #undef r_arg1H
  #undef r_arg2L
  #undef r_arg2H
! #undef r_resL         
! #undef r_resH 
  
  .endfunc
  #endif /* defined (L_mulhi3) */
--- 155,162 ----
  #undef r_arg1H
  #undef r_arg2L
  #undef r_arg2H
! #undef r_resL
! #undef r_resH
  
  .endfunc
  #endif /* defined (L_mulhi3) */
*************** __umulhisi3:
*** 204,219 ****
  
  
  #define       r_arg2L  r18            /* multiplicand Low */
! #define       r_arg2H  r19    
  #define       r_arg2HL r20
  #define       r_arg2HH r21            /* multiplicand High */
!       
  #define r_resL         r26            /* result Low */
  #define r_resH   r27
  #define r_resHL        r30
  #define r_resHH  r31          /* result High */
  
!       
        .global __mulsi3
        .func   __mulsi3
  __mulsi3:
--- 205,220 ----
  
  
  #define       r_arg2L  r18            /* multiplicand Low */
! #define       r_arg2H  r19
  #define       r_arg2HL r20
  #define       r_arg2HH r21            /* multiplicand High */
! 
  #define r_resL         r26            /* result Low */
  #define r_resH   r27
  #define r_resHL        r30
  #define r_resHH  r31          /* result High */
  
! 
        .global __mulsi3
        .func   __mulsi3
  __mulsi3:
*************** __mulsi3_skip1:
*** 266,272 ****
        adc     r_arg2H,r_arg2H
        adc     r_arg2HL,r_arg2HL
        adc     r_arg2HH,r_arg2HH
!       
        lsr     r_arg1HH        ; gets LSB of multiplier
        ror     r_arg1HL
        ror     r_arg1H
--- 267,273 ----
        adc     r_arg2H,r_arg2H
        adc     r_arg2HL,r_arg2HL
        adc     r_arg2HH,r_arg2HH
! 
        lsr     r_arg1HH        ; gets LSB of multiplier
        ror     r_arg1HL
        ror     r_arg1H
*************** __mulsi3_exit:
*** 282,306 ****
        mov     r_arg1L,r_resL
        ret
  #endif /* !defined (__AVR_ENHANCED__) */
! #undef r_arg1L 
! #undef r_arg1H 
  #undef r_arg1HL
  #undef r_arg1HH
!              
!              
! #undef r_arg2L 
! #undef r_arg2H 
  #undef r_arg2HL
  #undef r_arg2HH
!              
! #undef r_resL  
! #undef r_resH  
! #undef r_resHL 
! #undef r_resHH 
  
  .endfunc
  #endif /* defined (L_mulsi3) */
!       
  /*******************************************************
         Division 8 / 8 => (result + remainder)
  *******************************************************/
--- 283,307 ----
        mov     r_arg1L,r_resL
        ret
  #endif /* !defined (__AVR_ENHANCED__) */
! #undef r_arg1L
! #undef r_arg1H
  #undef r_arg1HL
  #undef r_arg1HH
! 
! 
! #undef r_arg2L
! #undef r_arg2H
  #undef r_arg2HL
  #undef r_arg2HH
! 
! #undef r_resL
! #undef r_resH
! #undef r_resHL
! #undef r_resHH
  
  .endfunc
  #endif /* defined (L_mulsi3) */
! 
  /*******************************************************
         Division 8 / 8 => (result + remainder)
  *******************************************************/
*************** __udivmodqi4_ep:
*** 325,331 ****
        rol     r_arg1          ; shift dividend (with CARRY)
        dec     r_cnt           ; decrement loop counter
        brne    __udivmodqi4_loop
!       com     r_arg1          ; complement result 
                                ; because C flag was complemented in loop
        ret
        .endfunc
--- 326,332 ----
        rol     r_arg1          ; shift dividend (with CARRY)
        dec     r_cnt           ; decrement loop counter
        brne    __udivmodqi4_loop
!       com     r_arg1          ; complement result
                                ; because C flag was complemented in loop
        ret
        .endfunc
*************** __divmodqi4_exit:
*** 357,364 ****
  #undef r_arg1
  #undef r_arg2
  #undef r_cnt
!       
!               
  /*******************************************************
         Division 16 / 16 => (result + remainder)
  *******************************************************/
--- 358,365 ----
  #undef r_arg1
  #undef r_arg2
  #undef r_cnt
! 
! 
  /*******************************************************
         Division 16 / 16 => (result + remainder)
  *******************************************************/
*************** __divmodqi4_exit:
*** 372,378 ****
  /* return: quotient */
  #define       r_arg2L r22     /* divisor Low */
  #define       r_arg2H r23     /* divisor High */
!       
  #define       r_cnt   r21     /* loop count */
  
  #if defined (L_udivmodhi4)
--- 373,379 ----
  /* return: quotient */
  #define       r_arg2L r22     /* divisor Low */
  #define       r_arg2H r23     /* divisor High */
! 
  #define       r_cnt   r21     /* loop count */
  
  #if defined (L_udivmodhi4)
*************** __divmodhi4_neg1:
*** 438,454 ****
        .endfunc
  #endif /* defined (L_divmodhi4) */
  
! #undef r_remH  
! #undef r_remL  
!              
! #undef r_arg1H 
! #undef r_arg1L 
!              
! #undef r_arg2H 
! #undef r_arg2L 
!               
! #undef r_cnt          
!       
  /*******************************************************
         Division 32 / 32 => (result + remainder)
  *******************************************************/
--- 439,455 ----
        .endfunc
  #endif /* defined (L_divmodhi4) */
  
! #undef r_remH
! #undef r_remL
! 
! #undef r_arg1H
! #undef r_arg1L
! 
! #undef r_arg2H
! #undef r_arg2L
! 
! #undef r_cnt
! 
  /*******************************************************
         Division 32 / 32 => (result + remainder)
  *******************************************************/
*************** __divmodhi4_neg1:
*** 468,474 ****
  #define       r_arg2HL r20
  #define       r_arg2H  r19
  #define       r_arg2L  r18    /* divisor Low */
!       
  #define       r_cnt __zero_reg__  /* loop count (0 after the loop!) */
  
  #if defined (L_udivmodsi4)
--- 469,475 ----
  #define       r_arg2HL r20
  #define       r_arg2H  r19
  #define       r_arg2L  r18    /* divisor Low */
! 
  #define       r_cnt __zero_reg__  /* loop count (0 after the loop!) */
  
  #if defined (L_udivmodsi4)
*************** __tablejump2__:
*** 674,676 ****
--- 675,752 ----
  .endfunc
  #endif /* defined (L_tablejump) */
  
+ #ifdef L_ctor
+         .sect   .init3,"ax",@progbits
+         .globl  __do_global_ctors
+ ;;
+ ;; Run through constructor table.
+ ;; This needs to be run before main is called.
+ ;;
+ #define ZH r31
+ #define ZL r30
+ #define XH r27
+ #define XL r26
+ 
+ __do_global_ctors:
+ #if defined (__AVR_ENHANCED__) && defined (__AVR_MEGA__)
+       ldi     ZL, lo8(__CTOR_LIST__)
+       ldi     ZH, hi8(__CTOR_LIST__)
+       ldi     r16, hh8(__CTOR_LIST__) ; init the RAMPZ value
+       out     __RAMPZ__, r16
+ _ctorsLoop:
+       cpi     ZL, lo8(__CTOR_END__)
+       brne    _do_ctor    ; Branch if low Z not equal to CTOR_END
+       cpi     ZH, hi8(__CTOR_END__)
+       brne    _do_ctor    ; Branch if high Z not equal to CTOR_END
+       jmp     _ctors_done
+ _do_ctor:
+       elpm    XL, Z+
+       elpm    XH, Z+          ; post-increment will automatically handle RAMPZ
+       push    ZL
+       push    ZH
+       movw    ZL, XL
+       icall
+       pop     ZH
+       pop     ZL
+       jmp     _ctorsLoop
+ #endif                                /* AVR_ENHANCED, AVR_MEGA */
+ _ctors_done:
+ #endif                                /* L_ctor */
+ 
+ #ifdef L_dtor
+         .sect   .fini3,"ax",@progbits
+         .globl  __do_global_dtors
+ ;;
+ ;; Run through the destructor table.
+ ;; This needs to be run in the exit function.
+ ;;
+ #define ZH r31
+ #define ZL r30
+ #define XH r27
+ #define XL r26
+ 
+ __do_global_dtors:
+ #if defined (__AVR_ENHANCED__) && defined (__AVR_MEGA__)
+       ldi     ZL, lo8(__DTOR_LIST__)
+       ldi     ZH, hi8(__DTOR_LIST__)
+       ldi     r16, hh8(__DTOR_LIST__) ; init the RAMPZ value
+       out     __RAMPZ__, r16
+ _dtorsLoop:
+       cpi     r30, lo8(__DTOR_END__)
+       brne    _do_dtor    ; Branch if low Z not equal to DTOR_END
+       cpi     r31, hi8(__DTOR_END__)
+       brne    _do_dtor    ; Branch if high Z not equal to DTOR_END
+       jmp     _dtors_done
+ _do_dtor:
+       elpm    XL, Z+
+       elpm    XH, Z+          ; post-increment will automatically handle RAMPZ
+       push    ZL
+       push    ZH
+       movw    ZL, XL
+       icall
+       pop     ZH
+       pop     ZL
+       jmp     _dtorsLoop
+ #endif                                /* AVR_ENHANCED, AVR_MEGA */
+ _dtors_done:
+ #endif                                /* L_dtor */
diff -c3pr gcc-3.0.2-patch-0.1/gcc/config/avr/t-avr 
gcc-3.0.2-patch-0.4/gcc/config/avr/t-avr
*** gcc-3.0.2-patch-0.1/gcc/config/avr/t-avr    Tue Nov  6 18:02:33 2001
--- gcc-3.0.2-patch-0.4/gcc/config/avr/t-avr    Tue Jan  8 19:34:41 2002
*************** LIB1ASMFUNCS = \
*** 18,24 ****
        _epilogue \
        _exit \
        _cleanup \
!       _tablejump
  
  # libgcc...
  LIBGCC1_TEST =
--- 18,26 ----
        _epilogue \
        _exit \
        _cleanup \
!       _tablejump \
!       _ctor \
!       _dtor
  
  # libgcc...
  LIBGCC1_TEST =
Only in gcc-3.0.2-patch-0.1/gcc/po: stamp-cat-id
Only in gcc-3.0.2-patch-0.4/gcc: tm.h
OUTPUT_FORMAT("elf32-avr","elf32-avr","elf32-avr")
OUTPUT_ARCH(avr:5)
MEMORY
{
  text   (rx)   : ORIGIN = 0,        LENGTH = 128K
  /* Data space is restricted to first page of external RAM */
  data   (rw!x) : ORIGIN = 0x800100, LENGTH = 0x07ef8
  eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 4K
}
SECTIONS
{
  /* Read-only sections, merged into text segment: */
  .hash          : { *(.hash)           }
  .dynsym        : { *(.dynsym)         }
  .dynstr        : { *(.dynstr)         }
  .gnu.version   : { *(.gnu.version)    }
  .gnu.version_d   : { *(.gnu.version_d)        }
  .gnu.version_r   : { *(.gnu.version_r)        }
  .rel.init      : { *(.rel.init)       }
  .rela.init     : { *(.rela.init)      }
  .rel.text      :
    {
      *(.rel.text)
      *(.rel.text.*)
      *(.rel.gnu.linkonce.t*)
    }
  .rela.text     :
    {
      *(.rela.text)
      *(.rela.text.*)
      *(.rela.gnu.linkonce.t*)
    }
  .rel.fini      : { *(.rel.fini)       }
  .rela.fini     : { *(.rela.fini)      }
  .rel.rodata    :
    {
      *(.rel.rodata)
      *(.rel.rodata.*)
      *(.rel.gnu.linkonce.r*)
    }
  .rela.rodata   :
    {
      *(.rela.rodata)
      *(.rela.rodata.*)
      *(.rela.gnu.linkonce.r*)
    }
  .rel.data      :
    {
      *(.rel.data)
      *(.rel.data.*)
      *(.rel.gnu.linkonce.d*)
    }
  .rela.data     :
    {
      *(.rela.data)
      *(.rela.data.*)
      *(.rela.gnu.linkonce.d*)
    }
  .rel.ctors     : { *(.rel.ctors)      }
  .rela.ctors    : { *(.rela.ctors)     }
  .rel.dtors     : { *(.rel.dtors)      }
  .rela.dtors    : { *(.rela.dtors)     }
  .rel.got       : { *(.rel.got)                }
  .rela.got      : { *(.rela.got)               }
  .rel.bss       : { *(.rel.bss)                }
  .rela.bss      : { *(.rela.bss)               }
  .rel.plt       : { *(.rel.plt)                }
  .rela.plt      : { *(.rela.plt)               }

  /* Internal text space or external memory */
  .text :
  {
    *(.vectors)
    *(.init0)
    *(.init1)
    *(.init2)
    *(.init3)
    *(.init4)
    *(.progmem.gcc*)
    *(.progmem*)
    . = ALIGN(2);
    *(.text)
    . = ALIGN(2);
    *(.text.*)
    . = ALIGN(2);
    __CTOR_LIST__ = .;
    *(.ctors)
    __CTOR_END__ = .;
    _etext = . ;
  }  > text

  /DISCARD/ :
  {
    *(.fini)
    *(.fini3)
/*    . = ALIGN(2); */
/*    __DTOR_LIST__ = .; */
    *(.dtors)
/*    __DTOR_END__ = .; */
  }

  .data   : AT (ADDR (.text) + SIZEOF (.text))
  {
    *(.data)
    *(.gnu.linkonce.d*)
    . = ALIGN(2);
     _edata = . ;
  }  > data

  __data_length = SIZEOF(.data);
  __data_start = ADDR(.data);
  __data_end = __data_start + SIZEOF(.data);
  __data_load_start = LOADADDR(.data);
  __data_load_end = __data_load_start + SIZEOF(.data);

  .bss __data_end :
  {
    *(.bss)
    *(COMMON)
     _end = . ;
  }  > data

  __bss_length = SIZEOF(.bss);
  __bss_start = LOADADDR(.bss);
  __bss_end = __bss_start + __bss_length;

  .eeprom  :
        AT (ADDR (.text) + SIZEOF (.text) + SIZEOF (.data))
  {
    *(.eeprom*)
     __eeprom_end = . ;
  }  > eeprom

  /* Stabs debugging sections.  */
  .stab 0 : { *(.stab) }
  .stabstr 0 : { *(.stabstr) }
  .stab.excl 0 : { *(.stab.excl) }
  .stab.exclstr 0 : { *(.stab.exclstr) }
  .stab.index 0 : { *(.stab.index) }
  .stab.indexstr 0 : { *(.stab.indexstr) }
  .comment 0 : { *(.comment) }
  /* DWARF debug sections.
     Symbols in the DWARF debugging sections are relative to the beginning
     of the section so we begin them at 0.  */
  /* DWARF 1 */
  .debug          0 : { *(.debug) }
  .line           0 : { *(.line) }
  /* GNU DWARF 1 extensions */
  .debug_srcinfo  0 : { *(.debug_srcinfo) }
  .debug_sfnames  0 : { *(.debug_sfnames) }
  /* DWARF 1.1 and DWARF 2 */
  .debug_aranges  0 : { *(.debug_aranges) }
  .debug_pubnames 0 : { *(.debug_pubnames) }
  /* DWARF 2 */
  .debug_info     0 : { *(.debug_info) *(.gnu.linkonce.wi.*) }
  .debug_abbrev   0 : { *(.debug_abbrev) }
  .debug_line     0 : { *(.debug_line) }
  .debug_frame    0 : { *(.debug_frame) }
  .debug_str      0 : { *(.debug_str) }
  .debug_loc      0 : { *(.debug_loc) }
  .debug_macinfo  0 : { *(.debug_macinfo) }
  PROVIDE (__stack = 0x7FF7) ;
  /* The following enables the external memory bus. */
  __init_mcucr__ = 0x80 ;
}
/* Copyright (C) 1999 Denis Chertykov <address@hidden>

This file is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.

In addition to the permissions in the GNU General Public License, the
author gives you unlimited permission to link the
compiled version of this file into combinations with other programs,
and to distribute those combinations without any restriction coming
from the use of this file.  (The General Public License restrictions
do apply in other respects; for example, they cover modification of
the file, and distribution when not linked into a combine
executable.)

This file is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.  */

/* Hacked a lot by Marek Michalkiewicz <address@hidden> to add
   support for many MCU types, etc.  These changes are public domain.  */

;; -*- mode: asm -*-

#include "macros.inc"

#if !defined (__AVR_ASM_ONLY__)
; not required by gas, but still a nice way to show referenced symbols
        .extern _U(main)
        .extern _etext
        .extern __data_start
        .extern __data_end
        .extern __data_load_start
        .extern _edata
        .extern __bss_start
        .extern __bss_end

; Stack init in main() (can override with avr-ld --defsym __stack=...)
;       .weak __stack
;__stack = RAMEND
        .extern __stack

; These too can be set with the avr-ld --defsym name=value option
; (MCUCR must be set up correctly to enable external SRAM).
        .weak   __init_mcucr__
        .weak   __init_emcucr__
        .weak   __init_wdtcr__

; You can plug in your own code to handle unexpected
; interrupts (which usually indicate a bug - if the program
; enables an interrupt for which there is no handler).
        .weak   _U(_unexpected_)
#endif /* if !defined (__AVR_ASM_ONLY__) */

; You can plug in your own asm code that runs immediately
; after reset, without any initialization at all.  When done,
; it should jump to _real_init_.
        .weak   _U(_init_)
;
; Vector table macros
;
        .set    no_vect, 0
        .macro  VEC name
          .if           (END_VECTOR > no_vect)
            .weak       _U(\name)
            #if !defined (__AVR_ASM_ONLY__)
            .set        _U(\name), _unexpected_1_
            #endif
            XJMP        _U(\name)
          .endif
          .set          no_vect, no_vect + 1
        .endm

; reset and interrupt vectors, starting at absolute address 0

        .section .vectors, "ax", @progbits
        .func   .__start_of_init__
.__start_of_init__:
        XJMP    _U(_init_)

        VEC     _vector_1
        VEC     _vector_2
        VEC     _vector_3
        VEC     _vector_4
        VEC     _vector_5
        VEC     _vector_6
        VEC     _vector_7
        VEC     _vector_8
        VEC     _vector_9
        VEC     _vector_10
        VEC     _vector_11
        VEC     _vector_12
        VEC     _vector_13
        VEC     _vector_14
        VEC     _vector_15
        VEC     _vector_16
        VEC     _vector_17
        VEC     _vector_18
        VEC     _vector_19
        VEC     _vector_20
        VEC     _vector_21
        VEC     _vector_22
        VEC     _vector_23
        VEC     _vector_24
        VEC     _vector_25
        VEC     _vector_26
        VEC     _vector_27
        VEC     _vector_28
        VEC     _vector_29
        VEC     _vector_30
        VEC     _vector_31
        VEC     _vector_32
        VEC     _vector_33
        VEC     _vector_34
        VEC     _vector_35
        VEC     _vector_36
        VEC     _vector_37
        VEC     _vector_38
        VEC     _vector_39

        .endfunc

        .sect   .init0,"ax",@progbits
#if !defined (__AVR_ASM_ONLY__)
        .func   .__c_startup__
.__c_startup__:
; two remporary registers (usable with ldi, not pointer registers)
#define r_tmp1 r18
#define r_tmp2 r19

/*
 * I/O instructions below (out) require an address < 0x40.
 * If an SFR offset is being used, the register address needs to be
 * scaled back from its DATA memory address to its I/O memory address.
 */
#ifndef __SFR_OFFSET
#define __SFR_OFFSET 0
#endif /* !__SFR_OFFSET */

        .global _U(_real_init_)
_U(_real_init_):
_U(_init_):
        clr     __zero_reg__
        out     (SREG - __SFR_OFFSET), __zero_reg__
#ifdef WDTCR
        ldi     r_tmp1, lo8(__init_wdtcr__)
        wdr
        out     (WDTCR - __SFR_OFFSET), r_tmp1
#endif
#ifdef MCUCR
        ldi     r_tmp1, lo8(__init_mcucr__)
        out     (MCUCR - __SFR_OFFSET), r_tmp1
#endif
#ifdef EMCUCR
        ldi     r_tmp1, lo8(__init_emcucr__)
        out     (EMCUCR - __SFR_OFFSET), r_tmp1
#endif

;; Set up the stack

        ldi     r_tmp1, lo8(__stack)
        out     (SPL - __SFR_OFFSET), r_tmp1
        ldi     r_tmp1, hi8(__stack)
        out     (SPH - __SFR_OFFSET), r_tmp1

; XXX should we also read, save and clear MCUSR (if present) here?
; (datasheets suggest to do it as soon as possible after reset)

        .endfunc

        .sect   .init1,"ax",@progbits

;; Copy initalized data from __data_load_start to __data_start until 
__data_load_end

.copy_data:
        ldi     ZL, lo8(__data_load_start); 
        ldi     ZH, hi8(__data_load_start);
#if BIG_CODE
        ldi     r_tmp2, hh8(__data_load_start)  ; this will be in RAMPZ for 
"elpm"
#endif
        ldi     XL, lo8(__data_start)   ; load start of ram
        ldi     XH, hi8(__data_start)
#if XRAMEND > 0x100  /* don't bother with high byte if we know it must be 0 */
        ldi     r_tmp1, hi8(__data_end)
#endif
        LPM_R0_ZPLUS_INIT r_tmp2
        rjmp    .copy_data_start
.copy_data_loop:
        LPM_R0_ZPLUS_NEXT r_tmp2
        st      X+, r0
.copy_data_start:
        cpi     XL, lo8(__data_end)
#if XRAMEND > 0x100
        cpc     XH, r_tmp1      ; hi8(__data_end)
#endif
        brne    .copy_data_loop

;; Clear BSS section

.zero_bss:
        ldi     XL, lo8(__bss_start)
        ldi     XH, hi8(__bss_start)
#if XRAMEND > 0x100
        ldi     r_tmp1, hi8(__bss_end)
#endif
        rjmp    .zero_bss_start
.zero_bss_loop:
        st      X+, __zero_reg__
.zero_bss_start:
        cpi     XL, lo8(__bss_end)
#if XRAMEND > 0x100
        cpc     XH, r_tmp1      ; hi8(__bss_end)
#endif
        brne    .zero_bss_loop

        .sect   .init4,"ax",@progbits
;; Call the main function

        XJMP    _U(main)

        .sect   .text,"ax",@progbits
;; Handle unexpected interrupts

_unexpected_1_:
        XJMP    _U(_unexpected_)

_U(_unexpected_):
        reti

#endif /* if !defined (__AVR_ASM_ONLY__) */

reply via email to

[Prev in Thread] Current Thread [Next in Thread]