176 lines
5.2 KiB
ArmAsm
176 lines
5.2 KiB
ArmAsm
/*
|
|
* 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
|
|
*/
|