1/*
2 * Copyright 2006-2010, Ingo Weinhold <ingo_weinhold@gmx.de>.
3 * All rights reserved. Distributed under the terms of the MIT License.
4 *
5 * Copyright 2003, Travis Geiselbrecht. All rights reserved.
6 * Distributed under the terms of the NewOS License.
7 */
8
9
10#include "asm_offsets.h"
11
12#define FUNCTION(x) .global x; .type x,@function; x
13
14#define MSR_EXCEPTIONS_ENABLED 15
15
16.text
17
18// ToDo: fixme
19FUNCTION(reboot):
20    b   .
21
22
23/* void arch_int_enable_interrupts(void) */
24FUNCTION(arch_int_enable_interrupts):
25	mfmsr	%r3							// load msr
26
27	li		%r4, 1
28	insrwi  %r3, %r4, 1, 31 - MSR_EXCEPTIONS_ENABLED
29		// sets bit 15, EE
30
31	mtmsr	%r3							// put it back into the msr
32	isync
33	blr
34
35
36/* int arch_int_disable_interrupts(void)
37 * r3
38 */
39FUNCTION(arch_int_disable_interrupts):
40	mfmsr	%r4							// load msr
41
42	mr		%r3, %r4					// save old state
43	rlwinm  %r4, %r4, 0, 32 - MSR_EXCEPTIONS_ENABLED, 30 - MSR_EXCEPTIONS_ENABLED
44		// clears bit 15, EE
45
46	mtmsr	%r4							// put it back into the msr
47	isync
48	blr
49
50
51/* void arch_int_restore_interrupts(int oldState)
52 *									r3
53 */
54FUNCTION(arch_int_restore_interrupts):
55	mfmsr	%r4
56
57	rlwimi  %r4, %r3, 0, 31 - MSR_EXCEPTIONS_ENABLED, 31 - MSR_EXCEPTIONS_ENABLED
58		// clear or set bit 15, EE to the same state as in r3, oldState
59
60	mtmsr	%r4
61	isync
62	blr
63
64/* bool arch_int_are_interrupts_enabled(void) */
65FUNCTION(arch_int_are_interrupts_enabled):
66	mfmsr	%r3							// load msr
67	extrwi	%r3, %r3, 1, 31 - MSR_EXCEPTIONS_ENABLED
68		// mask out the EE bit
69	blr
70
71
72// ToDo: fixme
73FUNCTION(dbg_save_registers):
74	blr
75
76/* long long get_time_base(void) */
77FUNCTION(get_time_base):
781:
79	mftbu	%r3							// get the upper time base register
80	mftb	%r4							// get the lower time base register
81	mftbu	%r5							// get the upper again
82	cmpw	%r5, %r3					// see if it changed while we were reading the lower
83	bne-	1b							// if so, repeat
84	blr
85
86/* void getibats(int bats[8]); */
87FUNCTION(getibats):
88	mfibatu 	%r0,0
89	stw     	%r0,0(%r3)
90	mfibatl 	%r0,0
91	stwu		%r0,4(%r3)
92	mfibatu 	%r0,1
93	stwu		%r0,4(%r3)
94	mfibatl 	%r0,1
95	stwu		%r0,4(%r3)
96	mfibatu 	%r0,2
97	stwu		%r0,4(%r3)
98	mfibatl 	%r0,2
99	stwu		%r0,4(%r3)
100	mfibatu 	%r0,3
101	stwu		%r0,4(%r3)
102	mfibatl 	%r0,3
103	stwu		%r0,4(%r3)
104	blr
105
106// void setibats(int bats[8]);
107FUNCTION(setibats):
108	lwz			%r0,0(%r3)
109	mtibatu 	0,%r0
110	isync
111	lwzu		%r0,4(%r3)
112	mtibatl 	0,%r0
113	isync
114	lwzu		%r0,4(%r3)
115	mtibatu 	1,%r0
116	isync
117	lwzu		%r0,4(%r3)
118	mtibatl 	1,%r0
119	isync
120	lwzu		%r0,4(%r3)
121	mtibatu 	2,%r0
122	isync
123	lwzu		%r0,4(%r3)
124	mtibatl 	2,%r0
125	isync
126	lwzu		%r0,4(%r3)
127	mtibatu 	3,%r0
128	isync
129	lwzu		%r0,4(%r3)
130	mtibatl 	3,%r0
131	isync
132
133	blr
134
135// void getdbats(int bats[8]);
136FUNCTION(getdbats):
137	mfdbatu 	%r0,0
138	stw     	%r0,0(%r3)
139	mfdbatl 	%r0,0
140	stwu		%r0,4(%r3)
141	mfdbatu 	%r0,1
142	stwu		%r0,4(%r3)
143	mfdbatl 	%r0,1
144	stwu		%r0,4(%r3)
145	mfdbatu 	%r0,2
146	stwu		%r0,4(%r3)
147	mfdbatl 	%r0,2
148	stwu		%r0,4(%r3)
149	mfdbatu		%r0,3
150	stwu		%r0,4(%r3)
151	mfdbatl 	%r0,3
152	stwu		%r0,4(%r3)
153	blr
154
155// void setdbats(int bats[8]);
156FUNCTION(setdbats):
157	lwz			%r0,0(%r3)
158	mtdbatu 	0,%r0
159	lwzu		%r0,4(%r3)
160	mtdbatl 	0,%r0
161	lwzu		%r0,4(%r3)
162	mtdbatu 	1,%r0
163	lwzu		%r0,4(%r3)
164	mtdbatl 	1,%r0
165	lwzu		%r0,4(%r3)
166	mtdbatu 	2,%r0
167	lwzu		%r0,4(%r3)
168	mtdbatl 	2,%r0
169	lwzu		%r0,4(%r3)
170	mtdbatu 	3,%r0
171	lwzu		%r0,4(%r3)
172	mtdbatl 	3,%r0
173	sync
174
175	blr
176
177// unsigned int gethid0();
178FUNCTION(gethid0):
179	mfspr		%r3, 1008
180	blr
181
182// void sethid0(unsigned int val);
183FUNCTION(sethid0):
184	isync
185	mtspr		1008, %r3
186	isync
187	blr
188
189// unsigned int getl2cr();
190FUNCTION(getl2cr):
191	mfspr		%r3, 1017
192	blr
193
194// void setl2cr(unsigned int val);
195FUNCTION(setl2cr):
196	isync
197	mtspr		1017, %r3
198	isync
199	blr
200
201
202// void ppc_context_switch(addr_t *old_sp, addr_t new_sp);
203FUNCTION(ppc_context_switch):
204
205	// regs to push on the stack: f13-f31, r13-r31, cr, r2, lr
206
207	// push the old regs we need to save on the stack
208	// f31-13
209	stfdu		%f31, -8(%r1)
210	stfdu		%f30, -8(%r1)
211	stfdu		%f29, -8(%r1)
212	stfdu		%f28, -8(%r1)
213	stfdu		%f27, -8(%r1)
214	stfdu		%f26, -8(%r1)
215	stfdu		%f25, -8(%r1)
216	stfdu		%f24, -8(%r1)
217	stfdu		%f23, -8(%r1)
218	stfdu		%f22, -8(%r1)
219	stfdu		%f21, -8(%r1)
220	stfdu		%f20, -8(%r1)
221	stfdu		%f19, -8(%r1)
222	stfdu		%f18, -8(%r1)
223	stfdu		%f17, -8(%r1)
224	stfdu		%f16, -8(%r1)
225	stfdu		%f15, -8(%r1)
226	stfdu		%f14, -8(%r1)
227	stfdu		%f13, -8(%r1)
228
229	// r31-13, r2
230	stwu		%r31, -4(%r1)
231	stwu		%r30, -4(%r1)
232	stwu		%r29, -4(%r1)
233	stwu		%r28, -4(%r1)
234	stwu		%r27, -4(%r1)
235	stwu		%r26, -4(%r1)
236	stwu		%r25, -4(%r1)
237	stwu		%r24, -4(%r1)
238	stwu		%r23, -4(%r1)
239	stwu		%r22, -4(%r1)
240	stwu		%r21, -4(%r1)
241	stwu		%r20, -4(%r1)
242	stwu		%r19, -4(%r1)
243	stwu		%r18, -4(%r1)
244	stwu		%r17, -4(%r1)
245	stwu		%r16, -4(%r1)
246	stwu		%r15, -4(%r1)
247	stwu		%r14, -4(%r1)
248	stwu		%r13, -4(%r1)
249	stwu		%r2, -4(%r1)
250
251	// CR and LR
252	mfcr		%r0
253	stwu		%r0, -4(%r1)
254	mflr		%r0
255	stwu		%r0, -4(%r1)
256
257	// save the old stack pointer
258	stwu		%r1, 0(%r3)
259
260	// restore the new stack pointer
261	mr			%r1, %r4
262
263	// restore the new regs
264	// LR and CR
265	lwz			%r0, 0(%r1)
266	mtlr		%r0
267	lwzu		%r0, 4(%r1)
268	mtcr		%r0
269
270	// r2, r13-31
271	lwzu		%r2, 4(%r1)
272	lwzu		%r13, 4(%r1)
273	lwzu		%r14, 4(%r1)
274	lwzu		%r15, 4(%r1)
275	lwzu		%r16, 4(%r1)
276	lwzu		%r17, 4(%r1)
277	lwzu		%r18, 4(%r1)
278	lwzu		%r19, 4(%r1)
279	lwzu		%r20, 4(%r1)
280	lwzu		%r21, 4(%r1)
281	lwzu		%r22, 4(%r1)
282	lwzu		%r23, 4(%r1)
283	lwzu		%r24, 4(%r1)
284	lwzu		%r25, 4(%r1)
285	lwzu		%r26, 4(%r1)
286	lwzu		%r27, 4(%r1)
287	lwzu		%r28, 4(%r1)
288	lwzu		%r29, 4(%r1)
289	lwzu		%r30, 4(%r1)
290	lwzu		%r31, 4(%r1)
291
292	// f13-31
293	lfdu		%f13, 4(%r1)
294	lfdu		%f14, 8(%r1)
295	lfdu		%f15, 8(%r1)
296	lfdu		%f16, 8(%r1)
297	lfdu		%f17, 8(%r1)
298	lfdu		%f18, 8(%r1)
299	lfdu		%f19, 8(%r1)
300	lfdu		%f20, 8(%r1)
301	lfdu		%f21, 8(%r1)
302	lfdu		%f22, 8(%r1)
303	lfdu		%f23, 8(%r1)
304	lfdu		%f24, 8(%r1)
305	lfdu		%f25, 8(%r1)
306	lfdu		%f26, 8(%r1)
307	lfdu		%f27, 8(%r1)
308	lfdu		%f28, 8(%r1)
309	lfdu		%f29, 8(%r1)
310	lfdu		%f30, 8(%r1)
311	lfdu		%f31, 8(%r1)
312
313	addi		%r1, %r1, 8
314
315	blr
316
317
318// ppc_kernel_thread_root(): parameters in r13-r15, the functions to call
319// (in that order). The function is used when spawing threads. It usually calls
320// an initialization function, the actual thread function, and a function that
321// destroys the thread.
322FUNCTION(ppc_kernel_thread_root):
323	mtlr		%r13
324	blrl
325	mtlr		%r14
326	blrl
327	mtlr		%r15
328	blrl
329
330	// We should never get here. If we do, it's time to enter the kernel
331	// debugger (without a message at the moment).
332	li			%r3, 0
333	b			kernel_debugger
334
335
336/*!	\fn void arch_debug_call_with_fault_handler(cpu_ent* cpu,
337		jmp_buf jumpBuffer, void (*function)(void*), void* parameter)
338
339	Called by debug_call_with_fault_handler() to do the dirty work of setting
340	the fault handler and calling the function. If the function causes a page
341	fault, the arch_debug_call_with_fault_handler() calls longjmp() with the
342	given \a jumpBuffer. Otherwise it returns normally.
343
344	debug_call_with_fault_handler() has already saved the CPU's fault_handler
345	and fault_handler_stack_pointer and will reset them later, so
346	arch_debug_call_with_fault_handler() doesn't need to care about it.
347
348	\param cpu The \c cpu_ent for the current CPU.
349	\param jumpBuffer Buffer to be used for longjmp().
350	\param function The function to be called.
351	\param parameter The parameter to be passed to the function to be called.
352*/
353FUNCTION(arch_debug_call_with_fault_handler):
354	// prolog: setup stack frame (16-byte aligned)
355	mflr	%r0
356	stw		%r0, 4(%r1)		// store LR
357	stwu	%r1, -16(%r1)	// store back chain
358	stw		%r4, 8(%r1)		// store jumpBuffer
359
360	// set cpu->fault_handler_stack_pointer
361	stw		%r1, CPU_ENT_fault_handler_stack_pointer(%r3)
362
363	// set cpu->fault_handler
364	lis		%r11, 1f@ha
365	ori		%r11, %r11, 1f@l
366	stw		%r11, CPU_ENT_fault_handler(%r3)
367
368	// call the given function
369	mr		%r3, %r6
370	mtlr	%r5
371	blrl
372
373	// epilog: restore stack frame
374	lwz		%r0, 16 + 4(%r1)	// load LR
375	mtlr	%r0
376	addi	%r1, %r1, 16		// restore SP
377
378	blr
379
380	// fault -- return via longjmp(jumpBuffer, 1)
3811:
382	lwz		%r3, 8(%r1) 		// load jumpBuffer
383
384	// call longjmp
385	li		%r4, 1
386	lis		%r0, longjmp@ha
387	ori		%r0, %r0, longjmp@l
388	mtlr	%r0
389	blr
390