.globl  _start
.globl  _start_background
.globl  _exit
.globl  __eabi


#ifdef BOOT_FROM_FLASH
.text
.section .rhcw,"a"	    # Reset configuration half word (RCHW)
# ifdef __PPC_VLE__
	.long	0x015a0000  # Magic BOOT_ID for Freescale VLE code
# else
	.long	0x005a0000  # Magic BOOT_ID for Power Architecture code
# endif
	.long	_start
#endif




# ifdef __PPC_VLE__

.macro bdnz target
	e_bdnz	\target
.endm

.macro li32 reg,imm
	e_lis 	\reg,\imm@h
	e_or2i	\reg,\imm@l
.endm

.macro ivor spr,reg,imm
	e_lis 	\reg,0
	e_or2i	\reg,\imm@l
	mtspr 	\spr,\reg
.endm

#else

.macro li32 reg,imm
	lis   	\reg,\imm@h
	ori   	\reg,\reg,\imm@l
.endm

.macro ivor spr,reg,imm
	lis   	\reg,0
	ori   	\reg,\reg,\imm@l   # "li reg,\imm@l" should work too
	mtspr 	\spr,\reg
.endm

#endif



.text
.section .start,"xa"
_start:
	li   	r0,0
	li   	r1,0
	li   	r2,0
	li   	r3,0
	li   	r4,0
	li   	r5,0
	li   	r6,0
	li   	r7,0
	li   	r8,0
	li   	r9,0
	li   	r10,0
	li   	r11,0
	li   	r12,0
	li   	r13,0
	li   	r14,0
	li   	r15,0
	li   	r16,0
	li   	r17,0
	li   	r18,0
	li   	r19,0
	li   	r20,0
	li   	r21,0
	li   	r22,0
	li   	r23,0
	li   	r24,0
	li   	r25,0
	li   	r26,0
	li   	r27,0
	li   	r28,0
	li   	r29,0
	li   	r30,0
	li   	r31,0

init_stackpointer:
	li32 	sp,__stack_end

init_int_vector_prefix:
	li32 	r3,IVOR0_entry
	mtspr	63,r3     # IVPR

# ifdef __PPC_VLE__
check_cpu:
	mfspr	r7,287    # read Processor Version Register (PVR)
	srwi 	r7,r7,20  # get only upper 12 bit, which contain Manuf.ID and processor type fields
	cmpwi	r7,0x817  # check if it's an Freescale e200z0 core (0b100000010111)
	e_beq	end_mmu   # for e200z0 branch over initialization of Interrupt Vector Offset table (hardwired) and MMU (MMU not available)
#endif

init_int_vector_offsets:
	ivor 	400,r3,IVOR0_entry    # IVOR0
	ivor 	401,r3,IVOR1_entry    # IVOR1
	ivor 	402,r3,IVOR2_entry    # IVOR2
	ivor 	403,r3,IVOR3_entry    # IVOR3
	ivor 	404,r3,IVOR4_entry    # IVOR4
	ivor 	405,r3,IVOR5_entry    # IVOR5
	ivor 	406,r3,IVOR6_entry    # IVOR6
	ivor 	407,r3,IVOR7_entry    # IVOR7
	ivor 	408,r3,IVOR8_entry    # IVOR8
	ivor 	409,r3,IVOR9_entry    # IVOR9
	ivor 	410,r3,IVOR10_entry   # IVOR10
	ivor 	411,r3,IVOR11_entry   # IVOR11
	ivor 	412,r3,IVOR12_entry   # IVOR12
	ivor 	413,r3,IVOR13_entry   # IVOR13
	ivor 	414,r3,IVOR14_entry   # IVOR14
	ivor 	415,r3,IVOR15_entry   # IVOR15
	ivor 	528,r3,IVOR32_entry   # IVOR32
	ivor 	529,r3,IVOR33_entry   # IVOR33
	ivor 	530,r3,IVOR34_entry   # IVOR34

#ifdef BOOT_FROM_FLASH

init_mmu:
	li32 	r4,__tlbdata_size
	mtctr	r4
	li32 	r4,__tlbdata_start
	subi 	r4,r4,4
