123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- /*
- * tbidefr.S
- *
- * Copyright (C) 2009, 2012 Imagination Technologies.
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- *
- * Routing deferred exceptions
- */
- #include <asm/metag_regs.h>
- #include <asm/tbx.h>
- .text
- .balign 4
- .global ___TBIHandleDFR
- .type ___TBIHandleDFR,function
- /* D1Ar1:D0Ar2 -- State
- * D0Ar3 -- SigNum
- * D0Ar4 -- Triggers
- * D1Ar5 -- Inst
- * D0Ar6 -- pTBI (volatile)
- */
- ___TBIHandleDFR:
- #ifdef META_BUG_MBN100212
- MSETL [A0StP++], D0FrT, D0.5
- /* D1Ar1,D0Ar2,D1Ar5,D0Ar6 -- Arguments to handler, must be preserved
- * D0Ar4 -- The deferred exceptions
- * D1Ar3 -- As per D0Ar4 but just the trigger bits
- * D0.5 -- The bgnd deferred exceptions
- * D1.5 -- TXDEFR with bgnd re-added
- */
- /* - Collect the pending deferred exceptions using TXSTAT,
- * (ack's the bgnd exceptions as a side-effect)
- * - Manually collect remaining (interrupt) deferred exceptions
- * using TXDEFR
- * - Replace the triggers (from TXSTATI) with the int deferred
- * exceptions DEFR ..., TXSTATI would have returned if it was valid
- * from bgnd code
- * - Reconstruct TXDEFR by or'ing bgnd deferred exceptions (except
- * the DEFER bit) and the int deferred exceptions. This will be
- * restored later
- */
- DEFR D0.5, TXSTAT
- MOV D1.5, TXDEFR
- ANDT D0.5, D0.5, #HI(0xFFFF0000)
- MOV D1Ar3, D1.5
- ANDT D1Ar3, D1Ar3, #HI(0xFFFF0000)
- OR D0Ar4, D1Ar3, #TXSTAT_DEFER_BIT
- OR D1.5, D1.5, D0.5
- /* Mask off anything unrelated to the deferred exception triggers */
- ANDT D1Ar3, D1Ar3, #HI(TXSTAT_BUSERR_BIT | TXSTAT_FPE_BITS)
- /* Can assume that at least one exception happened since this
- * handler wouldnt have been called otherwise.
- *
- * Replace the signal number and at the same time, prepare
- * the mask to acknowledge the exception
- *
- * D1Re0 -- The bits to acknowledge
- * D1Ar3 -- The signal number
- * D1RtP -- Scratch to deal with non-conditional insns
- */
- MOVT D1Re0, #HI(TXSTAT_FPE_BITS & ~TXSTAT_FPE_DENORMAL_BIT)
- MOV D1RtP, #TXSTAT_FPE_INVALID_S
- FFB D1Ar3, D1Ar3
- CMP D1Ar3, #TXSTAT_FPE_INVALID_S
- MOVLE D1Ar3, D1RtP /* Collapse FPE triggers to a single signal */
- MOV D1RtP, #1
- LSLGT D1Re0, D1RtP, D1Ar3
- /* Get the handler using the signal number
- *
- * D1Ar3 -- The signal number
- * D0Re0 -- Offset into TBI struct containing handler address
- * D1Re0 -- Mask of triggers to keep
- * D1RtP -- Address of handler
- */
- SUB D1Ar3, D1Ar3, #(TXSTAT_FPE_INVALID_S - TBID_SIGNUM_FPE)
- LSL D0Re0, D1Ar3, #2
- XOR D1Re0, D1Re0, #-1 /* Prepare mask for acknowledge (avoids stall) */
- ADD D0Re0,D0Re0,#TBI_fnSigs
- GETD D1RtP, [D0Ar6+D0Re0]
- /* Acknowledge triggers */
- AND D1.5, D1.5, D1Re0
- /* Restore remaining exceptions
- * Do this here in case the handler enables nested interrupts
- *
- * D1.5 -- TXDEFR with this exception ack'd
- */
- MOV TXDEFR, D1.5
- /* Call the handler */
- SWAP D1RtP, PC
- GETL D0.5, D1.5, [--A0StP]
- GETL D0FrT, D1RtP, [--A0StP]
- MOV PC,D1RtP
- #else /* META_BUG_MBN100212 */
- /* D1Ar1,D0Ar2,D1Ar5,D0Ar6 -- Arguments to handler, must be preserved
- * D0Ar4 -- The deferred exceptions
- * D1Ar3 -- As per D0Ar4 but just the trigger bits
- */
- /* - Collect the pending deferred exceptions using TXSTAT,
- * (ack's the interrupt exceptions as a side-effect)
- */
- DEFR D0Ar4, TXSTATI
- /* Mask off anything unrelated to the deferred exception triggers */
- MOV D1Ar3, D0Ar4
- ANDT D1Ar3, D1Ar3, #HI(TXSTAT_BUSERR_BIT | TXSTAT_FPE_BITS)
- /* Can assume that at least one exception happened since this
- * handler wouldnt have been called otherwise.
- *
- * Replace the signal number and at the same time, prepare
- * the mask to acknowledge the exception
- *
- * The unusual code for 1<<D1Ar3 may need explanation.
- * Normally this would be done using 'MOV rs,#1' and 'LSL rd,rs,D1Ar3'
- * but only D1Re0 is available in D1 and no crossunit insns are available
- * Even worse, there is no conditional 'MOV r,#uimm8'.
- * Since the CMP proves that D1Ar3 >= 20, we can reuse the bottom 12-bits
- * of D1Re0 (using 'ORGT r,#1') in the knowledge that the top 20-bits will
- * be discarded without affecting the result.
- *
- * D1Re0 -- The bits to acknowledge
- * D1Ar3 -- The signal number
- */
- MOVT D1Re0, #HI(TXSTAT_FPE_BITS & ~TXSTAT_FPE_DENORMAL_BIT)
- MOV D0Re0, #TXSTAT_FPE_INVALID_S
- FFB D1Ar3, D1Ar3
- CMP D1Ar3, #TXSTAT_FPE_INVALID_S
- MOVLE D1Ar3, D0Re0 /* Collapse FPE triggers to a single signal */
- ORGT D1Re0, D1Re0, #1
- LSLGT D1Re0, D1Re0, D1Ar3
- SUB D1Ar3, D1Ar3, #(TXSTAT_FPE_INVALID_S - TBID_SIGNUM_FPE)
- /* Acknowledge triggers and restore remaining exceptions
- * Do this here in case the handler enables nested interrupts
- *
- * (x | y) ^ y == x & ~y. It avoids the restrictive XOR ...,#-1 insn
- * and is the same length
- */
- MOV D0Re0, TXDEFR
- OR D0Re0, D0Re0, D1Re0
- XOR TXDEFR, D0Re0, D1Re0
- /* Get the handler using the signal number
- *
- * D1Ar3 -- The signal number
- * D0Re0 -- Address of handler
- */
- LSL D0Re0, D1Ar3, #2
- ADD D0Re0,D0Re0,#TBI_fnSigs
- GETD D0Re0, [D0Ar6+D0Re0]
- /* Tailcall the handler */
- MOV PC,D0Re0
- #endif /* META_BUG_MBN100212 */
- .size ___TBIHandleDFR,.-___TBIHandleDFR
- /*
- * End of tbidefr.S
- */
|