1/******************************************************************************
2 * Copyright (c) 2004, 2008 IBM Corporation
3 * All rights reserved.
4 * This program and the accompanying materials
5 * are made available under the terms of the BSD License
6 * which accompanies this distribution, and is available at
7 * http://www.opensource.org/licenses/bsd-license.php
8 *
9 * Contributors:
10 *     IBM Corporation - initial implementation
11 *****************************************************************************/
12
13#include <macros.h>
14
15#define STACKSIZE 0x2000
16
17	#
18	# The generic exception code.
19	#
20	# Enter with GPR0 = vector, SPRG0 = saved GPR0
21	#
22
23	.section ".entry_text"
24
25the_handler:
26	.quad	handler
27
28eregs:
29	/* the_exception_frame is a C variable which is usually
30	 * defined in $(TARG).c
31	 * the_exception_frame can be accessed from paflof through
32	 * the word eregs
33	 * in the case an excpetion is handled paflof will read
34	 * from eregs the values of all registers and print them
35	 * out in the exception handler */
36	.quad	the_exception_frame
37
38handler:
39	mtsprg 1,1	# SPRG1 = saved GPR1
40	bcl 20,31,$+4
41	mflr 1
42	ld 1,eregs-$+4(1)	# GPR1 = address of register save area
43
44	.irp i, 2,3,4,5,6,7,8,9,10,11,12,13,14,15, \
45		16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
46	std \i,\i*8(1)
47	.endr		# save GPR2..GPR31
48
49	li r3, 3        // GPR3 = mode (param_1, param_2)
50	mr 4,0		// GPR4 = vector
51
52	mfsprg 0,0
53	std 0,0(1)	# save GPR0
54	mfsprg 0,1
55	std 0,8(1)	# save GPR1
56
57	cmpwi	r4, 0x900	# Decrementer interrupt
58	bne	0f
59	mfdec	r5		# Save old value of decrementer as reason
60	lis	r0,0x7fff	# Set decrementer to highest value
61	mtdec	r0
620:
63	mfcr 0
64	std 0,0x100(1)
65	mfxer 0
66	std 0,0x108(1)
67	mfsprg 0,3	# save lr
68	std 0,0x110(1)
69	mfsprg 0,2	# save ctr
70	std 0,0x118(1)
71	mfsrr0 0
72	std 0,0x120(1)
73	mfsrr1 0
74	std 0,0x128(1)
75	mfdar 0
76	std 0,0x130(1)
77	mfdsisr 0
78	std 0,0x138(1)	# save special regs
79
80	bcl	20, 31, over
81base:
82	.align	3
83.the_system_stack:
84	.quad   the_system_stack+STACKSIZE-base
85over:
86	mflr	r2				/* gpr 2 is the base */
87	ld	r1, .the_system_stack-base(r2)	/* load stack pointer */
88	add	r1, r1, r2			/* add base */
89	li	r0, 0
90	stdu	r0, -0x10(r1)
91	stdu	r1, -0x100(r1)
92
93	lis 2,engine@ha
94	ld 0,engine@l(2) # set up entry
95	mtsrr0	0
96
97	ld 2,8+engine@l(2) # set up TOC pointer
98
99	rfid
100#	b .engine	# ...and run!
101
102
103
104	#
105	# Swap non-volatile client interface regs, plus GPR3..GPR7.
106	#
107
108swap_ci_regs:
109	/* save lr */
110	mflr	r0
111	/* let's find out where our client stack is */
112	bcl	20, 31, client_over
113client_base:
114	.align	3
115.the_client_frame:
116	.quad   the_client_frame-client_base
117client_over:
118	mflr	r8				/* gpr 2 is the client_base */
119	mtlr	r0				/* restore the original lr */
120	ld	r0, .the_client_frame-client_base(r8)
121	add	r8, r0, r8			/* add the client_base */
122	/* r8 now contains the address of the_client_frame */
123
124	.irp i, 1,2,3,4,5,6,7, \
125		13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
126	ld 0,\i*8(8)
127	std \i,\i*8(8)
128	mr \i,0
129	.endr		# swap GPR1..7, GPR13..31
130
131	ld 0,0x100(8)
132	mfcr 9
133	mtcrf 0xff,0
134	std 9,0x100(8)	# swap CR
135
136	ld 0,0x128(8)
137	mfmsr 9
138	mtmsrd 0
139	sync
140	isync
141	std 9,0x128(8)	# swap MSR
142
143	blr
144
145	#
146	# Entry point for the OF client interface.
147	#
148
149        .globl client_entry_point
150        .section        ".opd","aw"
151        .align 3
152client_entry_point:
153        .quad   .client_entry_point,.TOC.@tocbase,0
154        .previous
155        .type   .client_entry_point,@function
156        .globl  .client_entry_point
157.client_entry_point:
158	mflr 4
159	bl swap_ci_regs	# swap regs
160	mtlr 4
161	li 3, 0 # client call
162	blr
163
164	#
165	# Start the client.
166	#
167
168        .globl call_client
169        .section        ".opd","aw"
170        .align 3
171call_client:
172        .quad   .call_client,.TOC.@tocbase,0
173        .previous
174        .type   .call_client,@function
175        .globl  .call_client
176
177.call_client:	# called with r3 = address, returns r3
178	mflr 4
179	mtctr 3
180	bl swap_ci_regs
181	/* Check if LE loading */
182	cmpwi 0,13,1
183	beq 0f
184	bctrl
185	b 1f
1860:	/* handle LE */
187	mfmsr 13
188	xori  13,13,1
189	mtsrr1 13
190	mfctr 13
191	mr 12,13
192	mtsrr0 13
193	rfid
194#if 0 /* in case we return back, still to be tested */
195	.long 0x05009f42; /* bcl 20,31,$+4   */
196	.long 0xa602c87d; /* mflr r14    */
197	.long 0x1c00ce39; /* addi r14,r14,28   */
198	.long 0xa600e07d; /* mfmsr r15    */
199	.long 0x0100ef69; /* xori r15,r15,1   */
200	.long 0xa603da7d; /* mtsrr0 r14    */
201	.long 0xa603fb7d; /* mtsrr1 r15    */
202	.long 0x2400004c; /* rfid */
203#endif
2041:
205	bl swap_ci_regs
206	mtlr 4
207	li 3, -1 # client app return
208	blr
209
210
211	# Call another function via pointer in r6
212	# (arguments can be provided in r3 to r5)
213	# Destination function should jump back to lr
214C_ENTRY(call_c)
215	mtctr	r6
216	bctr
217
218.global the_system_stack
219	.lcomm	the_system_stack, STACKSIZE, 16
220