/* (C) Copyright IBM Corp. 2005, 2006 All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of IBM nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* crt0.S - entry function for C Runtime. * * With _STD_MAIN switch, the crt0.S will be compiled to crt2.o. * The crt2.o sets up a C99-style interface for the SPU application's * main() function, including a local copy of argv strings. * * The number of argument strings is passed in R3. The size and EA * location of the argument vector region is passed in R4. Once the * argv region is copied to the highest range of LS, and $SP is set * just below it. * * Without _STD_MAIN, the crt0.S is compiled to crt1.o. * The crt1.o prepares the entry for an SPU module. The main() function * is called with different parameter list: spu_id, param and env * are passed by R3, R4 and R5 respectively. */ #ifdef _STD_MAIN #define MFC_TAG_UPDATE_ALL 2 #define MFC_GET_CMD 0x40 #define TAGID 0 #define TAGMASK 1 #endif .comm __ea_local_store,16,16 .text .global _start .type _start, @function _start: /* Save the local store base from $6. */ stqr $6, __ea_local_store #ifdef _STD_MAIN /* * Copy the argument vector region from EA to LS. The DMA * parameters are passed in R4: * * +-------+-------+-------+-------+ * R4 | LS | EA-HI | EA-LO | SIZE | * +-------+-------+-------+-------+ * word 0 1 2 3 * * By the end of this sequence, the prefered slot (word 0) of * R4 will contain the LS offset of argv region, which also * serves as the base offset for $SP. */ wrch $MFC_LSA, $4 rotqbyi $4, $4, 4 wrch $MFC_EAH, $4 rotqbyi $4, $4, 4 wrch $MFC_EAL, $4 rotqbyi $4, $4, 4 wrch $MFC_Size, $4 rotqbyi $4, $4, 4 il $LR, TAGID wrch $MFC_TagID, $LR /* Issue MFC_GET_CMD, then wait for transfer of argument * vector region to complete. */ il $LR, MFC_GET_CMD wrch $MFC_Cmd, $LR il $LR, TAGMASK wrch $MFC_WrTagMask, $LR il $LR, MFC_TAG_UPDATE_ALL wrch $MFC_WrTagUpdate, $LR rdch $LR, $MFC_RdTagStat #endif /* Save parameter list of main function to the non-volatile * registers. spu_thread module has three parameters, while * spulet only has two. */ ori $80, $3, 0 ori $81, $4, 0 #ifndef _STD_MAIN ori $82, $5, 0 #endif /* The Link Register is initialized to NULL. */ il $LR, 0 #ifdef _STD_MAIN /* For spulet, initialize stack pointer just below the argv region. */ ai $SP,$4,-16 #else /* For spe_thread module, the stack pointer is initialized * below the area where __stack points to. */ ila $SP,__stack #endif /* Initialize back chain to NULL. */ stqd $LR,0($SP) /* Allocate 2 slots for stack frame. */ stqd $SP,-32($SP) ai $SP,$SP,-32 /* Save the Link Register in Link Register Save Area. */ stqd $LR,16($SP) /* Calculate stack size. */ ila $3,_end sf $3,$3,$SP rotqbyi $3,$3,12 /* The BE Linux ABI passes the stack size in $2, or use * the default if $2 == 0. */ rotqbyi $4,$2,12 ceqi $5,$4,0 selb $3,$4,$3,$5 fsmbi $4,3840 selb $SP,$SP,$3,$4 /* Call the _init function. */ brsl $LR, _init /* Call the _fini function at exit time. */ ila $3, _fini brsl $LR, atexit #ifdef _PROFILE /* Call monstartup if profiling is enabled */ #ifdef _STD_MAIN ila $3,0 #else ori $3,$80,0 #endif brsl $LR, __monstartup #endif ori $3,$80,0 ori $4,$81,0 #ifndef _STD_MAIN ori $5,$82,0 #endif /* Call the programs main. */ brsl $LR, main /* Call exit. */ brsl $LR, exit