void _CPU_Context_Initialize( Context_Control *the_context, uint32_t *stack_base, uint32_t size, uint32_t new_level, void *entry_point, bool is_fp ) { uint32_t msr_value; uint32_t sp; sp = (uint32_t)stack_base + size - PPC_MINIMUM_STACK_FRAME_SIZE; sp &= ~(CPU_STACK_ALIGNMENT-1); *((uint32_t*)sp) = 0; _CPU_MSR_GET( msr_value ); /* * Setting the interrupt mask here is not strictly necessary * since the IRQ level will be established from _Thread_Handler() * again, as soon as the task starts execution. * Because we have to establish a defined state anyways we * can as well leave this code here. * I.e., simply (and unconditionally) saying * * msr_value &= ~ppc_interrupt_get_disable_mask(); * * would be an alternative. */ if (!(new_level & CPU_MODES_INTERRUPT_MASK)) { msr_value |= ppc_interrupt_get_disable_mask(); } else { msr_value &= ~ppc_interrupt_get_disable_mask(); } /* * The FP bit of the MSR should only be enabled if this is a floating * point task. Unfortunately, the vfprintf_r routine in newlib * ends up pushing a floating point register regardless of whether or * not a floating point number is being printed. Serious restructuring * of vfprintf.c will be required to avoid this behavior. At this * time (7 July 1997), this restructuring is not being done. */ /* Make sure integer tasks have no FPU access in order to * catch violations. Gcc may implicitely use the FPU and * data corruption may happen. * Since we set the_contex->msr using our current MSR, * we must make sure MSR_FP is off if (!is_fp)... * Unfortunately, this means that users of vfprintf_r have to use FP * tasks or fix vfprintf. Furthermore, users of int-only tasks * must prevent gcc from using the FPU (currently -msoft-float is the * only way...) */ if ( is_fp ) msr_value |= PPC_MSR_FP; else msr_value &= ~PPC_MSR_FP; memset( the_context, 0, sizeof( *the_context ) ); PPC_CONTEXT_SET_SP( the_context, sp ); PPC_CONTEXT_SET_PC( the_context, (uint32_t) entry_point ); PPC_CONTEXT_SET_MSR( the_context, msr_value ); #ifndef __SPE__ #if (PPC_ABI == PPC_ABI_SVR4) /* * SVR4 says R2 is for 'system-reserved' use; it cannot hurt to * propagate R2 to all task contexts. */ { uint32_t r2 = 0; unsigned r13 = 0; __asm__ volatile ("mr %0,2; mr %1,13" : "=r" ((r2)), "=r" ((r13))); the_context->gpr2 = r2; the_context->gpr13 = r13; } #elif (PPC_ABI == PPC_ABI_EABI) { uint32_t r2 = 0; unsigned r13 = 0; __asm__ volatile ("mr %0,2; mr %1,13" : "=r" ((r2)), "=r" ((r13))); the_context->gpr2 = r2; the_context->gpr13 = r13; } #else #error unsupported PPC_ABI #endif #endif /* __SPE__ */ #ifdef __ALTIVEC__ _CPU_Context_initialize_altivec(the_context); #endif }
rtems_status_code ppc_exc_make_prologue( unsigned vector, ppc_exc_category category, uint32_t *prologue, size_t *prologue_size ) { const uint32_t *prologue_template = NULL; size_t prologue_template_size = 0; bool fixup_vector = false; if (!ppc_exc_is_valid_category(category)) { return RTEMS_INVALID_NUMBER; } if ( ppc_cpu_has_shadowed_gprs() && (vector == ASM_60X_IMISS_VECTOR || vector == ASM_60X_DLMISS_VECTOR || vector == ASM_60X_DSMISS_VECTOR) ) { prologue_template = ppc_exc_tgpr_clr_prolog; prologue_template_size = (size_t) ppc_exc_tgpr_clr_prolog_size; } else if ( category == PPC_EXC_CLASSIC && ppc_cpu_is_bookE() != PPC_BOOKE_STD && ppc_cpu_is_bookE() != PPC_BOOKE_E500 ) { prologue_template = ppc_exc_min_prolog_auto; prologue_template_size = (size_t) ppc_exc_min_prolog_size; } else if ( category == PPC_EXC_CLASSIC_ASYNC && ppc_cpu_is_bookE() == PPC_BOOKE_E500 && (ppc_interrupt_get_disable_mask() & MSR_CE) == 0 ) { prologue_template = ppc_exc_min_prolog_async_tmpl_normal; prologue_template_size = (size_t) ppc_exc_min_prolog_size; fixup_vector = true; } else { prologue_template = ppc_exc_prologue_templates [category]; prologue_template_size = (size_t) ppc_exc_min_prolog_size; fixup_vector = true; } if (prologue_template_size <= *prologue_size) { *prologue_size = prologue_template_size; memcpy(prologue, prologue_template, prologue_template_size); if (!ppc_exc_create_branch_op(vector, prologue, prologue_template_size)) { return RTEMS_INVALID_ADDRESS; } if (fixup_vector) { if (vector <= 0x7fffU) { prologue [PPC_EXC_PROLOG_VEC_OFFSET] = (prologue [PPC_EXC_PROLOG_VEC_OFFSET] & 0xffff8000U) | (vector & 0x7fffU); } else { return RTEMS_INVALID_ID; } } } else { return RTEMS_INVALID_SIZE; } return RTEMS_SUCCESSFUL; }