| /* head.S: kernel entry point for FR-V kernel | 
 |  * | 
 |  * Copyright (C) 2003, 2004 Red Hat, Inc. All Rights Reserved. | 
 |  * Written by David Howells (dhowells@redhat.com) | 
 |  * | 
 |  * This program is free software; you can redistribute it and/or | 
 |  * modify it under the terms of the GNU General Public License | 
 |  * as published by the Free Software Foundation; either version | 
 |  * 2 of the License, or (at your option) any later version. | 
 |  */ | 
 |  | 
 | #include <linux/init.h> | 
 | #include <linux/threads.h> | 
 | #include <linux/linkage.h> | 
 | #include <asm/thread_info.h> | 
 | #include <asm/ptrace.h> | 
 | #include <asm/page.h> | 
 | #include <asm/spr-regs.h> | 
 | #include <asm/mb86943a.h> | 
 | #include <asm/cache.h> | 
 | #include "head.inc" | 
 |  | 
 | ############################################################################### | 
 | # | 
 | # void _boot(unsigned long magic, char *command_line) __attribute__((noreturn)) | 
 | # | 
 | # - if magic is 0xdead1eaf, then command_line is assumed to point to the kernel | 
 | #   command line string | 
 | # | 
 | ############################################################################### | 
 | 	__HEAD | 
 | 	.balign		4 | 
 |  | 
 | 	.globl		_boot, __head_reference | 
 |         .type		_boot,@function | 
 | _boot: | 
 | __head_reference: | 
 | 	sethi.p		%hi(LED_ADDR),gr30 | 
 | 	setlo		%lo(LED_ADDR),gr30 | 
 |  | 
 | 	LEDS		0x0000 | 
 |  | 
 | 	# calculate reference address for PC-relative stuff | 
 | 	call		0f | 
 | 0:	movsg		lr,gr26 | 
 | 	addi		gr26,#__head_reference-0b,gr26 | 
 |  | 
 | 	# invalidate and disable both of the caches and turn off the memory access checking | 
 | 	dcef		@(gr0,gr0),1 | 
 | 	bar | 
 |  | 
 | 	sethi.p		%hi(~(HSR0_ICE|HSR0_DCE|HSR0_CBM|HSR0_EIMMU|HSR0_EDMMU)),gr4 | 
 | 	setlo		%lo(~(HSR0_ICE|HSR0_DCE|HSR0_CBM|HSR0_EIMMU|HSR0_EDMMU)),gr4 | 
 | 	movsg		hsr0,gr5 | 
 | 	and		gr4,gr5,gr5 | 
 | 	movgs		gr5,hsr0 | 
 | 	movsg		hsr0,gr5 | 
 |  | 
 | 	LEDS		0x0001 | 
 |  | 
 | 	icei		@(gr0,gr0),1 | 
 | 	dcei		@(gr0,gr0),1 | 
 | 	bar | 
 |  | 
 | 	# turn the instruction cache back on | 
 | 	sethi.p		%hi(HSR0_ICE),gr4 | 
 | 	setlo		%lo(HSR0_ICE),gr4 | 
 | 	movsg		hsr0,gr5 | 
 | 	or		gr4,gr5,gr5 | 
 | 	movgs		gr5,hsr0 | 
 | 	movsg		hsr0,gr5 | 
 |  | 
 | 	bar | 
 |  | 
 | 	LEDS		0x0002 | 
 |  | 
 | 	# retrieve the parameters (including command line) before we overwrite them | 
 | 	sethi.p		%hi(0xdead1eaf),gr7 | 
 | 	setlo		%lo(0xdead1eaf),gr7 | 
 | 	subcc		gr7,gr8,gr0,icc0 | 
 | 	bne		icc0,#0,__head_no_parameters | 
 |  | 
 | 	sethi.p		%hi(redboot_command_line-1),gr6 | 
 | 	setlo		%lo(redboot_command_line-1),gr6 | 
 | 	sethi.p		%hi(__head_reference),gr4 | 
 | 	setlo		%lo(__head_reference),gr4 | 
 | 	sub		gr6,gr4,gr6 | 
 | 	add.p		gr6,gr26,gr6 | 
 | 	subi		gr9,#1,gr9 | 
 | 	setlos.p	#511,gr4 | 
 | 	setlos		#1,gr5 | 
 |  | 
 | __head_copy_cmdline: | 
 | 	ldubu.p		@(gr9,gr5),gr16 | 
 | 	subicc		gr4,#1,gr4,icc0 | 
 | 	stbu.p		gr16,@(gr6,gr5) | 
 | 	subicc		gr16,#0,gr0,icc1 | 
 | 	bls		icc0,#0,__head_end_cmdline | 
 | 	bne		icc1,#1,__head_copy_cmdline | 
 | __head_end_cmdline: | 
 | 	stbu		gr0,@(gr6,gr5) | 
 | __head_no_parameters: | 
 |  | 
 | ############################################################################### | 
 | # | 
 | # we need to relocate the SDRAM to 0x00000000 (linux) or 0xC0000000 (uClinux) | 
 | # - note that we're going to have to run entirely out of the icache whilst | 
 | #   fiddling with the SDRAM controller registers | 
 | # | 
 | ############################################################################### | 
 | #ifdef CONFIG_MMU | 
 | 	call		__head_fr451_describe_sdram | 
 |  | 
 | #else | 
 | 	movsg		psr,gr5 | 
 | 	srli		gr5,#28,gr5 | 
 | 	subicc		gr5,#3,gr0,icc0 | 
 | 	beq		icc0,#0,__head_fr551_sdram | 
 |  | 
 | 	call		__head_fr401_describe_sdram | 
 | 	bra		__head_do_sdram | 
 |  | 
 | __head_fr551_sdram: | 
 | 	call		__head_fr555_describe_sdram | 
 | 	LEDS		0x000d | 
 |  | 
 | __head_do_sdram: | 
 | #endif | 
 |  | 
 | 	# preload the registers with invalid values in case any DBR/DARS are marked not present | 
 | 	sethi.p		%hi(0xfe000000),gr17		; unused SDRAM DBR value | 
 | 	setlo		%lo(0xfe000000),gr17 | 
 | 	or.p		gr17,gr0,gr20 | 
 | 	or		gr17,gr0,gr21 | 
 | 	or.p		gr17,gr0,gr22 | 
 | 	or		gr17,gr0,gr23 | 
 |  | 
 | 	# consult the SDRAM controller CS address registers | 
 | 	cld		@(gr14,gr0 ),gr20,	cc0,#1	; DBR0 / DARS0 | 
 | 	cld		@(gr14,gr11),gr21,	cc1,#1	; DBR1 / DARS1 | 
 | 	cld		@(gr14,gr12),gr22,	cc2,#1	; DBR2 / DARS2 | 
 | 	cld.p		@(gr14,gr13),gr23,	cc3,#1	; DBR3 / DARS3 | 
 |  | 
 | 	sll		gr20,gr15,gr20			; shift values up for FR551 | 
 | 	sll		gr21,gr15,gr21 | 
 | 	sll		gr22,gr15,gr22 | 
 | 	sll		gr23,gr15,gr23 | 
 |  | 
 | 	LEDS		0x0003 | 
 |  | 
 | 	# assume the lowest valid CS line to be the SDRAM base and get its address | 
 | 	subcc		gr20,gr17,gr0,icc0 | 
 | 	subcc.p		gr21,gr17,gr0,icc1 | 
 | 	subcc		gr22,gr17,gr0,icc2 | 
 | 	subcc.p		gr23,gr17,gr0,icc3 | 
 | 	ckne		icc0,cc4			; T if DBR0 != 0xfe000000 | 
 | 	ckne		icc1,cc5 | 
 | 	ckne		icc2,cc6 | 
 | 	ckne		icc3,cc7 | 
 | 	cor		gr23,gr0,gr24,		cc7,#1	; GR24 = SDRAM base | 
 | 	cor		gr22,gr0,gr24,		cc6,#1 | 
 | 	cor		gr21,gr0,gr24,		cc5,#1 | 
 | 	cor		gr20,gr0,gr24,		cc4,#1 | 
 |  | 
 | 	# calculate the displacement required to get the SDRAM into the right place in memory | 
 | 	sethi.p		%hi(__sdram_base),gr16 | 
 | 	setlo		%lo(__sdram_base),gr16 | 
 | 	sub		gr16,gr24,gr16			; delta = __sdram_base - DBRx | 
 |  | 
 | 	# calculate the new values to go in the controller regs | 
 | 	cadd.p		gr20,gr16,gr20,		cc4,#1	; DCS#0 (new) = DCS#0 (old) + delta | 
 | 	cadd		gr21,gr16,gr21,		cc5,#1 | 
 | 	cadd.p		gr22,gr16,gr22,		cc6,#1 | 
 | 	cadd		gr23,gr16,gr23,		cc7,#1 | 
 |  | 
 | 	srl		gr20,gr15,gr20			; shift values down for FR551 | 
 | 	srl		gr21,gr15,gr21 | 
 | 	srl		gr22,gr15,gr22 | 
 | 	srl		gr23,gr15,gr23 | 
 |  | 
 | 	# work out the address at which the reg updater resides and lock it into icache | 
 | 	# also work out the address the updater will jump to when finished | 
 | 	sethi.p		%hi(__head_move_sdram-__head_reference),gr18 | 
 | 	setlo		%lo(__head_move_sdram-__head_reference),gr18 | 
 | 	sethi.p		%hi(__head_sdram_moved-__head_reference),gr19 | 
 | 	setlo		%lo(__head_sdram_moved-__head_reference),gr19 | 
 | 	add.p		gr18,gr26,gr18 | 
 | 	add		gr19,gr26,gr19 | 
 | 	add.p		gr19,gr16,gr19			; moved = addr + (__sdram_base - DBRx) | 
 | 	add		gr18,gr5,gr4			; two cachelines probably required | 
 |  | 
 | 	icpl		gr18,gr0,#1			; load and lock the cachelines | 
 | 	icpl		gr4,gr0,#1 | 
 | 	LEDS		0x0004 | 
 | 	membar | 
 | 	bar | 
 | 	jmpl		@(gr18,gr0) | 
 |  | 
 | 	.balign		L1_CACHE_BYTES | 
 | __head_move_sdram: | 
 | 	cst		gr20,@(gr14,gr0 ),	cc4,#1 | 
 | 	cst		gr21,@(gr14,gr11),	cc5,#1 | 
 | 	cst		gr22,@(gr14,gr12),	cc6,#1 | 
 | 	cst		gr23,@(gr14,gr13),	cc7,#1 | 
 | 	cld		@(gr14,gr0 ),gr20,	cc4,#1 | 
 | 	cld		@(gr14,gr11),gr21,	cc5,#1 | 
 | 	cld		@(gr14,gr12),gr22,	cc4,#1 | 
 | 	cld		@(gr14,gr13),gr23,	cc7,#1 | 
 | 	bar | 
 | 	membar | 
 | 	jmpl		@(gr19,gr0) | 
 |  | 
 | 	.balign		L1_CACHE_BYTES | 
 | __head_sdram_moved: | 
 | 	icul		gr18 | 
 | 	add		gr18,gr5,gr4 | 
 | 	icul		gr4 | 
 | 	icei		@(gr0,gr0),1 | 
 | 	dcei		@(gr0,gr0),1 | 
 |  | 
 | 	LEDS		0x0005 | 
 |  | 
 | 	# recalculate reference address | 
 | 	call		0f | 
 | 0:	movsg		lr,gr26 | 
 | 	addi		gr26,#__head_reference-0b,gr26 | 
 |  | 
 |  | 
 | ############################################################################### | 
 | # | 
 | # move the kernel image down to the bottom of the SDRAM | 
 | # | 
 | ############################################################################### | 
 | 	sethi.p		%hi(__kernel_image_size_no_bss+15),gr4 | 
 | 	setlo		%lo(__kernel_image_size_no_bss+15),gr4 | 
 | 	srli.p		gr4,#4,gr4			; count | 
 | 	or		gr26,gr26,gr16			; source | 
 |  | 
 | 	sethi.p		%hi(__sdram_base),gr17		; destination | 
 | 	setlo		%lo(__sdram_base),gr17 | 
 |  | 
 | 	setlos		#8,gr5 | 
 | 	sub.p		gr16,gr5,gr16			; adjust src for LDDU | 
 | 	sub		gr17,gr5,gr17			; adjust dst for LDDU | 
 |  | 
 | 	sethi.p		%hi(__head_move_kernel-__head_reference),gr18 | 
 | 	setlo		%lo(__head_move_kernel-__head_reference),gr18 | 
 | 	sethi.p		%hi(__head_kernel_moved-__head_reference+__sdram_base),gr19 | 
 | 	setlo		%lo(__head_kernel_moved-__head_reference+__sdram_base),gr19 | 
 | 	add		gr18,gr26,gr18 | 
 | 	icpl		gr18,gr0,#1 | 
 | 	jmpl		@(gr18,gr0) | 
 |  | 
 | 	.balign		32 | 
 | __head_move_kernel: | 
 | 	lddu		@(gr16,gr5),gr10 | 
 | 	lddu		@(gr16,gr5),gr12 | 
 | 	stdu.p		gr10,@(gr17,gr5) | 
 | 	subicc		gr4,#1,gr4,icc0 | 
 | 	stdu.p		gr12,@(gr17,gr5) | 
 | 	bhi		icc0,#0,__head_move_kernel | 
 | 	jmpl		@(gr19,gr0) | 
 |  | 
 | 	.balign		32 | 
 | __head_kernel_moved: | 
 | 	icul		gr18 | 
 | 	icei		@(gr0,gr0),1 | 
 | 	dcei		@(gr0,gr0),1 | 
 |  | 
 | 	LEDS		0x0006 | 
 |  | 
 | 	# recalculate reference address | 
 | 	call		0f | 
 | 0:	movsg		lr,gr26 | 
 | 	addi		gr26,#__head_reference-0b,gr26 | 
 |  | 
 |  | 
 | ############################################################################### | 
 | # | 
 | # rearrange the iomem map and set the protection registers | 
 | # | 
 | ############################################################################### | 
 |  | 
 | #ifdef CONFIG_MMU | 
 | 	LEDS		0x3301 | 
 | 	call		__head_fr451_set_busctl | 
 | 	LEDS		0x3303 | 
 | 	call		__head_fr451_survey_sdram | 
 | 	LEDS		0x3305 | 
 | 	call		__head_fr451_set_protection | 
 |  | 
 | #else | 
 | 	movsg		psr,gr5 | 
 | 	srli		gr5,#PSR_IMPLE_SHIFT,gr5 | 
 | 	subicc		gr5,#PSR_IMPLE_FR551,gr0,icc0 | 
 | 	beq		icc0,#0,__head_fr555_memmap | 
 | 	subicc		gr5,#PSR_IMPLE_FR451,gr0,icc0 | 
 | 	beq		icc0,#0,__head_fr451_memmap | 
 |  | 
 | 	LEDS		0x3101 | 
 | 	call		__head_fr401_set_busctl | 
 | 	LEDS		0x3103 | 
 | 	call		__head_fr401_survey_sdram | 
 | 	LEDS		0x3105 | 
 | 	call		__head_fr401_set_protection | 
 | 	bra		__head_done_memmap | 
 |  | 
 | __head_fr451_memmap: | 
 | 	LEDS		0x3301 | 
 | 	call		__head_fr401_set_busctl | 
 | 	LEDS		0x3303 | 
 | 	call		__head_fr401_survey_sdram | 
 | 	LEDS		0x3305 | 
 | 	call		__head_fr451_set_protection | 
 | 	bra		__head_done_memmap | 
 |  | 
 | __head_fr555_memmap: | 
 | 	LEDS		0x3501 | 
 | 	call		__head_fr555_set_busctl | 
 | 	LEDS		0x3503 | 
 | 	call		__head_fr555_survey_sdram | 
 | 	LEDS		0x3505 | 
 | 	call		__head_fr555_set_protection | 
 |  | 
 | __head_done_memmap: | 
 | #endif | 
 | 	LEDS		0x0007 | 
 |  | 
 | ############################################################################### | 
 | # | 
 | # turn the data cache and MMU on | 
 | # - for the FR451 this'll mean that the window through which the kernel is | 
 | #   viewed will change | 
 | # | 
 | ############################################################################### | 
 |  | 
 | #ifdef CONFIG_MMU | 
 | #define MMUMODE		HSR0_EIMMU|HSR0_EDMMU|HSR0_EXMMU|HSR0_EDAT|HSR0_XEDAT | 
 | #else | 
 | #define MMUMODE		HSR0_EIMMU|HSR0_EDMMU | 
 | #endif | 
 |  | 
 | 	movsg		hsr0,gr5 | 
 |  | 
 | 	sethi.p		%hi(MMUMODE),gr4 | 
 | 	setlo		%lo(MMUMODE),gr4 | 
 | 	or		gr4,gr5,gr5 | 
 |  | 
 | #if defined(CONFIG_FRV_DEFL_CACHE_WTHRU) | 
 | 	sethi.p		%hi(HSR0_DCE|HSR0_CBM_WRITE_THRU),gr4 | 
 | 	setlo		%lo(HSR0_DCE|HSR0_CBM_WRITE_THRU),gr4 | 
 | #elif defined(CONFIG_FRV_DEFL_CACHE_WBACK) | 
 | 	sethi.p		%hi(HSR0_DCE|HSR0_CBM_COPY_BACK),gr4 | 
 | 	setlo		%lo(HSR0_DCE|HSR0_CBM_COPY_BACK),gr4 | 
 | #elif defined(CONFIG_FRV_DEFL_CACHE_WBEHIND) | 
 | 	sethi.p		%hi(HSR0_DCE|HSR0_CBM_COPY_BACK),gr4 | 
 | 	setlo		%lo(HSR0_DCE|HSR0_CBM_COPY_BACK),gr4 | 
 |  | 
 | 	movsg		psr,gr6 | 
 | 	srli		gr6,#24,gr6 | 
 | 	cmpi		gr6,#0x50,icc0		// FR451 | 
 | 	beq		icc0,#0,0f | 
 | 	cmpi		gr6,#0x40,icc0		// FR405 | 
 | 	bne		icc0,#0,1f | 
 | 0: | 
 | 	# turn off write-allocate | 
 | 	sethi.p		%hi(HSR0_NWA),gr6 | 
 | 	setlo		%lo(HSR0_NWA),gr6 | 
 | 	or		gr4,gr6,gr4 | 
 | 1: | 
 |  | 
 | #else | 
 | #error No default cache configuration set | 
 | #endif | 
 |  | 
 | 	or		gr4,gr5,gr5 | 
 | 	movgs		gr5,hsr0 | 
 | 	bar | 
 |  | 
 | 	LEDS		0x0008 | 
 |  | 
 | 	sethi.p		%hi(__head_mmu_enabled),gr19 | 
 | 	setlo		%lo(__head_mmu_enabled),gr19 | 
 | 	jmpl		@(gr19,gr0) | 
 |  | 
 | __head_mmu_enabled: | 
 | 	icei		@(gr0,gr0),#1 | 
 | 	dcei		@(gr0,gr0),#1 | 
 |  | 
 | 	LEDS		0x0009 | 
 |  | 
 | #ifdef CONFIG_MMU | 
 | 	call		__head_fr451_finalise_protection | 
 | #endif | 
 |  | 
 | 	LEDS		0x000a | 
 |  | 
 | ############################################################################### | 
 | # | 
 | # set up the runtime environment | 
 | # | 
 | ############################################################################### | 
 |  | 
 | 	# clear the BSS area | 
 | 	sethi.p		%hi(__bss_start),gr4 | 
 | 	setlo		%lo(__bss_start),gr4 | 
 | 	sethi.p		%hi(_end),gr5 | 
 | 	setlo		%lo(_end),gr5 | 
 | 	or.p		gr0,gr0,gr18 | 
 | 	or		gr0,gr0,gr19 | 
 |  | 
 | 0: | 
 | 	stdi		gr18,@(gr4,#0) | 
 | 	stdi		gr18,@(gr4,#8) | 
 | 	stdi		gr18,@(gr4,#16) | 
 | 	stdi.p		gr18,@(gr4,#24) | 
 | 	addi		gr4,#24,gr4 | 
 | 	subcc		gr5,gr4,gr0,icc0 | 
 | 	bhi		icc0,#2,0b | 
 |  | 
 | 	LEDS		0x000b | 
 |  | 
 | 	# save the SDRAM details | 
 | 	sethi.p		%hi(__sdram_old_base),gr4 | 
 | 	setlo		%lo(__sdram_old_base),gr4 | 
 | 	st		gr24,@(gr4,gr0) | 
 |  | 
 | 	sethi.p		%hi(__sdram_base),gr5 | 
 | 	setlo		%lo(__sdram_base),gr5 | 
 | 	sethi.p		%hi(memory_start),gr4 | 
 | 	setlo		%lo(memory_start),gr4 | 
 | 	st		gr5,@(gr4,gr0) | 
 |  | 
 | 	add		gr25,gr5,gr25 | 
 | 	sethi.p		%hi(memory_end),gr4 | 
 | 	setlo		%lo(memory_end),gr4 | 
 | 	st		gr25,@(gr4,gr0) | 
 |  | 
 | 	# point the TBR at the kernel trap table | 
 | 	sethi.p		%hi(__entry_kerneltrap_table),gr4 | 
 | 	setlo		%lo(__entry_kerneltrap_table),gr4 | 
 | 	movgs		gr4,tbr | 
 |  | 
 | 	# set up the exception frame for init | 
 | 	sethi.p		%hi(__kernel_frame0_ptr),gr28 | 
 | 	setlo		%lo(__kernel_frame0_ptr),gr28 | 
 | 	sethi.p		%hi(_gp),gr16 | 
 | 	setlo		%lo(_gp),gr16 | 
 | 	sethi.p		%hi(__entry_usertrap_table),gr4 | 
 | 	setlo		%lo(__entry_usertrap_table),gr4 | 
 |  | 
 | 	lddi		@(gr28,#0),gr28		; load __frame & current | 
 | 	ldi.p		@(gr29,#4),gr15		; set current_thread | 
 |  | 
 | 	or		gr0,gr0,fp | 
 | 	or		gr28,gr0,sp | 
 |  | 
 | 	sti.p		gr4,@(gr28,REG_TBR) | 
 | 	setlos		#ISR_EDE|ISR_DTT_DIVBYZERO|ISR_EMAM_EXCEPTION,gr5 | 
 | 	movgs		gr5,isr | 
 |  | 
 | 	# turn on and off various CPU services | 
 | 	movsg		psr,gr22 | 
 | 	sethi.p		%hi(#PSR_EM|PSR_EF|PSR_CM|PSR_NEM),gr4 | 
 | 	setlo		%lo(#PSR_EM|PSR_EF|PSR_CM|PSR_NEM),gr4 | 
 | 	or		gr22,gr4,gr22 | 
 | 	movgs		gr22,psr | 
 |  | 
 | 	andi		gr22,#~(PSR_PIL|PSR_PS|PSR_S),gr22 | 
 | 	ori		gr22,#PSR_ET,gr22 | 
 | 	sti		gr22,@(gr28,REG_PSR) | 
 |  | 
 |  | 
 | ############################################################################### | 
 | # | 
 | # set up the registers and jump into the kernel | 
 | # | 
 | ############################################################################### | 
 |  | 
 | 	LEDS		0x000c | 
 |  | 
 | 	# initialise the processor and the peripherals | 
 | 	#call		SYMBOL_NAME(processor_init) | 
 | 	#call		SYMBOL_NAME(unit_init) | 
 | 	#LEDS		0x0aff | 
 |  | 
 | 	sethi.p		#0xe5e5,gr3 | 
 | 	setlo		#0xe5e5,gr3 | 
 | 	or.p		gr3,gr0,gr4 | 
 | 	or		gr3,gr0,gr5 | 
 | 	or.p		gr3,gr0,gr6 | 
 | 	or		gr3,gr0,gr7 | 
 | 	or.p		gr3,gr0,gr8 | 
 | 	or		gr3,gr0,gr9 | 
 | 	or.p		gr3,gr0,gr10 | 
 | 	or		gr3,gr0,gr11 | 
 | 	or.p		gr3,gr0,gr12 | 
 | 	or		gr3,gr0,gr13 | 
 | 	or.p		gr3,gr0,gr14 | 
 | 	or		gr3,gr0,gr17 | 
 | 	or.p		gr3,gr0,gr18 | 
 | 	or		gr3,gr0,gr19 | 
 | 	or.p		gr3,gr0,gr20 | 
 | 	or		gr3,gr0,gr21 | 
 | 	or.p		gr3,gr0,gr23 | 
 | 	or		gr3,gr0,gr24 | 
 | 	or.p		gr3,gr0,gr25 | 
 | 	or		gr3,gr0,gr26 | 
 | 	or.p		gr3,gr0,gr27 | 
 | #	or		gr3,gr0,gr30 | 
 | 	or		gr3,gr0,gr31 | 
 | 	movgs		gr0,lr | 
 | 	movgs		gr0,lcr | 
 | 	movgs		gr0,ccr | 
 | 	movgs		gr0,cccr | 
 |  | 
 | 	# initialise the virtual interrupt handling | 
 | 	subcc		gr0,gr0,gr0,icc2		/* set Z, clear C */ | 
 |  | 
 | #ifdef CONFIG_MMU | 
 | 	movgs		gr3,scr2 | 
 | 	movgs		gr3,scr3 | 
 | #endif | 
 |  | 
 | 	LEDS		0x0fff | 
 |  | 
 | 	# invoke the debugging stub if present | 
 | 	# - arch/frv/kernel/debug-stub.c will shift control directly to init/main.c | 
 | 	#   (it will not return here) | 
 | 	break | 
 | 	.globl		__debug_stub_init_break | 
 | __debug_stub_init_break: | 
 |  | 
 | 	# however, if you need to use an ICE, and don't care about using any userspace | 
 | 	# debugging tools (such as the ptrace syscall), you can just step over the break | 
 | 	# above and get to the kernel this way | 
 | 	# look at arch/frv/kernel/debug-stub.c: debug_stub_init() to see what you've missed | 
 | 	call		start_kernel | 
 |  | 
 | 	.globl		__head_end | 
 | __head_end: | 
 | 	.size		_boot, .-_boot | 
 |  | 
 | 	# provide a point for GDB to place a break | 
 | 	.section	.text.start,"ax" | 
 | 	.globl		_start | 
 | 	.balign		4 | 
 | _start: | 
 | 	call		_boot | 
 |  | 
 | 	.previous | 
 | ############################################################################### | 
 | # | 
 | # split a tile off of the region defined by GR8-GR9 | 
 | # | 
 | #	ENTRY:			EXIT: | 
 | # GR4	-			IAMPR value representing tile | 
 | # GR5	-			DAMPR value representing tile | 
 | # GR6	-			IAMLR value representing tile | 
 | # GR7	-			DAMLR value representing tile | 
 | # GR8	region base pointer	[saved] | 
 | # GR9	region top pointer	updated to exclude new tile | 
 | # GR11	xAMLR mask		[saved] | 
 | # GR25	SDRAM size		[saved] | 
 | # GR30	LED address		[saved] | 
 | # | 
 | # - GR8 and GR9 should be rounded up/down to the nearest megabyte before calling | 
 | # | 
 | ############################################################################### | 
 | 	.globl		__head_split_region | 
 | 	.type		__head_split_region,@function | 
 | __head_split_region: | 
 | 	subcc.p		gr9,gr8,gr4,icc0 | 
 | 	setlos		#31,gr5 | 
 | 	scan.p		gr4,gr0,gr6 | 
 | 	beq		icc0,#0,__head_region_empty | 
 | 	sub.p		gr5,gr6,gr6			; bit number of highest set bit (1MB=>20) | 
 | 	setlos		#1,gr4 | 
 | 	sll.p		gr4,gr6,gr4			; size of region (1 << bitno) | 
 | 	subi		gr6,#17,gr6			; 1MB => 0x03 | 
 | 	slli.p		gr6,#4,gr6			; 1MB => 0x30 | 
 | 	sub		gr9,gr4,gr9			; move uncovered top down | 
 |  | 
 | 	or		gr9,gr6,gr4 | 
 | 	ori		gr4,#xAMPRx_S_USER|xAMPRx_C_CACHED|xAMPRx_V,gr4 | 
 | 	or.p		gr4,gr0,gr5 | 
 |  | 
 | 	and		gr4,gr11,gr6 | 
 | 	and.p		gr5,gr11,gr7 | 
 | 	bralr | 
 |  | 
 | __head_region_empty: | 
 | 	or.p		gr0,gr0,gr4 | 
 | 	or		gr0,gr0,gr5 | 
 | 	or.p		gr0,gr0,gr6 | 
 | 	or		gr0,gr0,gr7 | 
 | 	bralr | 
 | 	.size		__head_split_region, .-__head_split_region | 
 |  | 
 | ############################################################################### | 
 | # | 
 | # write the 32-bit hex number in GR8 to ttyS0 | 
 | # | 
 | ############################################################################### | 
 | #if 0 | 
 | 	.globl		__head_write_to_ttyS0 | 
 | 	.type		__head_write_to_ttyS0,@function | 
 | __head_write_to_ttyS0: | 
 | 	sethi.p		%hi(0xfeff9c00),gr31 | 
 | 	setlo		%lo(0xfeff9c00),gr31 | 
 | 	setlos		#8,gr20 | 
 |  | 
 | 0:	ldubi		@(gr31,#5*8),gr21 | 
 | 	andi		gr21,#0x60,gr21 | 
 | 	subicc		gr21,#0x60,gr21,icc0 | 
 | 	bne		icc0,#0,0b | 
 |  | 
 | 1:	srli		gr8,#28,gr21 | 
 | 	slli		gr8,#4,gr8 | 
 |  | 
 | 	addi		gr21,#'0',gr21 | 
 | 	subicc		gr21,#'9',gr0,icc0 | 
 | 	bls		icc0,#2,2f | 
 | 	addi		gr21,#'A'-'0'-10,gr21 | 
 | 2: | 
 | 	stbi		gr21,@(gr31,#0*8) | 
 | 	subicc		gr20,#1,gr20,icc0 | 
 | 	bhi		icc0,#2,1b | 
 |  | 
 | 	setlos		#'\r',gr21 | 
 | 	stbi		gr21,@(gr31,#0*8) | 
 |  | 
 | 	setlos		#'\n',gr21 | 
 | 	stbi		gr21,@(gr31,#0*8) | 
 |  | 
 | 3:	ldubi		@(gr31,#5*8),gr21 | 
 | 	andi		gr21,#0x60,gr21 | 
 | 	subicc		gr21,#0x60,gr21,icc0 | 
 | 	bne		icc0,#0,3b | 
 | 	bralr | 
 |  | 
 | 	.size		__head_write_to_ttyS0, .-__head_write_to_ttyS0 | 
 | #endif |