// **********************************************************************
// *                    SEGGER Microcontroller GmbH                     *
// *                        The Embedded Experts                        *
// **********************************************************************
// *                                                                    *
// *            (c) 2014 - 2020 SEGGER Microcontroller GmbH             *
// *            (c) 2001 - 2020 Rowley Associates Limited               *
// *                                                                    *
// *           www.segger.com     Support: support@segger.com           *
// *                                                                    *
// **********************************************************************
// *                                                                    *
// * All rights reserved.                                               *
// *                                                                    *
// * Redistribution and use in source and binary forms, with or         *
// * without modification, are permitted provided that the following    *
// * conditions are met:                                                *
// *                                                                    *
// * - Redistributions of source code must retain the above copyright   *
// *   notice, this list of conditions and the following disclaimer.    *
// *                                                                    *
// * - Neither the name of SEGGER Microcontroller GmbH                  *
// *   nor the names of its contributors may be used to endorse or      *
// *   promote products derived from this software without specific     *
// *   prior written permission.                                        *
// *                                                                    *
// * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND             *
// * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,        *
// * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF           *
// * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE           *
// * DISCLAIMED.                                                        *
// * IN NO EVENT SHALL SEGGER Microcontroller GmbH BE LIABLE FOR        *
// * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR           *
// * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  *
// * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;    *
// * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF      *
// * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT          *
// * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE  *
// * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH   *
// * DAMAGE.                                                            *
// *                                                                    *
// **********************************************************************
//                           Preprocessor Definitions
//                           ------------------------
//
// 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
//

  .syntax unified

  .section .segger.init.__SEGGER_init_lzss, "ax"
  .code 16
  .balign 2
  .global __SEGGER_init_lzss
