diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2011-07-21 15:03:31 +0000 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2011-07-21 15:03:31 +0000 |
commit | fdd9de8001b9edbbe57ecf6de015cb3f1f5b27ad (patch) | |
tree | d6f21a8c1ead8f004f96e616bea2c59f6473f5e7 /c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_async_normal.S | |
parent | 2011-07-21 Sebastian Huber <sebastian.huber@embedded-brains.de> (diff) | |
download | rtems-fdd9de8001b9edbbe57ecf6de015cb3f1f5b27ad.tar.bz2 |
2011-07-21 Sebastian Huber <sebastian.huber@embedded-brains.de>
PR 1799/bsps
* new-exceptions/bspsupport/ppc_exc_async_normal.S: New file.
* new-exceptions/cpu.c, new-exceptions/cpu_asm.S,
new-exceptions/bspsupport/ppc_exc_asm_macros.h,
new-exceptions/bspsupport/ppc_exc_global_handler.c,
new-exceptions/bspsupport/ppc_exc_prologue.c,
new-exceptions/bspsupport/vectors.h: Added support for SPE.
* configure.ac, preinstall.am, Makefile.am: Added support for qoriq
BSPs.
Diffstat (limited to 'c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_async_normal.S')
-rw-r--r-- | c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_async_normal.S | 235 |
1 files changed, 235 insertions, 0 deletions
diff --git a/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_async_normal.S b/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_async_normal.S new file mode 100644 index 0000000000..64295cbb3a --- /dev/null +++ b/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_async_normal.S @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2011 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#include <bspopts.h> +#include <rtems/score/percpu.h> +#include <bsp/vectors.h> + +#define VECTOR_REGISTER r4 +#define ISR_NEST_HADDR_REGISTER r5 +#define ISR_NEST_REGISTER r6 +#define DISPATCH_LEVEL_REGISTER r7 +#define HANDLER_REGISTER r8 +#define SCRATCH_0_REGISTER r0 +#define SCRATCH_1_REGISTER r3 +#define SCRATCH_2_REGISTER r9 +#define SCRATCH_3_REGISTER r10 +#define SCRATCH_4_REGISTER r11 +#define SCRATCH_5_REGISTER r12 +#define FRAME_REGISTER r14 + +#define VECTOR_OFFSET(reg) GPR4_OFFSET(reg) +#define ISR_NEST_HADDR_OFFSET(reg) GPR5_OFFSET(reg) +#define ISR_NEST_OFFSET(reg) GPR6_OFFSET(reg) +#define DISPATCH_LEVEL_OFFSET(reg) GPR7_OFFSET(reg) +#define HANDLER_OFFSET(reg) GPR8_OFFSET(reg) +#define SCRATCH_0_OFFSET(reg) GPR0_OFFSET(reg) +#define SCRATCH_1_OFFSET(reg) GPR3_OFFSET(reg) +#define SCRATCH_2_OFFSET(reg) GPR9_OFFSET(reg) +#define SCRATCH_3_OFFSET(reg) GPR10_OFFSET(reg) +#define SCRATCH_4_OFFSET(reg) GPR11_OFFSET(reg) +#define SCRATCH_5_OFFSET(reg) GPR12_OFFSET(reg) + +/* + * The register 2 slot is free, since this is the read-only small data anchor. + */ +#define FRAME_OFFSET(reg) GPR2_OFFSET(reg) + + .global ppc_exc_min_prolog_async_tmpl_normal + .global ppc_exc_wrap_async_normal + +ppc_exc_min_prolog_async_tmpl_normal: + + stwu r1, -PPC_EXC_MINIMAL_FRAME_SIZE(r1) + stw VECTOR_REGISTER, PPC_EXC_VECTOR_PROLOGUE_OFFSET(r1) + li VECTOR_REGISTER, 0xffff8000 + + /* + * We store the absolute branch target address here. It will be used + * to generate the branch operation in ppc_exc_make_prologue(). + */ + .int ppc_exc_wrap_async_normal + +ppc_exc_wrap_async_normal: + + /* Save non-volatile FRAME_REGISTER */ + stw FRAME_REGISTER, FRAME_OFFSET(r1) + +#ifdef __SPE__ + /* Enable SPE */ + mfmsr FRAME_REGISTER + oris FRAME_REGISTER, FRAME_REGISTER, MSR_SPE >> 16 + mtmsr FRAME_REGISTER +#endif + + /* Move frame pointer to non-volatile FRAME_REGISTER */ + mr FRAME_REGISTER, r1 + + /* Load ISR nest level and thread dispatch disable level */ + PPC_EXC_GPR_STORE ISR_NEST_HADDR_REGISTER, ISR_NEST_HADDR_OFFSET(r1) + lis ISR_NEST_HADDR_REGISTER, ISR_NEST_LEVEL@ha + PPC_EXC_GPR_STORE ISR_NEST_REGISTER, ISR_NEST_OFFSET(r1) + lwz ISR_NEST_REGISTER, ISR_NEST_LEVEL@l(ISR_NEST_HADDR_REGISTER) + PPC_EXC_GPR_STORE DISPATCH_LEVEL_REGISTER, DISPATCH_LEVEL_OFFSET(r1) + lwz DISPATCH_LEVEL_REGISTER, _Thread_Dispatch_disable_level@sdarel(r13) + + PPC_EXC_GPR_STORE SCRATCH_0_REGISTER, SCRATCH_0_OFFSET(r1) + +#ifdef __SPE__ + /* + * Save high order part of VECTOR_REGISTER here. The low order part + * was saved in the minimal prologue. + */ + evmergehi SCRATCH_0_REGISTER, SCRATCH_0_REGISTER, VECTOR_REGISTER + stw SCRATCH_0_REGISTER, VECTOR_OFFSET(r1) +#endif + + PPC_EXC_GPR_STORE HANDLER_REGISTER, HANDLER_OFFSET(r1) + + /* + * Load the handler address. Get the handler table index from the + * vector number. We have to discard the exception type. Take only + * the least significant five bits (= LAST_VALID_EXC + 1) from the + * vector register. Multiply by four (= size of function pointer). + */ + rlwinm SCRATCH_0_REGISTER, VECTOR_REGISTER, 2, 25, 29 + lis HANDLER_REGISTER, ppc_exc_handler_table@h + ori HANDLER_REGISTER, HANDLER_REGISTER, ppc_exc_handler_table@l + lwzx HANDLER_REGISTER, HANDLER_REGISTER, SCRATCH_0_REGISTER + + PPC_EXC_GPR_STORE SCRATCH_1_REGISTER, SCRATCH_1_OFFSET(r1) + PPC_EXC_GPR_STORE SCRATCH_2_REGISTER, SCRATCH_2_OFFSET(r1) + PPC_EXC_GPR_STORE SCRATCH_3_REGISTER, SCRATCH_3_OFFSET(r1) + PPC_EXC_GPR_STORE SCRATCH_4_REGISTER, SCRATCH_4_OFFSET(r1) + PPC_EXC_GPR_STORE SCRATCH_5_REGISTER, SCRATCH_5_OFFSET(r1) + + /* Save SRR0, SRR1, CR, CTR, XER, and LR */ + mfsrr0 SCRATCH_0_REGISTER + mfsrr1 SCRATCH_1_REGISTER + mfcr SCRATCH_2_REGISTER + mfctr SCRATCH_3_REGISTER + mfxer SCRATCH_4_REGISTER + mflr SCRATCH_5_REGISTER + stw SCRATCH_0_REGISTER, SRR0_FRAME_OFFSET(r1) + stw SCRATCH_1_REGISTER, SRR1_FRAME_OFFSET(r1) + stw SCRATCH_2_REGISTER, EXC_CR_OFFSET(r1) + stw SCRATCH_3_REGISTER, EXC_CTR_OFFSET(r1) + stw SCRATCH_4_REGISTER, EXC_XER_OFFSET(r1) + stw SCRATCH_5_REGISTER, EXC_LR_OFFSET(r1) + +#ifdef __SPE__ + /* Save SPEFSCR and ACC */ + mfspr SCRATCH_0_REGISTER, FSL_EIS_SPEFSCR + evxor SCRATCH_1_REGISTER, SCRATCH_1_REGISTER, SCRATCH_1_REGISTER + evmwumiaa SCRATCH_1_REGISTER, SCRATCH_1_REGISTER, SCRATCH_1_REGISTER + stw SCRATCH_0_REGISTER, PPC_EXC_SPEFSCR_OFFSET(r1) + evstdd SCRATCH_1_REGISTER, PPC_EXC_ACC_OFFSET(r1) +#endif + + /* Increment ISR nest level and thread dispatch disable level */ + cmpwi ISR_NEST_REGISTER, 0 + addi ISR_NEST_REGISTER, ISR_NEST_REGISTER, 1 + addi DISPATCH_LEVEL_REGISTER, DISPATCH_LEVEL_REGISTER, 1 + stw ISR_NEST_REGISTER, ISR_NEST_LEVEL@l(ISR_NEST_HADDR_REGISTER) + stw DISPATCH_LEVEL_REGISTER, _Thread_Dispatch_disable_level@sdarel(r13) + + /* Switch stack if necessary */ + mfspr SCRATCH_0_REGISTER, SPRG1 + iselgt r1, r1, SCRATCH_0_REGISTER + + /* + * Call high level exception handler. + * + * First parameter = exception frame pointer + FRAME_LINK_SPACE + * Second parameter = vector number (r4 is the VECTOR_REGISTER) + */ + addi r3, FRAME_REGISTER, FRAME_LINK_SPACE + rlwinm VECTOR_REGISTER, VECTOR_REGISTER, 0, 27, 31 + mtctr HANDLER_REGISTER + bctrl + + /* Load ISR nest level and thread dispatch disable level */ + lis ISR_NEST_HADDR_REGISTER, ISR_NEST_LEVEL@ha + lwz ISR_NEST_REGISTER, ISR_NEST_LEVEL@l(ISR_NEST_HADDR_REGISTER) + lwz DISPATCH_LEVEL_REGISTER, _Thread_Dispatch_disable_level@sdarel(r13) + + /* + * Switch back to original stack (FRAME_REGISTER == r1 if we are still + * on the IRQ stack) and restore FRAME_REGISTER. + */ + mr r1, FRAME_REGISTER + lwz FRAME_REGISTER, FRAME_OFFSET(r1) + + /* Decrement ISR nest level and thread dispatch disable level */ + subi ISR_NEST_REGISTER, ISR_NEST_REGISTER, 1 + subic. DISPATCH_LEVEL_REGISTER, DISPATCH_LEVEL_REGISTER, 1 + stw ISR_NEST_REGISTER, ISR_NEST_LEVEL@l(ISR_NEST_HADDR_REGISTER) + stw DISPATCH_LEVEL_REGISTER, _Thread_Dispatch_disable_level@sdarel(r13) + + /* Call thread dispatcher if necessary */ + bne thread_dispatching_done + bl _Thread_Dispatch +thread_dispatching_done: + +#ifdef __SPE__ + /* Load SPEFSCR and ACC */ + lwz DISPATCH_LEVEL_REGISTER, PPC_EXC_SPEFSCR_OFFSET(r1) + evldd HANDLER_REGISTER, PPC_EXC_ACC_OFFSET(r1) +#endif + + /* Load SRR0, SRR1, CR, CTR, XER, and LR */ + lwz SCRATCH_0_REGISTER, SRR0_FRAME_OFFSET(r1) + lwz SCRATCH_1_REGISTER, SRR1_FRAME_OFFSET(r1) + lwz SCRATCH_2_REGISTER, EXC_CR_OFFSET(r1) + lwz SCRATCH_3_REGISTER, EXC_CTR_OFFSET(r1) + lwz SCRATCH_4_REGISTER, EXC_XER_OFFSET(r1) + lwz SCRATCH_5_REGISTER, EXC_LR_OFFSET(r1) + + PPC_EXC_GPR_LOAD VECTOR_REGISTER, VECTOR_OFFSET(r1) + PPC_EXC_GPR_LOAD ISR_NEST_HADDR_REGISTER, ISR_NEST_HADDR_OFFSET(r1) + PPC_EXC_GPR_LOAD ISR_NEST_REGISTER, ISR_NEST_OFFSET(r1) + +#ifdef __SPE__ + /* Restore SPEFSCR */ + mtspr FSL_EIS_SPEFSCR, DISPATCH_LEVEL_REGISTER +#endif + PPC_EXC_GPR_LOAD DISPATCH_LEVEL_REGISTER, DISPATCH_LEVEL_OFFSET(r1) + +#ifdef __SPE__ + /* Restore ACC */ + evmra HANDLER_REGISTER, HANDLER_REGISTER +#endif + PPC_EXC_GPR_LOAD HANDLER_REGISTER, HANDLER_OFFSET(r1) + + /* Restore SRR0, SRR1, CR, CTR, XER, and LR */ + mtsrr0 SCRATCH_0_REGISTER + PPC_EXC_GPR_LOAD SCRATCH_0_REGISTER, SCRATCH_0_OFFSET(r1) + mtsrr1 SCRATCH_1_REGISTER + PPC_EXC_GPR_LOAD SCRATCH_1_REGISTER, SCRATCH_1_OFFSET(r1) + mtcr SCRATCH_2_REGISTER + PPC_EXC_GPR_LOAD SCRATCH_2_REGISTER, SCRATCH_2_OFFSET(r1) + mtctr SCRATCH_3_REGISTER + PPC_EXC_GPR_LOAD SCRATCH_3_REGISTER, SCRATCH_3_OFFSET(r1) + mtxer SCRATCH_4_REGISTER + PPC_EXC_GPR_LOAD SCRATCH_4_REGISTER, SCRATCH_4_OFFSET(r1) + mtlr SCRATCH_5_REGISTER + PPC_EXC_GPR_LOAD SCRATCH_5_REGISTER, SCRATCH_5_OFFSET(r1) + + /* Pop stack */ + addi r1, r1, PPC_EXC_MINIMAL_FRAME_SIZE + + /* Return */ + rfi |