/* Copyright (C) 2003 Analog Devices, Inc. All Rights Reserved. * * This file is subject to the terms and conditions of the GNU General Public * License. * * Blackfin BF533/2.6 support : LG Soft India */ /* Include an exception handler to invoke the CPLB manager */ #include #include #include .text .globl _cplb_hdr; .type _cplb_hdr, STT_FUNC; .extern _cplb_mgr; .type _cplb_mgr, STT_FUNC; .extern __unknown_exception_occurred; .type __unknown_exception_occurred, STT_FUNC; .extern __cplb_miss_all_locked; .type __cplb_miss_all_locked, STT_FUNC; .extern __cplb_miss_without_replacement; .type __cplb_miss_without_replacement, STT_FUNC; .extern __cplb_protection_violation; .type __cplb_protection_violation, STT_FUNC; .extern panic_pv; .align 2; ENTRY(_cplb_hdr) SSYNC; [--SP] = ( R7:0, P5:0 ); [--SP] = ASTAT; [--SP] = SEQSTAT; [--SP] = I0; [--SP] = I1; [--SP] = I2; [--SP] = I3; [--SP] = LT0; [--SP] = LB0; [--SP] = LC0; [--SP] = LT1; [--SP] = LB1; [--SP] = LC1; R2 = SEQSTAT; /*Mask the contents of SEQSTAT and leave only EXCAUSE in R2*/ R2 <<= 26; R2 >>= 26; R1 = 0x23; /* Data access CPLB protection violation */ CC = R2 == R1; IF !CC JUMP not_data_write; R0 = 2; /* is a write to data space*/ JUMP is_icplb_miss; not_data_write: R1 = 0x2C; /* CPLB miss on an instruction fetch */ CC = R2 == R1; R0 = 0; /* is_data_miss == False*/ IF CC JUMP is_icplb_miss; R1 = 0x26; CC = R2 == R1; IF !CC JUMP unknown; R0 = 1; /* is_data_miss == True*/ is_icplb_miss: #if ( defined (CONFIG_BLKFIN_CACHE) || defined (CONFIG_BLKFIN_DCACHE)) #if ( defined (CONFIG_BLKFIN_CACHE) && !defined (CONFIG_BLKFIN_DCACHE)) R1 = CPLB_ENABLE_ICACHE; #endif #if ( !defined (CONFIG_BLKFIN_CACHE) && defined (CONFIG_BLKFIN_DCACHE)) R1 = CPLB_ENABLE_DCACHE; #endif #if ( defined (CONFIG_BLKFIN_CACHE) && defined (CONFIG_BLKFIN_DCACHE)) R1 = CPLB_ENABLE_DCACHE | CPLB_ENABLE_ICACHE; #endif #else R1 = 0; #endif [--SP] = RETS; CALL _cplb_mgr; RETS = [SP++]; CC = R0 == 0; IF !CC JUMP not_replaced; LC1 = [SP++]; LB1 = [SP++]; LT1 = [SP++]; LC0 = [SP++]; LB0 = [SP++]; LT0 = [SP++]; I3 = [SP++]; I2 = [SP++]; I1 = [SP++]; I0 = [SP++]; SEQSTAT = [SP++]; ASTAT = [SP++]; ( R7:0, P5:0 ) = [SP++]; RTS; unknown: [--SP] = RETS; CALL __unknown_exception_occurred; RETS = [SP++]; JUMP unknown; not_replaced: CC = R0 == CPLB_NO_UNLOCKED; IF !CC JUMP next_check; [--SP] = RETS; CALL __cplb_miss_all_locked; RETS = [SP++]; next_check: CC = R0 == CPLB_NO_ADDR_MATCH; IF !CC JUMP next_check2; [--SP] = RETS; CALL __cplb_miss_without_replacement; RETS = [SP++]; JUMP not_replaced; next_check2: CC = R0 == CPLB_PROT_VIOL; IF !CC JUMP strange_return_from_cplb_mgr; [--SP] = RETS; CALL __cplb_protection_violation; RETS = [SP++]; JUMP not_replaced; strange_return_from_cplb_mgr: IDLE; CSYNC; JUMP strange_return_from_cplb_mgr; /************************************ * Diagnostic exception handlers */ __cplb_miss_all_locked: sp += -12; R0 = CPLB_NO_UNLOCKED; call panic_bfin; SP += 12; RTS; __cplb_miss_without_replacement: sp += -12; R0 = CPLB_NO_ADDR_MATCH; call panic_bfin; SP += 12; RTS; __cplb_protection_violation: sp += -12; R0 = CPLB_PROT_VIOL; call panic_bfin; SP += 12; RTS; __unknown_exception_occurred: /* This function is invoked by the default exception * handler, if it does not recognise the kind of * exception that has occurred. In other words, the * default handler only handles some of the system's * exception types, and it does not expect any others * to occur. If your application is going to be using * other kinds of exceptions, you must replace the * default handler with your own, that handles all the * exceptions you will use. * * Since there's nothing we can do, we just loop here * at what we hope is a suitably informative label. */ IDLE; do_not_know_what_to_do: CSYNC; JUMP __unknown_exception_occurred; RTS; .__unknown_exception_occurred.end: .global __unknown_exception_occurred; .type __unknown_exception_occurred, STT_FUNC; panic_bfin: RTS;