[Top][All Lists]
[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__) */
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [avr-gcc-list] C++ for AVR,
Peter Jansen <=