root/arch/powerpc/platforms/cell/spufs/spu_restore_crt0.S
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * crt0_r.S: Entry function for SPU-side context restore.
 *
 * Copyright (C) 2005 IBM
 *
 * Entry and exit function for SPU-side of the context restore
 * sequence.  Sets up an initial stack frame, then branches to
 * 'main'.  On return, restores all 128 registers from the LSCSA
 * and exits.
 */

#include <asm/spu_csa.h>

.data
.align 7
.globl regs_spill
regs_spill:
.space SIZEOF_SPU_SPILL_REGS, 0x0

.text
.global _start
_start:
        /* Initialize the stack pointer to point to 16368
         * (16kb-16). The back chain pointer is initialized
         * to NULL.
         */
        il      $0, 0
        il      $SP, 16368
        stqd    $0, 0($SP)

        /* Allocate a minimum stack frame for the called main.
         * This is needed so that main has a place to save the
         * link register when it calls another function.
         */
        stqd    $SP, -160($SP)
        ai      $SP, $SP, -160

        /* Call the program's main function. */
        brsl    $0, main

.global exit
.global _exit
exit:
_exit:
        /* SPU Context Restore, Step 5: Restore the remaining 112 GPRs. */
        ila     $3, regs_spill + 256
restore_regs:
        lqr     $4, restore_reg_insts
restore_reg_loop:
        ai      $4, $4, 4
        .balignl 16, 0x40200000
restore_reg_insts:       /* must be quad-word aligned. */
        lqd     $16, 0($3)
        lqd     $17, 16($3)
        lqd     $18, 32($3)
        lqd     $19, 48($3)
        andi    $5, $4, 0x7F
        stqr    $4, restore_reg_insts
        ai      $3, $3, 64
        brnz    $5, restore_reg_loop

        /* SPU Context Restore Step 17: Restore the first 16 GPRs. */
        lqa $0, regs_spill + 0
        lqa $1, regs_spill + 16
        lqa $2, regs_spill + 32
        lqa $3, regs_spill + 48
        lqa $4, regs_spill + 64
        lqa $5, regs_spill + 80
        lqa $6, regs_spill + 96
        lqa $7, regs_spill + 112
        lqa $8, regs_spill + 128
        lqa $9, regs_spill + 144
        lqa $10, regs_spill + 160
        lqa $11, regs_spill + 176
        lqa $12, regs_spill + 192
        lqa $13, regs_spill + 208
        lqa $14, regs_spill + 224
        lqa $15, regs_spill + 240

        /* Under normal circumstances, the 'exit' function
         * terminates with 'stop SPU_RESTORE_COMPLETE',
         * indicating that the SPU-side restore code has
         * completed.
         *
         * However it is possible that instructions immediately
         * following the 'stop 0x3ffc' have been modified at run
         * time so as to recreate the exact SPU_Status settings
         * from the application, e.g. illegal instruciton, halt,
         * etc.
         */
.global exit_fini
.global _exit_fini
exit_fini:
_exit_fini:
        stop    SPU_RESTORE_COMPLETE
        stop    0
        stop    0
        stop    0

        /* Pad the size of this crt0.o to be multiple of 16 bytes. */
.balignl 16, 0x0