init_mmu_loop:
	lwzu 	r3, 4(r4)
	mtspr	624,r3         # MAS0
	lwzu 	r3, 4(r4)
	mtspr	625,r3         # MAS1
	lwzu 	r3, 4(r4)
	mtspr	626,r3         # MAS2
	lwzu 	r3, 4(r4)
	mtspr	627,r3         # MAS3
	tlbwe
	isync
	bdnz 	init_mmu_loop
#endif
end_mmu:

disable_watchdog:
	li32 	r4,0xFFF38000  #Software Watchdog Timer (SWT) base address
	li32 	r3,0xC520
	stw  	r3,0x10(r4)    # SWT_SR : 1st magic word to clear the soft lock bit
	li32 	r3,0xD928
	stw  	r3,0x10(r4)    # SWT_SR : 2nd magic word to clear the soft lock bit
	li32 	r3,0xC000011A
	stw  	r3,0x00(r4)    # SWT_CR : disable watchdog and set soft lock bit

	bl   	init_memory

gomain:
#ifdef T32_FDX_TRACE
	bl   	T32_Fdx_TraceInit
	bl   	T32_Fdx_TimerInit
#endif
	li   	r3,0
	li   	r4,0
	li   	r5,0
	bl   	main

_exit:
	b    	_exit


init_memory:
#ifdef BOOT_FROM_FLASH
init_sram:
	# Init ECC of SRAM (and clear BSS section at the same time)
	# For ECC we wouldn't care about the content of the registers,
	# but for the BSS section we're lucky that we've set r16-r31 to zero before
	li32 	r3,__SRAM_start
	li32 	r4,__SRAM_size
	srwi 	r4,r4,6        # divide size of SRAM by 64=16*4 (16-Registers with 4 Bytes)
	mtctr	r4
init_sram_loop:
	stmw 	r16,0(r3)      # write r16-r31 to SRAM to initialize ECC
	addi 	r3,r3,64
	bdnz 	init_sram_loop

init_data:
	li32 	r3,__data_vaddr
	li32 	r4,__data_laddr
	li32 	r5,__data_size
	mflr  	r31
	bl   	memcpy
	mtlr  	r31
#else

init_stack:
	li   	r0,0
	stw  	r0,0(sp)       # clear Back Chain Word
bss_clear:
	li32 	r3,__bss_start
	li32 	r4,__bss_size
	cmpwi	r4,0
	beq  	gomain
	srwi 	r4,r4,2
	mtctr	r4
	subi 	r3,r3,4
bss_clear_loop:
	stwu 	r0,4(r3)
	bdnz 	bss_clear_loop
#endif
	blr


init_calypso:
	# Turn off SWTs
	li32 	r5,0xC520
	li32 	r6,0xD928
	li32 	r7,0xFF00010A

	# SWT0
	li32 	r4,0xFC050000
	stw  	r5,0x10(r4)
	stw  	r6,0x10(r4)
	stw  	r7,0x00(r4)
	
	# SWT1
	li32 	r4,0xFC054000
	stw  	r5,0x10(r4)
	stw  	r6,0x10(r4)
	stw  	r7,0x00(r4)

	# SWT2
	li32 	r4,0xFC058000
	stw  	r5,0x10(r4)
	stw  	r6,0x10(r4)
	stw  	r7,0x00(r4)

	bl   	init_memory
#ifndef BOOT_FROM_FLASH
	bl   	Sys_Init
	bl   	SIUL2_Init
#endif
	b    	gomain


__eabi:
	blr


.align  2
_start_background:    # very reduced start-sequence for secondary core of a Bolero3M
	li32 	r0,_sp_background
	lwz  	sp,0(r0)        # load initial value of stack pointer from memory
	li   	r0,0
	stw  	r0,0(sp)        # clear Back Chain Word
	bl   	background
	b    	_exit


.align  2
_sp_background:
	.long	0x40020000


#ifdef BOOT_FROM_FLASH
.rodata
.section .mmudata,"a"
__tlbdata_start:
	/*** TLB1 entry 0 -> FLASH ***/
	.long	0x10000000  # MAS0: ESL 0
	.long	0x80000600  # MAS1: valid, no-protect, global, 4 MB
# ifdef __PPC_VLE__
	.long	0x00000020  # MAS2: log.addr.0x00000000, big-endian, VLE
