105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter/*
205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * crt0_r.S: Entry function for SPU-side context restore.
305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter *
405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * Copyright (C) 2005 IBM
505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter *
605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * Entry and exit function for SPU-side of the context restore
705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * sequence.  Sets up an initial stack frame, then branches to
805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * 'main'.  On return, restores all 128 registers from the LSCSA
905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * and exits.
1005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter *
1105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter *
1205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * This program is free software; you can redistribute it and/or modify
1305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * it under the terms of the GNU General Public License as published by
1405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * the Free Software Foundation; either version 2, or (at your option)
1505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * any later version.
1605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter *
1705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * This program is distributed in the hope that it will be useful,
1805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * but WITHOUT ANY WARRANTY; without even the implied warranty of
1905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * GNU General Public License for more details.
2105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter *
2205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * You should have received a copy of the GNU General Public License
2305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * along with this program; if not, write to the Free Software
2405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
2505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter */
2605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter
2705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter#include <asm/spu_csa.h>
2805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter
2905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter.data
3005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter.align 7
3105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter.globl regs_spill
3205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutterregs_spill:
3305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter.space SIZEOF_SPU_SPILL_REGS, 0x0
3405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter
3505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter.text
3605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter.global _start
3705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter_start:
3805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	/* Initialize the stack pointer to point to 16368
3905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	 * (16kb-16). The back chain pointer is initialized
4005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	 * to NULL.
4105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	 */
4205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	il      $0, 0
4305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	il      $SP, 16368
4405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	stqd    $0, 0($SP)
4505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter
4605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	/* Allocate a minimum stack frame for the called main.
4705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	 * This is needed so that main has a place to save the
4805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	 * link register when it calls another function.
4905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	 */
5005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	stqd    $SP, -160($SP)
5105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	ai      $SP, $SP, -160
5205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter
5305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	/* Call the program's main function. */
5405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	brsl    $0, main
5505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter
5605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter.global exit
5705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter.global	_exit
5805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutterexit:
5905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter_exit:
6005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	/* SPU Context Restore, Step 5: Restore the remaining 112 GPRs. */
6105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	ila     $3, regs_spill + 256
6205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutterrestore_regs:
6305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	lqr     $4, restore_reg_insts
6405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutterrestore_reg_loop:
6505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	ai      $4, $4, 4
6605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	.balignl 16, 0x40200000
6705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutterrestore_reg_insts:       /* must be quad-word aligned. */
6805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	lqd     $16, 0($3)
6905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	lqd     $17, 16($3)
7005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	lqd     $18, 32($3)
7105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	lqd     $19, 48($3)
7205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	andi    $5, $4, 0x7F
7305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	stqr    $4, restore_reg_insts
7405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	ai      $3, $3, 64
7505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	brnz    $5, restore_reg_loop
7605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter
7705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	/* SPU Context Restore Step 17: Restore the first 16 GPRs. */
7805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	lqa $0, regs_spill + 0
7905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	lqa $1, regs_spill + 16
8005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	lqa $2, regs_spill + 32
8105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	lqa $3, regs_spill + 48
8205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	lqa $4, regs_spill + 64
8305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	lqa $5, regs_spill + 80
8405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	lqa $6, regs_spill + 96
8505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	lqa $7, regs_spill + 112
8605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	lqa $8, regs_spill + 128
8705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	lqa $9, regs_spill + 144
8805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	lqa $10, regs_spill + 160
8905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	lqa $11, regs_spill + 176
9005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	lqa $12, regs_spill + 192
9105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	lqa $13, regs_spill + 208
9205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	lqa $14, regs_spill + 224
9305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	lqa $15, regs_spill + 240
9405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter
9505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	/* Under normal circumstances, the 'exit' function
9605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	 * terminates with 'stop SPU_RESTORE_COMPLETE',
9705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	 * indicating that the SPU-side restore code has
9805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	 * completed.
9905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	 *
10005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	 * However it is possible that instructions immediately
10105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	 * following the 'stop 0x3ffc' have been modified at run
10205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	 * time so as to recreate the exact SPU_Status settings
10305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	 * from the application, e.g. illegal instruciton, halt,
10405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	 * etc.
10505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	 */
10605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter.global exit_fini
10705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter.global	_exit_fini
10805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutterexit_fini:
10905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter_exit_fini:
11005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	stop	SPU_RESTORE_COMPLETE
11105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	stop	0
11205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	stop	0
11305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	stop	0
11405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter
11505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter	/* Pad the size of this crt0.o to be multiple of 16 bytes. */
11605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter.balignl 16, 0x0
117