/* * Copyright 2006-2010, Ingo Weinhold . * 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)