421 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
		
		
			
		
	
	
			421 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
|   | // SEGGER Embedded Studio, runtime support. | ||
|  | // | ||
|  | // Copyright (c) 2014-2017 SEGGER Microcontroller GmbH & Co KG | ||
|  | // Copyright (c) 2001-2017 Rowley Associates Limited. | ||
|  | // | ||
|  | // This file may be distributed under the terms of the License Agreement | ||
|  | // provided with this software. | ||
|  | // | ||
|  | // THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING THE | ||
|  | // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | ||
|  | // | ||
|  | // | ||
|  | //                           Preprocessor Definitions | ||
|  | //                           ------------------------ | ||
|  | // APP_ENTRY_POINT | ||
|  | // | ||
|  | //   Defines the application entry point function, if undefined this setting | ||
|  | //   defaults to "main". | ||
|  | // | ||
|  | // INITIALIZE_STACK | ||
|  | // | ||
|  | //   If defined, the contents of the stack will be initialized to a the | ||
|  | //   value 0xCC. | ||
|  | // | ||
|  | // INITIALIZE_SECONDARY_SECTIONS | ||
|  | // | ||
|  | //   If defined, the .data2, .text2, .rodata2 and .bss2 sections will be initialized. | ||
|  | // | ||
|  | // INITIALIZE_TCM_SECTIONS | ||
|  | // | ||
|  | //   If defined, the .data_tcm, .text_tcm, .rodata_tcm and .bss_tcm sections  | ||
|  | //   will be initialized. | ||
|  | // | ||
|  | // INITIALIZE_USER_SECTIONS | ||
|  | // | ||
|  | //   If defined, the function InitializeUserMemorySections will be called prior | ||
|  | //   to entering main in order to allow the user to initialize any user defined | ||
|  | //   memory sections. | ||
|  | // | ||
|  | // FULL_LIBRARY | ||
|  | // | ||
|  | //  If defined then  | ||
|  | //    - argc, argv are setup by the debug_getargs. | ||
|  | //    - the exit symbol is defined and executes on return from main. | ||
|  | //    - the exit symbol calls destructors, atexit functions and then debug_exit. | ||
|  | //   | ||
|  | //  If not defined then | ||
|  | //    - argc and argv are zero. | ||
|  | //    - the exit symbol is defined, executes on return from main and loops | ||
|  | // | ||
|  | 
 | ||
|  | #ifndef APP_ENTRY_POINT | ||
|  | #define APP_ENTRY_POINT main | ||
|  | #endif | ||
|  | 
 | ||
|  | #ifndef ARGSSPACE | ||
|  | #define ARGSSPACE 128 | ||
|  | #endif | ||
|  |   .syntax unified
 | ||
|  | 
 | ||
|  |   .global _start
 | ||
|  |   .extern APP_ENTRY_POINT
 | ||
|  |   .global exit
 | ||
|  |   .weak exit
 | ||
|  | 
 | ||
|  | #ifdef INITIALIZE_USER_SECTIONS | ||
|  |   .extern InitializeUserMemorySections
 | ||
|  | #endif | ||
|  | 
 | ||
|  |   .section .init, "ax" | ||
|  |   .code 16
 | ||
|  |   .align 2
 | ||
|  |   .thumb_func | ||
|  | 
 | ||
|  | _start: | ||
|  |   /* Set up main stack if size > 0 */ | ||
|  |   ldr r1, =__stack_end__ | ||
|  |   ldr r0, =__stack_start__ | ||
|  |   subs r2, r1, r0 | ||
|  |   beq 1f | ||
|  | #ifdef __ARM_EABI__ | ||
|  |   movs r2, #0x7 | ||
|  |   bics r1, r2 | ||
|  | #endif | ||
|  |   mov sp, r1 | ||
|  | #ifdef INITIALIZE_STACK | ||
|  |   movs r2, #0xCC | ||
|  |   ldr r0, =__stack_start__ | ||
|  |   bl memory_set | ||
|  | #endif | ||
|  | 1: | ||
|  | 
 | ||
|  |   /* Set up process stack if size > 0 */ | ||
|  |   ldr r1, =__stack_process_end__ | ||
|  |   ldr r0, =__stack_process_start__ | ||
|  |   subs r2, r1, r0 | ||
|  |   beq 1f | ||
|  | #ifdef __ARM_EABI__ | ||
|  |   movs r2, #0x7 | ||
|  |   bics r1, r2 | ||
|  | #endif | ||
|  |   msr psp, r1 | ||
|  |   movs r2, #2 | ||
|  |   msr control, r2 | ||
|  | #ifdef INITIALIZE_STACK | ||
|  |   movs r2, #0xCC | ||
|  |   bl memory_set | ||
|  | #endif | ||
|  | 1: | ||
|  | 
 | ||
