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