        .global main                    // int main(void)
/*
 * Some defines for the program status registers
 */
   ARM_MODE_USER  = 0x10      /* Normal User Mode                             */ 
   ARM_MODE_FIQ   = 0x11      /* FIQ Fast Interrupts Mode                     */
   ARM_MODE_IRQ   = 0x12      /* IRQ Standard Interrupts Mode                 */
   ARM_MODE_SVC   = 0x13      /* Supervisor Interrupts Mode                   */
   ARM_MODE_ABORT = 0x17      /* Abort Processing memory Faults Mode          */
   ARM_MODE_UNDEF = 0x1B      /* Undefined Instructions Mode                  */
   ARM_MODE_SYS   = 0x1F      /* System Running in Priviledged Operating Mode */
   ARM_MODE_MASK  = 0x1F
   
   I_BIT          = 0x80      /* disable IRQ when I bit is set */
   F_BIT          = 0x40      /* disable IRQ when I bit is set */

        .text
        .code 32
        .align 2
        .func  _boot
_boot:   

// Runtime Interrupt Vectors
// -------------------------
Vectors:
        b     _start                    // reset - _start
        ldr   pc, _undf
        ldr   pc, _swi
        ldr   pc, _pabt
        ldr   pc, _dabt
        nop    
        ldr   pc, _irq	 
        ldr   pc, _fiq
        
// Use this group for development
_undf:  .word __undf                    // undefined
_swi:   .word __swi                     // SWI
_pabt:  .word __pabt                    // program abort
_dabt:  .word __dabt                    // data abort
_irq:   .word __irq                     // IRQ
_fiq:   .word __fiq                     // FIQ

__undf: b     .                         // undefined
__swi:  b     .                         // SWI
__pabt: b     .                         // program abort
__dabt: b     .                         // data abort
__fiq:  b     .                         // FIQ
__irq:  b     .                         // enter InterruptHandler


        .size _boot, . - _boot
        .endfunc


// Setup the operating mode & stack.
// ---------------------------------
        .global _start
        .func   _start

_start:

  //*****************************************************************************
  // Disable MMU and caches
  //*****************************************************************************/
        mov r0, #0
        mcr p15, 0, r0, c7, c7, 0    // Invalidate ICache and DCache 
        mcr p15, 0, r0, c7, c10, 4   // Drain write buffer 
        mcr p15, 0, r0, c8, c7, 0    // Invalidate I & D TLBs 
        mrc p15, 0, r0, c1, c0, 0    // Read MMU control register 
        bic r0, r0, #0x00001000      // Disable ICache 
        bic r0, r0, #0x00000007      // Disable DCache, MMU and alignment fault 
#ifdef __BIG_ENDIAN
        orr r0, r0, #0x00000080      // Set B bit
#else
        bic r0, r0, #0x00000080      // Clear B bit
#endif
        mcr p15, 0, r0, c1, c0, 0    // Write MMU control register


// Initialize Interrupt System
// - Set stack location for each mode
// - Leave in System Mode with Interrupts Disabled    
   		msr   CPSR_c, #ARM_MODE_UNDEF | I_BIT | F_BIT   /* Undefined Instruction Mode */     
   		ldr   sp, =__stack_und_end
   
   		msr   CPSR_c, #ARM_MODE_ABORT | I_BIT | F_BIT   /* Abort Mode */
   		ldr   sp, =__stack_abt_end
   
   		msr   CPSR_c, #ARM_MODE_FIQ | I_BIT | F_BIT     /* FIQ Mode */   
   		ldr   sp, =__stack_fiq_end
   
   		msr   CPSR_c, #ARM_MODE_IRQ | I_BIT | F_BIT     /* IRQ Mode */   
   		ldr   sp, =__stack_irq_end
   
   		msr   CPSR_c, #ARM_MODE_SVC | I_BIT | F_BIT     /* Supervisor Mode */
   		ldr   sp, =__stack_svc_end

// Copy initialized data to its execution address in RAM
// -----------------------------------------------------
#ifdef ROM_RUN
        ldr   r1,=_etext                // -> ROM data start
        ldr   r2,=_data                 // -> data start
        ldr   r3,=_edata                // -> end of data
1:      cmp   r2,r3                     // check if data to move
        ldrlo r0,[r1],#4                // copy it
        strlo r0,[r2],#4
        blo   1b                        // loop until done
#endif
// Clear .bss
// ----------
        mov   r0,#0                     // get a zero
        ldr   r1,=__bss_start__         // -> bss start
        ldr   r2,=__bss_end__           // -> bss end
2:      cmp   r1,r2                     // check if data to clear
        strlo r0,[r1],#4                // clear 4 bytes
        blo   2b                        // loop until done
		
	  	ldr   r0, =__ctors_start__
	  	ldr   r1, =__ctors_end__
ctor_loop:
        cmp   r0, r1
        beq   ctor_end
	  	ldr   r2, [r0], #4
	  	stmfd sp!, {r0-r1}
	  	mov   lr, pc
	  	mov   pc, r2
	  	ldm   sp!, {r0-r1}
	  	b 	  ctor_loop
ctor_end:

// Call main program: main(0)
// --------------------------
        mov   r0,#0                     // no arguments (argc = 0)
        mov   r1,r0
        mov   r2,r0
        mov   fp,r0                     // null frame pointer
        mov   r7,r0                     // null frame pointer for thumb
        ldr   r10,=main
        mov   lr,pc
        bx    r10                       // enter main()

/* "global object"-dtors are never called and it should not be 
   needed since there is no OS to exit to. */
  
        .endfunc

        .global _reset
        .func   _reset
_reset:
        b     .                         // loop until reset

        .endfunc

        .end