|  |   /* Copy initialized memory sections into RAM (if necessary). */ | ||
|  |   ldr r0, =__data_load_start__ | ||
|  |   ldr r1, =__data_start__ | ||
|  |   ldr r2, =__data_end__ | ||
|  |   bl memory_copy | ||
|  |   ldr r0, =__text_load_start__ | ||
|  |   ldr r1, =__text_start__ | ||
|  |   ldr r2, =__text_end__ | ||
|  |   bl memory_copy | ||
|  |   ldr r0, =__fast_load_start__ | ||
|  |   ldr r1, =__fast_start__ | ||
|  |   ldr r2, =__fast_end__ | ||
|  |   bl memory_copy | ||
|  |   ldr r0, =__ctors_load_start__ | ||
|  |   ldr r1, =__ctors_start__ | ||
|  |   ldr r2, =__ctors_end__ | ||
|  |   bl memory_copy | ||
|  |   ldr r0, =__dtors_load_start__ | ||
|  |   ldr r1, =__dtors_start__ | ||
|  |   ldr r2, =__dtors_end__ | ||
|  |   bl memory_copy | ||
|  |   ldr r0, =__rodata_load_start__ | ||
|  |   ldr r1, =__rodata_start__ | ||
|  |   ldr r2, =__rodata_end__ | ||
|  |   bl memory_copy | ||
|  |   ldr r0, =__tdata_load_start__ | ||
|  |   ldr r1, =__tdata_start__ | ||
|  |   ldr r2, =__tdata_end__ | ||
|  |   bl memory_copy | ||
|  | #ifdef INITIALIZE_SECONDARY_SECTIONS | ||
|  |   ldr r0, =__data2_load_start__ | ||
|  |   ldr r1, =__data2_start__ | ||
|  |   ldr r2, =__data2_end__ | ||
|  |   bl memory_copy | ||
|  |   ldr r0, =__text2_load_start__ | ||
|  |   ldr r1, =__text2_start__ | ||
|  |   ldr r2, =__text2_end__ | ||
|  |   bl memory_copy | ||
|  |   ldr r0, =__rodata2_load_start__ | ||
|  |   ldr r1, =__rodata2_start__ | ||
|  |   ldr r2, =__rodata2_end__ | ||
|  |   bl memory_copy | ||
|  | #endif /* #ifdef INITIALIZE_SECONDARY_SECTIONS */ | ||
|  | #ifdef INITIALIZE_TCM_SECTIONS | ||
|  |   ldr r0, =__data_tcm_load_start__ | ||
|  |   ldr r1, =__data_tcm_start__ | ||
|  |   ldr r2, =__data_tcm_end__ | ||
|  |   bl memory_copy | ||
|  |   ldr r0, =__text_tcm_load_start__ | ||
|  |   ldr r1, =__text_tcm_start__ | ||
|  |   ldr r2, =__text_tcm_end__ | ||
|  |   bl memory_copy | ||
|  |   ldr r0, =__rodata_tcm_load_start__ | ||
|  |   ldr r1, =__rodata_tcm_start__ | ||
|  |   ldr r2, =__rodata_tcm_end__ | ||
|  |   bl memory_copy | ||
|  | #endif /* #ifdef INITIALIZE_TCM_SECTIONS */ | ||
|  | 
 | ||
|  |   /* Zero the bss. */ | ||
|  |   ldr r0, =__bss_start__ | ||
|  |   ldr r1, =__bss_end__ | ||
|  |   movs r2, #0 | ||
|  |   bl memory_set | ||
|  |   ldr r0, =__tbss_start__ | ||
|  |   ldr r1, =__tbss_end__ | ||
|  |   movs r2, #0 | ||
|  |   bl memory_set | ||
|  | #ifdef INITIALIZE_SECONDARY_SECTIONS | ||
|  |   ldr r0, =__bss2_start__ | ||
|  |   ldr r1, =__bss2_end__ | ||
|  |   mov r2, #0 | ||
|  |   bl memory_set | ||
|  | #endif /* #ifdef INITIALIZE_SECONDARY_SECTIONS */ | ||
|  | #ifdef INITIALIZE_TCM_SECTIONS | ||
|  |   ldr r0, =__bss_tcm_start__ | ||
|  |   ldr r1, =__bss_tcm_end__ | ||
|  |   mov r2, #0 | ||
|  |   bl memory_set | ||
|  | #endif /* #ifdef INITIALIZE_TCM_SECTIONS */ | ||
|  | 
 | ||
