| /* (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 |
| |