# This module initializes BSS section, stack pointers and interrupts for each mode, 
# and finally branches to main in the C library (which eventually calls main()).
#
# On reset, the ARM core starts up in Supervisor (SVC) mode, in ARM state, with IRQ and FIQ disabled.

# --- Standard definitions of mode bits and interrupt (I & F) flags in PSRs

        .equ    Mode_USR,   0x10
        .equ    Mode_FIQ,   0x11
        .equ    Mode_IRQ,   0x12
        .equ    Mode_SVC,   0x13
        .equ    Mode_ABT,   0x17
        .equ    Mode_UNDEF, 0x1B
        .equ    Mode_SYS,   0x1F   /* available on ARM Arch 4 and later */

        .equ    I_Bit, 0x80        /* when I bit is set, IRQ is disabled */
        .equ    F_Bit, 0x40        /* when F bit is set, FIQ is disabled */


# --- System memory locations

        .equ    RAM_Limit,  0x40010000     /* RAM: 0x40000000 .. 0x4000FFFF (Internal 64kB RAM) */

        .equ    SVC_Stack,  RAM_Limit      /* 256 byte SVC stack at top of memory */
        .equ    IRQ_Stack,  RAM_Limit-256  /* followed by IRQ stack */
# add FIQ_Stack, ABT_Stack, UNDEF_Stack here if you need them
        .equ    USR_Stack,  IRQ_Stack-256  /* followed by USR stack */


        .text

        .global Reset_Handler

Reset_Handler:

# --- Initialise stack pointer registers
# Enter SVC mode and set up the SVC stack pointer
        MSR     CPSR_c, #Mode_SVC|I_Bit|F_Bit  /* No interrupts */
        LDR     SP, =SVC_Stack

# Enter IRQ mode and set up the IRQ stack pointer
        MSR     CPSR_c, #Mode_IRQ|I_Bit|F_Bit  /* No interrupts */
        LDR     SP, =IRQ_Stack

# Set up other stack pointers if necessary
#       ; ...

# --- Initialise memory system
#       ; ...

# --- Initialise critical IO devices
#       ; ...

# --- Initialise interrupt system variables here
#       ; ...

# --- Now change to User mode and set up User mode stack.
        MSR     CPSR_c, #Mode_USR|F_Bit  /* FIQ disabled, IRQ enabled */
        LDR     SP, =USR_Stack

	/* Setup a default stack-limit in-case the code has been
	   compiled with "-mapcs-stack-check".  Hard-wiring this value
	   is not ideal, since there is currently no support for
	   checking that the heap and stack have not collided, or that
	   this default 4k is enough for the program being executed. */
	SUB	sl, SP, #4 << 10	/* Still assumes 256bytes below sl */

# --- Initialize BSS Section
	MOV 	a2, #0			/* Second arg: fill value */
	MOV	fp, a2			/* Null frame pointer */
	MOV	R7, a2			/* Null frame pointer for Thumb */
	
	LDR	a1, .LC1		/* First arg: start of memory block */
	LDR	a3, .LC2	
	SUB	a3, a3, a1		/* Third arg: length of block */
	BL	memset

# --- Now enter the C code
	BL	main

	BL	exit		        /* Should not return */

	
	.align 0
.LC1:
	.word	__bss_start__
.LC2:
	.word	__bss_end__


        .global __gccmain
__gccmain:
	MOV	PC, LR

        .end