# else
	.long	0x00000000  # MAS2: log.addr.0x00000000, big-endian
# endif
	.long	0x0000003F  # MAS3: phy.addr.0x00000000, full-access
	/*** TLB1 entry 1 -> SRAM  ***/
	.long	0x10010000  # MAS0: ESL 1
	.long	0x80000400  # MAS1: valid, no-protect, global, 256 KBytes
	.long	0x40000000  # MAS2: log.addr.0x40000000, big-endian
	.long	0x4000003F  # MAS3: phy.addr.0x40000000, full-access
	/*** TLB1 entry 2 -> Flash configuration ***/
	.long	0x10020000  # MAS0: ESL 2
	.long	0xC0000500  # MAS1: valid, no-protect, global, 1 MB
	.long	0xC3F0000A  # MAS2: log.addr.0xC3F00000, cache-inhibited, guarded (no speculative access), big-endian
	.long	0xC3F0003F  # MAS3: phy.addr.0xC3F00000, full-access
	/*** TLB1 entry 3 -> Peripherals ***/
	.long	0x10030000  # MAS0: ESL 3
	.long	0xC0000500  # MAS1: valid, no-protect, global, 1 MB
	.long	0xFFF0000A  # MAS2: log.addr.0xFFF00000, cache-inhibited, guarded (no speculative access), big-endian
	.long	0xFFF0003F  # MAS3: phy.addr.0xFFF00000, full-access
	/*** TLB1 entry 4 -> disable default entry of SPC564A80-V2 ***/
	.long	0x10040000  # MAS0: ESL 4
	.long	0x00000000  # MAS1: invalid 
	.long	0x00000000  # MAS2 
	.long	0x00000000  # MAS3 
__tlbdata_end:
	.set __tlbdata_size, (__tlbdata_end-__tlbdata_start)/16
#endif


.section .ivec,"xa"  # for e200z0 cores this section must be aligned to 4096 bytes (since this e200z0 has a hardwired Interrupt Vector Offset table)
.align  4
IVOR0_entry:  #Critical Input
	nop
	nop
	nop
	b IVOR0_entry

.align  4
IVOR1_entry:  #Machine Check
	nop
	nop
	nop
	b IVOR1_entry

.align  4
IVOR2_entry:  #Data Storage
	nop
	nop
	nop
	b IVOR2_entry

.align  4
IVOR3_entry:  #Instruction Storage
	nop
	nop
	nop
	b IVOR3_entry

.align  4
IVOR4_entry:  #External Input
	nop
	nop
	nop
	b IVOR4_entry

.align  4
IVOR5_entry:  #Alignment
	nop
	nop
	nop
	b IVOR5_entry

.align  4
IVOR6_entry:  #Program
	nop
	nop
	nop
	b IVOR6_entry

.align  4
IVOR7_entry:  #Floating-Point Unavailable
	nop
	nop
	nop
	b IVOR7_entry

.align  4
IVOR8_entry:  #System Call
	nop
	nop
	nop
	b IVOR8_entry

.align  4
IVOR9_entry:  #Auxiliary Processor Unavailable
	nop
	nop
	nop
	b IVOR9_entry

.align  4
IVOR10_entry:  #Decrementer
	nop
	nop
	nop
	b IVOR10_entry

.align  4
IVOR11_entry:  #Fixed Interval Timer
	nop
	nop
	nop
	b IVOR11_entry

.align  4
IVOR12_entry:  #Watchdog
	nop
	nop
	nop
	b IVOR12_entry

.align  4
IVOR13_entry:  #Data TLB Error
	nop
	nop
	nop
	b IVOR13_entry

.align  4
IVOR14_entry:  #Instruction TLB Error
	nop
	nop
	nop
	b IVOR14_entry

.align  4
IVOR15_entry:  #Debug
	nop
	nop
	nop
	b IVOR15_entry

.align  4
IVOR32_entry:  #SPE APU unavailable
	nop
	nop
	nop
	b IVOR15_entry

.align  4
IVOR33_entry:  #SPE Floating-point Data
	nop
	nop
	nop
	b IVOR15_entry

.align  4
IVOR34_entry:  #SPE Floating-point Round
	nop
	nop
	nop
	b IVOR15_entry

