| # 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 |