[acc25ee] | 1 | /* |
---|
| 2 | * PowerPC CPU Dependent Source |
---|
[78a38fa2] | 3 | */ |
---|
| 4 | |
---|
| 5 | /* |
---|
| 6 | * Author: Andrew Bray <andy@i-cubed.co.uk> |
---|
[acc25ee] | 7 | * |
---|
| 8 | * COPYRIGHT (c) 1995 by i-cubed ltd. |
---|
| 9 | * |
---|
| 10 | * To anyone who acknowledges that this file is provided "AS IS" |
---|
| 11 | * without any express or implied warranty: |
---|
| 12 | * permission to use, copy, modify, and distribute this file |
---|
| 13 | * for any purpose is hereby granted without fee, provided that |
---|
| 14 | * the above copyright notice and this notice appears in all |
---|
| 15 | * copies, and that the name of i-cubed limited not be used in |
---|
| 16 | * advertising or publicity pertaining to distribution of the |
---|
| 17 | * software without specific, written prior permission. |
---|
| 18 | * i-cubed limited makes no representations about the suitability |
---|
| 19 | * of this software for any purpose. |
---|
| 20 | * |
---|
| 21 | * Derived from c/src/exec/cpu/no_cpu/cpu.c: |
---|
| 22 | * |
---|
| 23 | * COPYRIGHT (c) 1989-1997. |
---|
| 24 | * On-Line Applications Research Corporation (OAR). |
---|
| 25 | * |
---|
| 26 | * The license and distribution terms for this file may be found in |
---|
| 27 | * the file LICENSE in this distribution or at |
---|
[c499856] | 28 | * http://www.rtems.org/license/LICENSE. |
---|
[acc25ee] | 29 | */ |
---|
| 30 | |
---|
[fdd9de80] | 31 | #include <string.h> |
---|
| 32 | |
---|
[acc25ee] | 33 | #include <rtems/system.h> |
---|
| 34 | #include <rtems/score/isr.h> |
---|
| 35 | #include <rtems/score/context.h> |
---|
| 36 | #include <rtems/score/thread.h> |
---|
| 37 | #include <rtems/score/interr.h> |
---|
[c7f8408d] | 38 | #include <rtems/score/cpu.h> |
---|
[022851a] | 39 | #include <rtems/score/tls.h> |
---|
[3e5a93cc] | 40 | #include <rtems/powerpc/powerpc.h> |
---|
[acc25ee] | 41 | |
---|
| 42 | /* _CPU_Initialize |
---|
| 43 | * |
---|
| 44 | * This routine performs processor dependent initialization. |
---|
| 45 | */ |
---|
[9b974cf4] | 46 | void _CPU_Initialize(void) |
---|
[acc25ee] | 47 | { |
---|
[3e2647a7] | 48 | #if defined(__ALTIVEC__) && !defined(PPC_MULTILIB_ALTIVEC) |
---|
[c7f8408d] | 49 | _CPU_Initialize_altivec(); |
---|
| 50 | #endif |
---|
[acc25ee] | 51 | } |
---|
| 52 | |
---|
[78a38fa2] | 53 | /* |
---|
[acc25ee] | 54 | * _CPU_Context_Initialize |
---|
| 55 | */ |
---|
| 56 | void _CPU_Context_Initialize( |
---|
| 57 | Context_Control *the_context, |
---|
[7837728b] | 58 | void *stack_base, |
---|
| 59 | size_t size, |
---|
[9347024] | 60 | uint32_t new_level, |
---|
[acc25ee] | 61 | void *entry_point, |
---|
[022851a] | 62 | bool is_fp, |
---|
| 63 | void *tls_area |
---|
[acc25ee] | 64 | ) |
---|
| 65 | { |
---|
[1869bb7] | 66 | ppc_context *the_ppc_context; |
---|
[0a7a30d] | 67 | uint32_t msr_value = 0; |
---|
[7837728b] | 68 | uintptr_t sp; |
---|
| 69 | uintptr_t stack_alignment; |
---|
[acc25ee] | 70 | |
---|
[7837728b] | 71 | sp = (uintptr_t) stack_base + size - PPC_MINIMUM_STACK_FRAME_SIZE; |
---|
[ab504d3] | 72 | |
---|
[7837728b] | 73 | stack_alignment = CPU_STACK_ALIGNMENT; |
---|
| 74 | sp &= ~(stack_alignment - 1); |
---|
[ab504d3] | 75 | |
---|
[7837728b] | 76 | sp = (uintptr_t) memset((void *) sp, 0, PPC_MINIMUM_STACK_FRAME_SIZE); |
---|
[6128a4a] | 77 | |
---|
[3e2647a7] | 78 | the_ppc_context = ppc_get_context( the_context ); |
---|
| 79 | |
---|
[0a7a30d] | 80 | #if !defined(PPC_DISABLE_MSR_ACCESS) |
---|
| 81 | _CPU_MSR_GET( msr_value ); |
---|
| 82 | |
---|
[d60239f] | 83 | /* |
---|
| 84 | * Setting the interrupt mask here is not strictly necessary |
---|
| 85 | * since the IRQ level will be established from _Thread_Handler() |
---|
| 86 | * again, as soon as the task starts execution. |
---|
| 87 | * Because we have to establish a defined state anyways we |
---|
| 88 | * can as well leave this code here. |
---|
| 89 | * I.e., simply (and unconditionally) saying |
---|
| 90 | * |
---|
| 91 | * msr_value &= ~ppc_interrupt_get_disable_mask(); |
---|
| 92 | * |
---|
| 93 | * would be an alternative. |
---|
| 94 | */ |
---|
| 95 | |
---|
[acc25ee] | 96 | if (!(new_level & CPU_MODES_INTERRUPT_MASK)) { |
---|
[d60239f] | 97 | msr_value |= ppc_interrupt_get_disable_mask(); |
---|
[acc25ee] | 98 | } |
---|
| 99 | else { |
---|
[d60239f] | 100 | msr_value &= ~ppc_interrupt_get_disable_mask(); |
---|
[acc25ee] | 101 | } |
---|
| 102 | |
---|
[3e2647a7] | 103 | #ifdef PPC_MULTILIB_FPU |
---|
[acc25ee] | 104 | /* |
---|
| 105 | * The FP bit of the MSR should only be enabled if this is a floating |
---|
[6128a4a] | 106 | * point task. Unfortunately, the vfprintf_r routine in newlib |
---|
[acc25ee] | 107 | * ends up pushing a floating point register regardless of whether or |
---|
| 108 | * not a floating point number is being printed. Serious restructuring |
---|
| 109 | * of vfprintf.c will be required to avoid this behavior. At this |
---|
| 110 | * time (7 July 1997), this restructuring is not being done. |
---|
| 111 | */ |
---|
[335e5ca] | 112 | msr_value |= MSR_FP; |
---|
[3e2647a7] | 113 | #endif |
---|
| 114 | |
---|
| 115 | #ifdef PPC_MULTILIB_ALTIVEC |
---|
| 116 | msr_value |= MSR_VE; |
---|
[0a7a30d] | 117 | #endif |
---|
| 118 | #endif /* END PPC_DISABLE_MSR_ACCESS */ |
---|
[3e2647a7] | 119 | |
---|
[0a7a30d] | 120 | #ifdef PPC_MULTILIB_ALTIVEC |
---|
[3e2647a7] | 121 | the_ppc_context->vrsave = 0; |
---|
| 122 | #endif |
---|
[fdd9de80] | 123 | |
---|
[1869bb7] | 124 | the_ppc_context->gpr1 = sp; |
---|
| 125 | the_ppc_context->msr = msr_value; |
---|
[7837728b] | 126 | the_ppc_context->lr = (uintptr_t) entry_point; |
---|
[f65dcc71] | 127 | the_ppc_context->isr_dispatch_disable = 0; |
---|
[c7f8408d] | 128 | |
---|
[3e2647a7] | 129 | #if defined(__ALTIVEC__) && !defined(PPC_MULTILIB_ALTIVEC) |
---|
[56435e6] | 130 | _CPU_Context_initialize_altivec( the_ppc_context ); |
---|
[c7f8408d] | 131 | #endif |
---|
[022851a] | 132 | |
---|
| 133 | if ( tls_area != NULL ) { |
---|
[320faf8e] | 134 | void *tls_block = _TLS_TCB_before_TLS_block_initialize( tls_area ); |
---|
[022851a] | 135 | |
---|
[a6f84b27] | 136 | the_ppc_context->tp = (uintptr_t) tls_block + 0x7000; |
---|
[022851a] | 137 | } |
---|
[acc25ee] | 138 | } |
---|