|  |   /* Initialize the heap */ | ||
|  |   ldr r0, = __heap_start__ | ||
|  |   ldr r1, = __heap_end__ | ||
|  |   subs r1, r1, r0 | ||
|  |   cmp r1, #8 | ||
|  |   blt 1f | ||
|  |   movs r2, #0 | ||
|  |   str r2, [r0] | ||
|  |   adds r0, r0, #4 | ||
|  |   str r1, [r0] | ||
|  | 1: | ||
|  | 
 | ||
|  | #ifdef INITIALIZE_USER_SECTIONS | ||
|  |   ldr r2, =InitializeUserMemorySections | ||
|  |   blx r2 | ||
|  | #endif | ||
|  | 
 | ||
|  |   /* Call constructors */ | ||
|  |   ldr r0, =__ctors_start__ | ||
|  |   ldr r1, =__ctors_end__ | ||
|  | ctor_loop: | ||
|  |   cmp r0, r1 | ||
|  |   beq ctor_end | ||
|  |   ldr r2, [r0] | ||
|  |   adds r0, #4 | ||
|  |   push {r0-r1}   | ||
|  |   blx r2 | ||
|  |   pop {r0-r1} | ||
|  |   b ctor_loop | ||
|  | ctor_end: | ||
|  | 
 | ||
|  |   /* Setup initial call frame */ | ||
|  |   movs r0, #0 | ||
|  |   mov lr, r0 | ||
|  |   mov r12, sp | ||
|  | 
 | ||
|  |   .type start, function | ||
|  | start: | ||
|  |   /* Jump to application entry point */ | ||
|  | #ifdef FULL_LIBRARY | ||
|  |   movs r0, #ARGSSPACE | ||
|  |   ldr r1, =args | ||
|  |   ldr r2, =debug_getargs   | ||
|  |   blx r2 | ||
|  |   ldr r1, =args | ||
|  | #else | ||
|  |   movs r0, #0 | ||
|  |   movs r1, #0 | ||
|  | #endif | ||
|  |   ldr r2, =APP_ENTRY_POINT | ||
|  |   blx r2 | ||
|  | 
 | ||
|  |   .thumb_func | ||
|  | exit: | ||
|  | #ifdef FULL_LIBRARY   | ||
|  |   mov r5, r0 // save the exit parameter/return result | ||
|  | 
 | ||
|  |   /* Call destructors */ | ||
|  |   ldr r0, =__dtors_start__ | ||
|  |   ldr r1, =__dtors_end__ | ||
|  | dtor_loop: | ||
|  |   cmp r0, r1 | ||
|  |   beq dtor_end | ||
|  |   ldr r2, [r0] | ||
|  |   add r0, #4 | ||
|  |   push {r0-r1} | ||
|  |   blx r2 | ||
|  |   pop {r0-r1} | ||
|  |   b dtor_loop | ||
|  | dtor_end: | ||
|  | 
 | ||
|  |   /* Call atexit functions */ | ||
|  |   ldr r2, =_execute_at_exit_fns   | ||
|  |   blx r2 | ||
|  | 
 | ||
|  |   /* Call debug_exit with return result/exit parameter */ | ||
|  |   mov r0, r5 | ||
|  |   ldr r2, =debug_exit   | ||
|  |   blx r2 | ||
|  | #endif | ||
|  | 
 | ||
|  |   /* Returned from application entry point, loop forever. */ | ||
|  | exit_loop: | ||
|  |   b exit_loop | ||
|  | 
 | ||
|  |   .thumb_func | ||
|  | memory_copy: | ||
|  |   cmp r0, r1 | ||
|  |   beq 2f | ||
|  |   subs r2, r2, r1 | ||
|  |   beq 2f | ||
|  | 1: | ||
|  |   ldrb r3, [r0] | ||
|  |   adds r0, r0, #1 | ||
|  |   strb r3, [r1] | ||
|  |   adds r1, r1, #1 | ||
|  |   subs r2, r2, #1 | ||
|  |   bne 1b | ||
|  | 2: | ||
|  |   bx lr | ||
|  | 
 | ||
|  |   .thumb_func | ||
|  | memory_set: | ||
|  |   cmp r0, r1 | ||
|  |   beq 1f | ||
|  |   strb r2, [r0] | ||
|  |   adds r0, r0, #1 | ||
|  |   b memory_set | ||
|  | 1: | ||
|  |   bx lr | ||
|  | 
 | ||
|  |   // default C/C++ library helpers | ||
|  | 
 | ||
