1251881Speter/* SPDX-License-Identifier: GPL-2.0-or-later */
2251881Speter/*
3251881Speter * crt0_r.S: Entry function for SPU-side context restore.
4251881Speter *
5251881Speter * Copyright (C) 2005 IBM
6251881Speter *
7251881Speter * Entry and exit function for SPU-side of the context restore
8251881Speter * sequence.  Sets up an initial stack frame, then branches to
9251881Speter * 'main'.  On return, restores all 128 registers from the LSCSA
10251881Speter * and exits.
11251881Speter */
12251881Speter
13251881Speter#include <asm/spu_csa.h>
14251881Speter
15251881Speter.data
16251881Speter.align 7
17251881Speter.globl regs_spill
18251881Speterregs_spill:
19251881Speter.space SIZEOF_SPU_SPILL_REGS, 0x0
20251881Speter
21251881Speter.text
22251881Speter.global _start
23251881Speter_start:
24251881Speter	/* Initialize the stack pointer to point to 16368
25251881Speter	 * (16kb-16). The back chain pointer is initialized
26251881Speter	 * to NULL.
27251881Speter	 */
28251881Speter	il      $0, 0
29251881Speter	il      $SP, 16368
30251881Speter	stqd    $0, 0($SP)
31251881Speter
32251881Speter	/* Allocate a minimum stack frame for the called main.
33251881Speter	 * This is needed so that main has a place to save the
34251881Speter	 * link register when it calls another function.
35251881Speter	 */
36251881Speter	stqd    $SP, -160($SP)
37251881Speter	ai      $SP, $SP, -160
38251881Speter
39251881Speter	/* Call the program's main function. */
40251881Speter	brsl    $0, main
41251881Speter
42251881Speter.global exit
43251881Speter.global	_exit
44251881Speterexit:
45251881Speter_exit:
46251881Speter	/* SPU Context Restore, Step 5: Restore the remaining 112 GPRs. */
47251881Speter	ila     $3, regs_spill + 256
48251881Speterrestore_regs:
49251881Speter	lqr     $4, restore_reg_insts
50251881Speterrestore_reg_loop:
51251881Speter	ai      $4, $4, 4
52251881Speter	.balignl 16, 0x40200000
53251881Speterrestore_reg_insts:       /* must be quad-word aligned. */
54251881Speter	lqd     $16, 0($3)
55251881Speter	lqd     $17, 16($3)
56251881Speter	lqd     $18, 32($3)
57251881Speter	lqd     $19, 48($3)
58251881Speter	andi    $5, $4, 0x7F
59251881Speter	stqr    $4, restore_reg_insts
60251881Speter	ai      $3, $3, 64
61251881Speter	brnz    $5, restore_reg_loop
62251881Speter
63251881Speter	/* SPU Context Restore Step 17: Restore the first 16 GPRs. */
64251881Speter	lqa $0, regs_spill + 0
65251881Speter	lqa $1, regs_spill + 16
66251881Speter	lqa $2, regs_spill + 32
67251881Speter	lqa $3, regs_spill + 48
68251881Speter	lqa $4, regs_spill + 64
69251881Speter	lqa $5, regs_spill + 80
70251881Speter	lqa $6, regs_spill + 96
71251881Speter	lqa $7, regs_spill + 112
72251881Speter	lqa $8, regs_spill + 128
73251881Speter	lqa $9, regs_spill + 144
74251881Speter	lqa $10, regs_spill + 160
75251881Speter	lqa $11, regs_spill + 176
76251881Speter	lqa $12, regs_spill + 192
77251881Speter	lqa $13, regs_spill + 208
78251881Speter	lqa $14, regs_spill + 224
79251881Speter	lqa $15, regs_spill + 240
80251881Speter
81251881Speter	/* Under normal circumstances, the 'exit' function
82251881Speter	 * terminates with 'stop SPU_RESTORE_COMPLETE',
83251881Speter	 * indicating that the SPU-side restore code has
84251881Speter	 * completed.
85251881Speter	 *
86251881Speter	 * However it is possible that instructions immediately
87251881Speter	 * following the 'stop 0x3ffc' have been modified at run
88251881Speter	 * time so as to recreate the exact SPU_Status settings
89251881Speter	 * from the application, e.g. illegal instruciton, halt,
90251881Speter	 * etc.
91251881Speter	 */
92251881Speter.global exit_fini
93251881Speter.global	_exit_fini
94251881Speterexit_fini:
95251881Speter_exit_fini:
96251881Speter	stop	SPU_RESTORE_COMPLETE
97251881Speter	stop	0
98251881Speter	stop	0
99	stop	0
100
101	/* Pad the size of this crt0.o to be multiple of 16 bytes. */
102.balignl 16, 0x0
103