#include "swi.h"
#define Mode_USR 0x10
#define Mode_IRQ 0x12
#define Mode_SVC 0x13
#define I_Bit 0x80
#define F_Bit 0x40

#define RAM_Limit __stack_base
#define IRQ_Stack RAM_Limit 
#define SVC_Stack RAM_Limit-1024 
#define USR_Stack SVC_Stack-1024 
#define AT91_EBI  0xFFE00000
        
        .text
        .code 32
        .align 0

        .global _mainCRTStartup
        .global _start
        .global start
start:
_start:
_mainCRTStartup:
        ldr r10, PtImageMemorySelect
        
        movs        r0, pc, LSR #20
        moveq       r10, r10, LSL #12
        moveq       r10, r10, LSR #12
        
        ldmia       r10!, {r0-r9,r11-r12}           
        stmia       r11!, {r0-r9}
        mov         pc, r12  

JumpAddress: 

	MOV R8, #0
	ADR R9, Vector_Init_Block
	LDMIA R9!, {R0-R7}
	STMIA R8!, {R0-R7}
	LDMIA R9!, {R0-R7}
	STMIA R8!, {R0-R7}
	
Vector_Init_Block:
	LDR PC, Reset_ADDR
	LDR PC, Undefined_ADDR
	LDR PC, SWI_ADDR
	LDR PC, Prefetch_ADDR
	LDR PC, Abort_ADDR
	NOP
	LDR PC, IRQ_ADDR
	LDR PC, FIQ_ADDR

Reset_ADDR:
	.word start_art
Undefined_ADDR:
	.word Undefined_Handler
SWI_ADDR:
	.word SWI_Handler
Prefetch_ADDR:
	.word Prefetch_Handler
Abort_ADDR:
	.word Abort_Handler
Reserve:
	.word 0
IRQ_ADDR:
	.word IRQ_Handler
FIQ_ADDR:
	.word FIQ_Handler


start_art:	

	/*Enter IRQ mode and set up the IRQ stack pointer*/
	MOV R0, #Mode_IRQ|I_Bit|F_Bit 
	MSR CPSR_c, R0
	LDR R13, =IRQ_Stack
	
	/*Enter SVC mode and set up the SVC stack pointer*/
        MOV R0, #Mode_SVC|I_Bit|F_Bit 
	MSR CPSR_c, R0
	LDR R13, =SVC_Stack
	
	/*Enable interrupt*/
	MOV R0, #Mode_SVC|F_Bit 
	MSR CPSR_c, R0
        
        /*Enter USR mode and set up the USR stack pointer*/
        MOV R0, #Mode_USR|I_Bit|F_Bit
	MSR CPSR_c, R0
	LDR sp, =USR_Stack


        sub sl, sp, #64 << 10


        ldr r0, =software_init_hook
        cmp r0, #0x0

        bxne r0


        ldr r0, =__rom_image
        cmp r0, #0x0
        bleq SKIP_DO_COPY

        ldr r0, =__data_start
        ldr r1, =_edata
        ldr r3, =__erom
DO_COPY:
        ldr r2, [r3], #0x4
        str r2, [r0], #0x4
        cmp r0, r1
        bcc DO_COPY


SKIP_DO_COPY:
        mov a2, #0
        mov fp, a2
        mov r7, a2

        ldr a1, .LC1
        ldr a3, .LC2
        sub a3, a3, a1

        bl memset

        mov r0, #0
        mov r1, #0

        mov r4, r0
        mov r5, r1
//        ldr r0, .Lfini
        bl atexit
//        bl _init
        mov r0, r4
        mov r1, r5

        bl main

        bl exit

        .align 0
.LC0:

.LC1:
        .word __bss_start__
.LC2:
        .word __bss_end__

/*
.Lfini:
        .word _fini
*/
PtImageMemorySelect:
            .word         ImageMemorySelect
    
ImageMemorySelect:
            .word         0x01002529  @ 0x01000000, 16MB,  2 cycles added after transfer, 16-bit, 6 wait states
            .word         0x022028a1  @ 0x02000000, 16MB, 0x02002121  0 cycles added after transfer, 16-bit, 1 wait state
            .word         0x03002529  @ unused
            .word         0x40000000  @ unused
            .word         0x02402021	@ unused	,CS 4 
            .word         0x02502021	@ unused	,CS 5
            .word         0x60000000  @ unused
            .word         0x70000000  @ unused
            .word         0x00000001  @ REMAP commande
            .word         0x00000006  @ 7 memory regions, standard read
            .word         AT91_EBI    @ EBI address
            .word         JumpAddress @ address where to jump
            
Undefined_Handler:
	b  Undefined_Handler
SWI_Handler:
	b  SWI_Handler
Prefetch_Handler: 
	b  Prefetch_Handler
Abort_Handler:
        b  Abort_Handler     
IRQ_Handler:
     	b  IRQ_Handler
FIQ_Handler:      
	b  FIQ_Handler


