/*
* Copyright 2006-2010, Ingo Weinhold <ingo_weinhold@gmx.de>.
* All rights reserved. Distributed under the terms of the MIT License.
*
* Copyright 2003, Travis Geiselbrecht. All rights reserved.
* Distributed under the terms of the NewOS License.
*/
#include "asm_defs.h"
#include "asm_offsets.h"
#define MSR_EXCEPTIONS_ENABLED 15
.text
// TODO: FIXME
FUNCTION(reboot):
b .
FUNCTION_END(reboot)
/* void arch_int_enable_interrupts(void) */
FUNCTION(arch_int_enable_interrupts):
mfmsr %r3 // load msr
li %r4, 1
insrwi %r3, %r4, 1, 31 - MSR_EXCEPTIONS_ENABLED
// sets bit 15, EE
mtmsr %r3 // put it back into the msr
isync
blr
FUNCTION_END(arch_int_enable_interrupts)
/* int arch_int_disable_interrupts(void)
* r3
*/
FUNCTION(arch_int_disable_interrupts):
mfmsr %r4 // load msr
mr %r3, %r4 // save old state
rlwinm %r4, %r4, 0, 32 - MSR_EXCEPTIONS_ENABLED, 30 - MSR_EXCEPTIONS_ENABLED
// clears bit 15, EE
mtmsr %r4 // put it back into the msr
isync
blr
FUNCTION_END(arch_int_disable_interrupts)
/* void arch_int_restore_interrupts(int oldState)
* r3
*/
FUNCTION(arch_int_restore_interrupts):
mfmsr %r4
rlwimi %r4, %r3, 0, 31 - MSR_EXCEPTIONS_ENABLED, 31 - MSR_EXCEPTIONS_ENABLED
// clear or set bit 15, EE to the same state as in r3, oldState
mtmsr %r4
isync
blr
FUNCTION_END(arch_int_restore_interrupts)
/* bool arch_int_are_interrupts_enabled(void) */
FUNCTION(arch_int_are_interrupts_enabled):
mfmsr %r3 // load msr
extrwi %r3, %r3, 1, 31 - MSR_EXCEPTIONS_ENABLED
// mask out the EE bit
blr
FUNCTION_END(arch_int_are_interrupts_enabled)
// TODO: FIXME
FUNCTION(dbg_save_registers):
blr
FUNCTION_END(dbg_save_registers)
/* long long get_time_base(void) */
FUNCTION(get_time_base):
1:
mftbu %r3 // get the upper time base register
mftb %r4 // get the lower time base register
mftbu %r5 // get the upper again
cmpw %r5, %r3 // see if it changed while we were reading the lower
bne- 1b // if so, repeat
blr
FUNCTION_END(get_time_base)
/* void getibats(int bats[8])
FUNCTION(getibats):
mfibatu %r0,0
stw %r0,0(%r3)
mfibatl %r0,0
stwu %r0,4(%r3)
mfibatu %r0,1
stwu %r0,4(%r3)
mfibatl %r0,1
stwu %r0,4(%r3)
mfibatu %r0,2
stwu %r0,4(%r3)
mfibatl %r0,2
stwu %r0,4(%r3)
mfibatu %r0,3
stwu %r0,4(%r3)
mfibatl %r0,3
stwu %r0,4(%r3)
blr
FUNCTION_END(getibats)
// void setibats(int bats[8])
FUNCTION(setibats):
lwz %r0,0(%r3)
mtibatu 0,%r0
isync
lwzu %r0,4(%r3)
mtibatl 0,%r0
isync
lwzu %r0,4(%r3)
mtibatu 1,%r0
isync
lwzu %r0,4(%r3)
mtibatl 1,%r0
isync
lwzu %r0,4(%r3)
mtibatu 2,%r0
isync
lwzu %r0,4(%r3)
mtibatl 2,%r0
isync
lwzu %r0,4(%r3)
mtibatu 3,%r0
isync
lwzu %r0,4(%r3)
mtibatl 3,%r0
isync
blr
FUNCTION_END(setibats)
// void getdbats(int bats[8])
FUNCTION(getdbats):
mfdbatu %r0,0
stw %r0,0(%r3)
mfdbatl %r0,0
stwu %r0,4(%r3)
mfdbatu %r0,1
stwu %r0,4(%r3)
mfdbatl %r0,1
stwu %r0,4(%r3)
mfdbatu %r0,2
stwu %r0,4(%r3)
mfdbatl %r0,2
stwu %r0,4(%r3)
mfdbatu %r0,3
stwu %r0,4(%r3)
mfdbatl %r0,3
stwu %r0,4(%r3)
blr
FUNCTION_END(getdbats)
// void setdbats(int bats[8])
FUNCTION(setdbats):
lwz %r0,0(%r3)
mtdbatu 0,%r0
lwzu %r0,4(%r3)
mtdbatl 0,%r0
lwzu %r0,4(%r3)
mtdbatu 1,%r0
lwzu %r0,4(%r3)
mtdbatl 1,%r0
lwzu %r0,4(%r3)
mtdbatu 2,%r0
lwzu %r0,4(%r3)
mtdbatl 2,%r0
lwzu %r0,4(%r3)
mtdbatu 3,%r0
lwzu %r0,4(%r3)
mtdbatl 3,%r0
sync
blr
FUNCTION_END(setdbats)
// unsigned int gethid0()
FUNCTION(gethid0):
mfspr %r3, 1008
blr
FUNCTION_END(gethid0)
// void sethid0(unsigned int val)
FUNCTION(sethid0):
isync
mtspr 1008, %r3
isync
blr
FUNCTION_END(sethid0)
// unsigned int getl2cr()
FUNCTION(getl2cr):
mfspr %r3, 1017
blr
FUNCTION_END(getl2cr)
// void setl2cr(unsigned int val)
FUNCTION(setl2cr):
isync
mtspr 1017, %r3
isync
blr
FUNCTION_END(setl2cr)
// void ppc_context_switch(addr_t *old_sp, addr_t new_sp)
FUNCTION(ppc_context_switch):
// regs to push on the stack: f13-f31, r13-r31, cr, r2, lr
// push the old regs we need to save on the stack
// f31-13
stfdu %f31, -8(%r1)
stfdu %f30, -8(%r1)
stfdu %f29, -8(%r1)
stfdu %f28, -8(%r1)
stfdu %f27, -8(%r1)
stfdu %f26, -8(%r1)
stfdu %f25, -8(%r1)
stfdu %f24, -8(%r1)
stfdu %f23, -8(%r1)
stfdu %f22, -8(%r1)
stfdu %f21, -8(%r1)
stfdu %f20, -8(%r1)
stfdu %f19, -8(%r1)
stfdu %f18, -8(%r1)
stfdu %f17, -8(%r1)
stfdu %f16, -8(%r1)
stfdu %f15, -8(%r1)
stfdu %f14, -8(%r1)
stfdu %f13, -8(%r1)
// r31-13, r2
stwu %r31, -4(%r1)
stwu %r30, -4(%r1)
stwu %r29, -4(%r1)
stwu %r28, -4(%r1)
stwu %r27, -4(%r1)
stwu %r26, -4(%r1)
stwu %r25, -4(%r1)
stwu %r24, -4(%r1)
stwu %r23, -4(%r1)
stwu %r22, -4(%r1)
stwu %r21, -4(%r1)
stwu %r20, -4(%r1)
stwu %r19, -4(%r1)
stwu %r18, -4(%r1)
stwu %r17, -4(%r1)
stwu %r16, -4(%r1)
stwu %r15, -4(%r1)
stwu %r14, -4(%r1)
stwu %r13, -4(%r1)
stwu %r2, -4(%r1)
// CR and LR
mfcr %r0
stwu %r0, -4(%r1)
mflr %r0
stwu %r0, -4(%r1)
// save the old stack pointer
stwu %r1, 0(%r3)
// restore the new stack pointer
mr %r1, %r4
// restore the new regs
// LR and CR
lwz %r0, 0(%r1)
mtlr %r0
lwzu %r0, 4(%r1)
mtcr %r0
// r2, r13-31
lwzu %r2, 4(%r1)
lwzu %r13, 4(%r1)
lwzu %r14, 4(%r1)
lwzu %r15, 4(%r1)
lwzu %r16, 4(%r1)
lwzu %r17, 4(%r1)
lwzu %r18, 4(%r1)
lwzu %r19, 4(%r1)
lwzu %r20, 4(%r1)
lwzu %r21, 4(%r1)
lwzu %r22, 4(%r1)
lwzu %r23, 4(%r1)
lwzu %r24, 4(%r1)
lwzu %r25, 4(%r1)
lwzu %r26, 4(%r1)
lwzu %r27, 4(%r1)
lwzu %r28, 4(%r1)
lwzu %r29, 4(%r1)
lwzu %r30, 4(%r1)
lwzu %r31, 4(%r1)
// f13-31
lfdu %f13, 4(%r1)
lfdu %f14, 8(%r1)
lfdu %f15, 8(%r1)
lfdu %f16, 8(%r1)
lfdu %f17, 8(%r1)
lfdu %f18, 8(%r1)
lfdu %f19, 8(%r1)
lfdu %f20, 8(%r1)
lfdu %f21, 8(%r1)
lfdu %f22, 8(%r1)
lfdu %f23, 8(%r1)
lfdu %f24, 8(%r1)
lfdu %f25, 8(%r1)
lfdu %f26, 8(%r1)
lfdu %f27, 8(%r1)
lfdu %f28, 8(%r1)
lfdu %f29, 8(%r1)
lfdu %f30, 8(%r1)
lfdu %f31, 8(%r1)
addi %r1, %r1, 8
blr
FUNCTION_END(ppc_context_switch)
// ppc_kernel_thread_root(): parameters in r13-r15, the functions to call
// (in that order). The function is used when spawing threads. It usually calls
// an initialization function, the actual thread function, and a function that
// destroys the thread.
FUNCTION(ppc_kernel_thread_root):
mtlr %r13
blrl
mtlr %r14
blrl
mtlr %r15
blrl
// We should never get here. If we do, it's time to enter the kernel
// debugger (without a message at the moment).
li %r3, 0
b kernel_debugger
FUNCTION_END(ppc_kernel_thread_root)
/*! \fn void arch_debug_call_with_fault_handler(cpu_ent* cpu,
jmp_buf jumpBuffer, void (*function)(void*), void* parameter)
Called by debug_call_with_fault_handler() to do the dirty work of setting
the fault handler and calling the function. If the function causes a page
fault, the arch_debug_call_with_fault_handler() calls longjmp() with the
given \a jumpBuffer. Otherwise it returns normally.
debug_call_with_fault_handler() has already saved the CPU's fault_handler
and fault_handler_stack_pointer and will reset them later, so
arch_debug_call_with_fault_handler() doesn't need to care about it.
\param cpu The \c cpu_ent for the current CPU.
\param jumpBuffer Buffer to be used for longjmp().
\param function The function to be called.
\param parameter The parameter to be passed to the function to be called.
*/
FUNCTION(arch_debug_call_with_fault_handler):
// prolog: setup stack frame (16-byte aligned)
mflr %r0
stw %r0, 4(%r1) // store LR
stwu %r1, -16(%r1) // store back chain
stw %r4, 8(%r1) // store jumpBuffer
// set cpu->fault_handler_stack_pointer
stw %r1, CPU_ENT_fault_handler_stack_pointer(%r3)
// set cpu->fault_handler
lis %r11, 1f@ha
ori %r11, %r11, 1f@l
stw %r11, CPU_ENT_fault_handler(%r3)
// call the given function
mr %r3, %r6
mtlr %r5
blrl
// epilog: restore stack frame
lwz %r0, 16 + 4(%r1) // load LR
mtlr %r0
addi %r1, %r1, 16 // restore SP
blr
// fault -- return via longjmp(jumpBuffer, 1)
1:
lwz %r3, 8(%r1) // load jumpBuffer
// call longjmp
li %r4, 1
lis %r0, longjmp@ha
ori %r0, %r0, longjmp@l
mtlr %r0
blr
FUNCTION_END(arch_debug_call_with_fault_handler)
/* status_t arch_cpu_user_memcpy(void *to, const void *from, size_t size, addr_t *faultHandler) */
FUNCTION(_arch_cpu_user_memcpy):
// TODO
blr
FUNCTION_END(_arch_cpu_user_memcpy)
/* status_t arch_cpu_user_memset(void *to, char c, size_t count, addr_t *faultHandler) */
FUNCTION(_arch_cpu_user_memset):
// TODO
blr
FUNCTION_END(_arch_cpu_user_memset)
/* ssize_t arch_cpu_user_strlcpy(void *to, const void *from, size_t size, addr_t *faultHandler) */
FUNCTION(_arch_cpu_user_strlcpy):
// TODO
blr
FUNCTION_END(_arch_cpu_user_strlcpy)