|  | .macro HELPER helper_name | ||
|  |   .section .text.\helper_name, "ax", %progbits | ||
|  |   .global \helper_name | ||
|  |   .weak \helper_name   | ||
|  | \helper_name: | ||
|  |   .thumb_func | ||
|  | .endm | ||
|  | 
 | ||
|  | .macro JUMPTO name | ||
|  | #if defined(__thumb__) && !defined(__thumb2__) | ||
|  |   mov r12, r0 | ||
|  |   ldr r0, =\name | ||
|  |   push {r0} | ||
|  |   mov r0, r12 | ||
|  |   pop {pc} | ||
|  | #else | ||
|  |   b \name | ||
|  | #endif | ||
|  | .endm | ||
|  | 
 | ||
|  | HELPER __aeabi_read_tp | ||
|  |   ldr r0, =__tbss_start__-8 | ||
|  |   bx lr | ||
|  | HELPER __heap_lock | ||
|  |   bx lr | ||
|  | HELPER __heap_unlock | ||
|  |   bx lr | ||
|  | HELPER __printf_lock | ||
|  |   bx lr | ||
|  | HELPER __printf_unlock | ||
|  |   bx lr | ||
|  | HELPER __scanf_lock | ||
|  |   bx lr | ||
|  | HELPER __scanf_unlock | ||
|  |   bx lr | ||
|  | HELPER __debug_io_lock | ||
|  |   bx lr | ||
|  | HELPER __debug_io_unlock | ||
|  |   bx lr | ||
|  | HELPER abort | ||
|  |   b . | ||
|  | HELPER __assert | ||
|  |   b . | ||
|  | HELPER __aeabi_assert | ||
|  |   b . | ||
|  | HELPER __cxa_pure_virtual | ||
|  |   b . | ||
|  | HELPER __cxa_guard_acquire | ||
|  |   ldr r3, [r0] | ||
|  | #if defined(__thumb__) && !defined(__thumb2__) | ||
|  |   movs r0, #1 | ||
|  |   tst r3, r0 | ||
|  | #else | ||
|  |   tst r3, #1 | ||
|  | #endif | ||
|  |   beq 1f | ||
|  |   movs r0, #0 | ||
|  |   bx lr | ||
|  | 1: | ||
|  |   movs r0, #1 | ||
|  |   bx lr | ||
|  | HELPER __cxa_guard_release | ||
|  |   movs r3, #1 | ||
|  |   str r3, [r0] | ||
|  |   bx lr | ||
|  | HELPER __cxa_guard_abort | ||
|  |   bx lr | ||
|  | HELPER __sync_synchronize | ||
|  |   bx lr | ||
|  | HELPER __getchar | ||
|  |   JUMPTO debug_getchar | ||
|  | HELPER __putchar | ||
|  |   JUMPTO debug_putchar | ||
|  | HELPER __open | ||
|  |   JUMPTO debug_fopen | ||
|  | HELPER __close | ||
|  |   JUMPTO debug_fclose | ||
|  | HELPER __write    | ||
|  |   mov r3, r0 | ||
|  |   mov r0, r1 | ||
|  |   movs r1, #1   | ||
|  |   JUMPTO debug_fwrite | ||
|  | HELPER __read   | ||
|  |   mov r3, r0 | ||
|  |   mov r0, r1 | ||
|  |   movs r1, #1  | ||
|  |   JUMPTO debug_fread | ||
|  | HELPER __seek | ||
|  |   push {r4, lr} | ||
|  |   mov r4, r0 | ||
|  |   bl debug_fseek | ||
|  |   cmp r0, #0 | ||
|  |   bne 1f | ||
|  |   mov r0, r4 | ||
|  |   bl debug_ftell | ||
|  |   pop {r4, pc} | ||
|  | 1: | ||
|  |   ldr r0, =-1 | ||
|  |   pop {r4, pc} | ||
|  |   // char __user_locale_name_buffer[];
 | ||
|  |   .section .bss.__user_locale_name_buffer, "aw", %nobits | ||
|  |   .global __user_locale_name_buffer
 | ||
|  |   .weak __user_locale_name_buffer
 | ||
|  |   __user_locale_name_buffer: | ||
|  |   .word 0x0
 | ||
|  | 
 | ||
|  | #ifdef FULL_LIBRARY | ||
|  |   .bss | ||
|  | args: | ||
|  |   .space ARGSSPACE
 | ||
|  | #endif | ||
|  | 
 | ||
|  |   /* Setup attibutes of stack and heap sections so they don't take up room in the elf file */ | ||
|  |   .section .stack, "wa", %nobits | ||
|  |   .section .stack_process, "wa", %nobits | ||
|  |   .section .heap, "wa", %nobits | ||
|  | 
 |