638 lines
16 KiB
ArmAsm
638 lines
16 KiB
ArmAsm
/* 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
|
|
|
|
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
|