# Copyright (c) 2003 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, modify, # copy, or redistribute it subject to the terms and conditions of the BSD # License. This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY expressed or implied, including the implied # warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. A copy of # this license is available at http://www.opensource.org/licenses. Any Red Hat # trademarks that are incorporated in the source code or documentation are not # subject to the BSD License and may only be used or replicated with the express # permission of Red Hat, Inc. # # Toshiba Media Processor startup file (crt0.S) # # Designed for user programs running in the 0-2Mb startup section. # Designed for the simulator by default. # # Exception/Interrupt Handler Locations # CFG.EVM CFG.EVA CFG.IVA Exception INTn ## 0 - - 0x0000_0000 0x0000_0030 rom ## 1 0 0 0x0020_0000 0x0020_0030 local RAM / local RAM ## 1 1 0 0x0080_0000 0x0020_0000 ext RAM / local RAM ## 1 0 1 0x0020_0000 0x0080_0000 local RAM / ext RAM ## 1 1 1 0x0080_0000 0x0080_0030 ext RAM / ext RAM # # Exceptions # Reset 0x0000_0000 # NMI 0x0000_0000+4 # RI (Base Address) +0x08 # ZDIV (Base Address) +0x0C # BRK (Base Address) +0x10 # SWI (Base Address) +0x14 # DSP (Base Address) +0x1C # COP (Base Address) +0x20 .set _local_ram_base, 0x00200000 .set _ext_ram_base, 0x00800000 .set _int_base_offset, 0x30 #include "syscall.h" .macro if_bitfield_zero reg, start, length, label ldc $0, \reg srl $0, \start and3 $0, $0, (1 << \length) - 1 beqz $0,\label .endm .macro if_bitfield_notN reg, start, length, N, label ldc $0, \reg srl $0, \start and3 $0, $0, (1 << \length) - 1 bnei $0,\N, \label .endm .macro if_bitfield_eqN reg, start, length, N, label ldc $0, \reg srl $0, \start and3 $0, $0, (1 << \length) - 1 beqi $0,\N, \label .endm .macro if_bitfield_ltN reg, start, length, N, label ldc $0, \reg srl $0, \start and3 $0, $0, (1 << \length) - 1 blti $0,\N, \label .endm .section .hwinit, "ax" # CCFG.ICSZ if_bitfield_zero reg=$ccfg, start=16, length=7, label=.Lend_enable_icache __enable_icache: # set ICE(cfg[1]) ldc $1,$cfg or3 $1,$1,2 stc $1,$cfg nop nop nop nop nop .Lend_enable_icache: ret __enable_dcache: # CCFG.DCSZ if_bitfield_zero reg=$ccfg, start=0, length=7, label=.Lend_enable_dcache # set DCE(cfg[0]) ldc $1,$cfg or3 $1,$1,1 stc $1,$cfg nop nop nop nop nop ret .Lend_enable_dcache: .text #ifdef NOVEC .global _reset _reset: #endif .global _start _start: mov $fp, 0 # for unwinding # $sp set movh $sp, %uhi(__stack_table) or3 $sp, $sp, %lo(__stack_table) # initialize sp, gp, tp # get CPU ID ldc $0, $id srl $0, 16 # load ID-specific stack pointer sl2ad3 $0, $0, $sp # $0 = ($0 << 2) + $sp lw $sp,($0) # $sp = *($0) mov $0,0xfffffff8 and $sp, $0 #ifndef NOVEC # copy exception vector table # RCFG.IRSZ if_bitfield_zero reg=$rcfg, start=16, length=7, label=.Lend_ev_imem # handle imem movh $11,%uhi(_local_ram_base) or3 $11,$11,%lo(_local_ram_base) # clear CFG.EVA ([23]) ldc $0,$cfg movh $1, %uhi(0xff7fffff) or3 $1, $1, %lo(0xff7fffff) and $0,$1 stc $0,$cfg bra .Ldo_repeat_ev .Lend_ev_imem: #ifdef UseSDRAM movh $11,%uhi(_ext_ram_base) or3 $11,$11,%lo(_ext_ram_base) # set CFG.EVA ([23]) ldc $0,$cfg movh $1,%uhi(1<<23) or3 $1,$1,%lo(1<<23) or $0,$1 stc $0,$cfg #else # handle ROM bra .Lend_ev #endif .Ldo_repeat_ev: # set CFG.EVM ([4]) ldc $0,$cfg or3 $0,$0,(1<<4) stc $0,$cfg # copy _exception_table to $11 movh $12,%uhi(_exception_table) or3 $12,$12,%lo(_exception_table) mov $13,8 repeat $13,.Lrepeat_ev lw $1,0($12) add $12,4 .Lrepeat_ev: sw $1,0($11) add $11,4 .Lend_ev: # copy interrupt vector table # RCFG.IRSZ if_bitfield_zero reg=$rcfg, start=16, length=7, label=.Lend_iv_imem # handle imem movh $11,%uhi(_local_ram_base) or3 $11,$11,%lo(_int_base_offset) # clear CFG.IVA ([22]) ldc $0,$cfg movh $1,%uhi(0xffbfffff) # ~(1<<22) or3 $1,$1,%lo(0xffbfffff) and $0,$1 stc $0,$cfg bra .Ldo_repeat_iv .Lend_iv_imem: #ifdef UseSDRAM movh $11,%uhi(_ext_ram_base) or3 $11,$11,%lo(_int_base_offset) # set CFG. IVA ([22]) ldc $0,$cfg movh $1,%uhi(1<<22) or3 $1,$1,%lo(1<<22) or $0,$1 stc $0,$cfg #else # handle ROM bra .Lend_iv #endif .Ldo_repeat_iv: # set CFG.IVM ([3]) ldc $0,$cfg or3 $0,$0,(1<<3) stc $0,$cfg # copy _interrupt_table to $11 movh $12,%uhi(_interrupt_table) or3 $12,$12,%lo(_interrupt_table) mov $13,32 add $13,-1 and3 $13,$13,127 repeat $13,.Lrepeat_iv lw $1,0($12) add $12,4 .Lrepeat_iv: sw $1,0($11) add $11,4 .Lend_iv: # initialize instruction cache # Icache Size CCFG.ICSZ ([22..16]) KByte if_bitfield_zero reg=$ccfg, start=16, length=7, label=.Lend_ic mov $3,$0 # cache size in KB # ID.ID if_bitfield_ltN reg=$ID, start=8, length=8, N=3, label=.Lend_mepc3_ic # Line Size CCFG.ICSZ ([26..24]) Byte if_bitfield_ltN reg=$ccfg, start=24, length=3, N=2, label=.Lend_ic bgei $0,5,.Lend_ic add3 $1,$0,3 # bit width of line size mov $0,$3 # clear tag mov $2,10 sub $2,$1 sll $0,$2 # *KByte/(line size) add $0,-1 mov $2,1 sll $2,$1 # line size bra .Ldo_repeat_icache .Lend_mepc3_ic: # ICache: $0 KByte mov $0,$3 # clear tag sll $0,(10-5) # *KByte/(32byte=linesize) add $0,-1 mov $2,32 .Ldo_repeat_icache: mov $1,0 bra 0f # Align this code on an 8 byte boundary in order to keep the repeat # loop entirely within the instruction fetch buffer. .p2align 3 0: movh $3,%hi(0x00310000) # for tag repeat $0,.Lrepeat_icache add $0,-1 .Lrepeat_icache: sw $1,0($3) add3 $3,$3,$2 .Lenable_icache: movh $1,%hi(__enable_icache) add3 $1,$1,%lo(__enable_icache) jsr $1 .Lend_ic: # initialize data cache # Dcache Size CCFG.DCSZ ([6..0]) KByte if_bitfield_zero reg=$ccfg, start=0, length=7, label=.Lend_dc mov $3,$0 # cache size in KB # ID.ID if_bitfield_ltN reg=$ID, start=8, length=8, N=3, label=.Lend_mepc3_dc # Line Size CCFG.DCSZ ([10..8]) Byte if_bitfield_ltN reg=$ccfg, start=8, length=3, N=2, label=.Lend_dc bgei $0,5,.Lend_dc add3 $1,$0,3 # bit width of line size mov $0,$3 # clear tag mov $2,10 sub $2,$1 sll $0,$2 # *KByte/(line size) add $0,-1 mov $2,1 sll $2,$1 # line size bra .Ldo_repeat_dcache .Lend_mepc3_dc: # DCache: $0 KByte mov $0,$3 # clear tag sll $0,(10-5) # *KByte/(32byte=linesize) add $0,-1 mov $2,32 .Ldo_repeat_dcache: mov $1,0 movh $3,%hi(0x00330000) # for tag repeat $0,.Lrepeat_dcache add $0,-1 .Lrepeat_dcache: sw $1,0($3) add3 $3,$3,$2 .Lenable_dcache: movh $1,%hi(__enable_dcache) add3 $1,$1,%lo(__enable_dcache) jsr $1 .Lend_dc: # NOVEC #endif mov $0, 0 movh $gp, %uhi(__sdabase) or3 $gp, $gp, %lo(__sdabase) movh $tp, %uhi(__tpbase) or3 $tp, $tp, %lo(__tpbase) # zero out BSS movh $1, %uhi(__bss_start) or3 $1, $1, %lo(__bss_start) mov $2, 0 movh $3, %uhi(_end) or3 $3, $3, %lo(_end) sub $3, $1 bsr memset movh $1, %uhi(__sbss_start) or3 $1, $1, %lo(__sbss_start) mov $2, 0 movh $3, %uhi(__sbss_end) or3 $3, $3, %lo(__sbss_end) sub $3, $1 bsr memset movh $1, %uhi(__farbss_start) or3 $1, $1, %lo(__farbss_start) mov $2, 0 movh $3, %uhi(__farbss_end) or3 $3, $3, %lo(__farbss_end) sub $3, $1 bsr memset # enable interrupts ei # construct global class variables bsr __invoke_init_section # invoke main mov $1, 0 # argc, argv, envp mov $2, 0 mov $3, 0 bsr main mov $1, $0 bsr exit .global _exit _exit: # Prevent _exit recursion movh $3, %uhi(_exit_in_progress) or3 $3, $3, %lo(_exit_in_progress) lw $5, ($3) bnez $5, _skip_fini mov $5, 1 sw $5, ($3) # We don't need to preserve $5 because we're going to exit anyway. mov $5,$1 # destruct global class variables bsr __invoke_fini_section mov $1,$5 _skip_fini: #ifdef NOSIM _exit_loop: bra _exit_loop #else .2byte 0x7800 | ((SYS_exit & 0xe) << 7) | ((SYS_exit & 1) << 4) ret #endif .data _exit_in_progress: .word 0 # For these two, the epilogue is in crtn.S .section .init __invoke_init_section: add $sp, -8 ldc $0, $lp sw $0, ($sp) .section .fini __invoke_fini_section: add $sp, -8 ldc $0, $lp sw $0, ($sp) #ifndef NOVEC .section .vec, "ax" .core .org 0x0, 0 .global _exception_table .type _exception_table,@function _exception_table: .p2align 2 .org 0x0000, 0 .global _reset _reset: jmp _handler_RESET .org 0x0004, 0 jmp _handler_NMI .org 0x0008, 0 jmp _handler_RI .org 0x000c, 0 jmp _handler_ZDIV .org 0x0010, 0 jmp _handler_BRK .org 0x0014, 0 jmp _handler_SWI .org 0x0018, 0 jmp _handler_DEBUG .org 0x001c, 0 jmp _handler_DSP .org 0x0020, 0 jmp _handler_COP .org 0x30, 0 .global _interrupt_table .type _interrupt_table,@function _interrupt_table: .org 0x0030 jmp _handler_INT0 .org 0x0034 jmp _handler_INT1 .org 0x0038 jmp _handler_INT2 .org 0x003c jmp _handler_INT3 .org 0x0040 jmp _handler_INT4 .org 0x0044 jmp _handler_INT5 .org 0x0048 jmp _handler_INT6 .org 0x004c jmp _handler_INT7 .org 0x0050 jmp _handler_INT8 .org 0x0054 jmp _handler_INT9 .org 0x0058 jmp _handler_INT10 .org 0x005c jmp _handler_INT11 .org 0x0060 jmp _handler_INT12 .org 0x0064 jmp _handler_INT13 .org 0x0068 jmp _handler_INT14 .org 0x006c jmp _handler_INT15 .org 0x0070 jmp _handler_INT16 .org 0x0074 jmp _handler_INT17 .org 0x0078 jmp _handler_INT18 .org 0x007c jmp _handler_INT19 .org 0x0080 jmp _handler_INT20 .org 0x0084 jmp _handler_INT21 .org 0x0088 jmp _handler_INT22 .org 0x008c jmp _handler_INT23 .org 0x0090 jmp _handler_INT24 .org 0x0094 jmp _handler_INT25 .org 0x0098 jmp _handler_INT26 .org 0x009c jmp _handler_INT27 .org 0x00a0 jmp _handler_INT28 .org 0x00a4 jmp _handler_INT29 .org 0x00a8 jmp _handler_INT30 .org 0x00ac jmp _handler_INT31 # NOVEC #endif