| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | /* 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. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-25 22:10:59 -04:00
										 |  |  | #include <linux/init.h> | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #include <linux/threads.h> | 
					
						
							|  |  |  | #include <linux/linkage.h> | 
					
						
							| 
									
										
										
										
											2006-07-10 04:44:55 -07:00
										 |  |  | #include <asm/thread_info.h> | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #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 | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | ############################################################################### | 
					
						
							| 
									
										
										
										
											2009-04-25 22:10:59 -04:00
										 |  |  | 	__HEAD | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	.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 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	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 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
											  
											
												[PATCH] FRV: Use virtual interrupt disablement
Make the FRV arch use virtual interrupt disablement because accesses to the
processor status register (PSR) are relatively slow and because we will
soon have the need to deal with multiple interrupt controls at the same
time (separate h/w and inter-core interrupts).
The way this is done is to dedicate one of the four integer condition code
registers (ICC2) to maintaining a virtual interrupt disablement state
whilst inside the kernel.  This uses the ICC2.Z flag (Zero) to indicate
whether the interrupts are virtually disabled and the ICC2.C flag (Carry)
to indicate whether the interrupts are physically disabled.
ICC2.Z is set to indicate interrupts are virtually disabled.  ICC2.C is set
to indicate interrupts are physically enabled.  Under normal running
conditions Z==0 and C==1.
Disabling interrupts with local_irq_disable() doesn't then actually
physically disable interrupts - it merely sets ICC2.Z to 1.  Should an
interrupt then happen, the exception prologue will note ICC2.Z is set and
branch out of line using one instruction (an unlikely BEQ).  Here it will
physically disable interrupts and clear ICC2.C.
When it comes time to enable interrupts (local_irq_enable()), this simply
clears the ICC2.Z flag and invokes a trap #2 if both Z and C flags are
clear (the HI integer condition).  This can be done with the TIHI
conditional trap instruction.
The trap then physically reenables interrupts and sets ICC2.C again.  Upon
returning the interrupt will be taken as interrupts will then be enabled.
Note that whilst processing the trap, the whole exceptions system is
disabled, and so an interrupt can't happen till it returns.
If no pending interrupt had happened, ICC2.C would still be set, the HI
condition would not be fulfilled, and no trap will happen.
Saving interrupts (local_irq_save) is simply a matter of pulling the ICC2.Z
flag out of the CCR register, shifting it down and masking it off.  This
gives a result of 0 if interrupts were enabled and 1 if they weren't.
Restoring interrupts (local_irq_restore) is then a matter of taking the
saved value mentioned previously and XOR'ing it against 1.  If it was one,
the result will be zero, and if it was zero the result will be non-zero.
This result is then used to affect the ICC2.Z flag directly (it is a
condition code flag after all).  An XOR instruction does not affect the
Carry flag, and so that bit of state is unchanged.  The two flags can then
be sampled to see if they're both zero using the trap (TIHI) as for the
unconditional reenablement (local_irq_enable).
This patch also:
 (1) Modifies the debugging stub (break.S) to handle single-stepping crossing
     into the trap #2 handler and into virtually disabled interrupts.
 (2) Removes superseded fixup pointers from the second instructions in the trap
     tables (there's no a separate fixup table for this).
 (3) Declares the trap #3 vector for use in .org directives in the trap table.
 (4) Moves irq_enter() and irq_exit() in do_IRQ() to avoid problems with
     virtual interrupt handling, and removes the duplicate code that has now
     been folded into irq_exit() (softirq and preemption handling).
 (5) Tells the compiler in the arch Makefile that ICC2 is now reserved.
 (6) Documents the in-kernel ABI, including the virtual interrupts.
 (7) Renames the old irq management functions to different names.
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
											
										 
											2006-02-14 13:53:20 -08:00
										 |  |  | 	# initialise the virtual interrupt handling | 
					
						
							|  |  |  | 	subcc		gr0,gr0,gr0,icc2		/* set Z, clear C */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #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 | 
					
						
							| 
									
										
										
										
											2010-02-20 01:03:56 +01:00
										 |  |  | 	.section	.text..start,"ax" | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	.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 |