.thumb_func
__SEGGER_init_lzss:
  ldr  r0, [r4]      @ destination
  ldr  r1, [r4, #4]  @ source stream
  adds r4, r4, #8
2:
  ldrb r2, [r1]
  adds r1, r1, #1
  tst r2, r2
  beq  9f           @ 0 -> end of table
  cmp r2, #0x80
  bcc  1f           @ +ve -> literal run
//
// -ve -> copy run
//
// r0 = pointer to output stream
// r1 = pointer to input stream
// r2 = run length
// r3 = copy byte
// r4 = pointer to initialization table
//
3:
  subs r2, r2, #0x80 // convert to run length
  beq 10f
  ldrb r3, [r1]       // r3 = first byte of distance
  adds r1, r1, #1
  cmp r3, #0x80
  bcc 5f              // r3 < 128, short run
  subs r3, r3, #0x80  // Adjust to recover true run length high byte
  lsls r3, r3, #8     // Prepare to fuse
  ldrb r5, [r1]       // extract run length low byte
  adds r1, r1, #1
  adds r3, r3, r5     // construct run length
5:
  subs r5, r0, r3    // source of where to copy from
4:
  ldrb r3, [r5]     // source byte of run
  strb r3, [r0]     // store to destination
  adds r5, r5, #1
  adds r0, r0, #1
  subs r2, r2, #1
  bne  4b
  b    2b
//
// +ve -> literal run
//
// r0 = pointer to output stream
// r1 = pointer to input stream
// r2 = run length
// r3 = copy byte
// r4 = pointer to initialization table
//
1:
  ldrb r3, [r1]     // source byte of run
  adds r1, r1, #1
  strb r3, [r0]     // store to destination
  adds r0, r0, #1
  subs r2, r2, #1
  bne  1b
  b    2b
9:
  bx lr
10:
  b 10b

  .section .segger.init.__SEGGER_init_zero, "ax"
  .code 16
  .balign 2
  .global __SEGGER_init_zero
.thumb_func
__SEGGER_init_zero:
  ldr r0, [r4]      @ destination
  ldr r1, [r4, #4]  @ size
  adds r4, r4, #8
  tst r1, r1
  beq 2f
  movs r2, #0
1:
  strb r2, [r0]
  adds r0, r0, #1
  subs r1, r1, #1
  bne 1b
2:
  bx lr

  .section .segger.init.__SEGGER_init_copy, "ax"
  .code 16
  .balign 2
  .global __SEGGER_init_copy
.thumb_func
__SEGGER_init_copy:
  ldr r0, [r4]      @ destination
  ldr r1, [r4, #4]  @ source
  ldr r2, [r4, #8]  @ size
  adds r4, r4, #12
  tst r2, r2
  beq 2f
1:
  ldrb r3, [r1]
  strb r3, [r0]
  adds r0, r0, #1
  adds r1, r1, #1
  subs r2, r2, #1
  bne 1b
2:
  bx lr

  .section .segger.init.__SEGGER_init_pack, "ax"
  .code 16
  .balign 2
  .global __SEGGER_init_pack
.thumb_func
__SEGGER_init_pack:
  ldr  r0, [r4]      @ destination
  ldr  r1, [r4, #4]  @ source stream
  adds r4, r4, #8
1:
  ldrb r2, [r1]
  adds r1, r1, #1
  cmp  r2, #0x80
  beq  4f
  bcc  3f
  ldrb r3, [r1]      @ byte to replicate
  adds r1, r1, #1
  negs r2, r2
  adds r2, r2, #255
  adds r2, r2, #1
2:
  strb r3, [r0]
  adds r0, r0, #1
  subs r2, r2, #1
  bpl  2b
  b    1b

3:                   @ 1+n literal bytes
  ldrb r3, [r1]
  strb r3, [r0]
  adds r0, r0, #1
  adds r1, r1, #1
  subs r2, r2, #1
  bpl  3b
  b    1b
4:
  bx lr

  .section .segger.init.__SEGGER_init_zpak, "ax"
  .code 16
  .balign 2
  .global __SEGGER_init_zpak
.thumb_func
__SEGGER_init_zpak:
  ldr  r0, [r4]      @ destination
  ldr  r1, [r4, #4]  @ source stream
  ldr  r2, [r4, #8]  @ size
  adds r4, r4, #12   @ skip table entries
1:
  ldrb r3, [r1]      @ get control byte from source stream
  adds r1, r1, #1
  movs r6, #8
2:
  movs r5, #0        @ prepare zero filler
  lsrs r3, r3, #1    @ get byte control flag
  bcs  3f            @ carry set -> zero filler
  ldrb r5, [r1]      @ get literal byte from source stream
  adds r1, r1, #1
3:
  strb r5, [r0]      @ store initialization byte
  adds r0, r0, #1
  subs r2, r2, #1    @ size -= 1
  beq  4f            @ exit when destination filled
  subs r6, r6, #1    @ decrement bit count
  bne  2b            @ still within this control byte
  b    1b            @ get next control byte
4:
  bx   lr

#ifndef APP_ENTRY_POINT
#define APP_ENTRY_POINT main
#endif

#ifndef ARGSSPACE
#define ARGSSPACE 128
#endif

  .global _start
  .extern APP_ENTRY_POINT
  .global exit
  .weak exit

#ifdef INITIALIZE_USER_SECTIONS
  .extern InitializeUserMemorySections
#endif

  .section .init, "ax"
  .code 16
  .align 1
  .thumb_func

_start:
  ldr r0, = __stack_end__
  mov sp, r0
  ldr r4, =__SEGGER_init_table__
1:
  ldr r0, [r4]
  adds r4, r4, #4
  tst r0, r0
  beq 2f
  blx r0
  b 1b
2:

#if !defined(__HEAP_SIZE__) || (__HEAP_SIZE__)
  /* 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:
#endif

#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

  // default C/C++ library helpers

.macro HELPER helper_name
  .section .text.\helper_name, "ax", %progbits
  .global \helper_name
  .align 1
  .weak \helper_name
  .thumb_func
\helper_name:
.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 abort
  b .
HELPER __assert
  b .
HELPER __assert_func
  b .
HELPER __aeabi_assert
  b .
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
