aboutsummaryrefslogtreecommitdiff
path: root/arch/metag/tbx/tbidefr.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/metag/tbx/tbidefr.S')
-rw-r--r--arch/metag/tbx/tbidefr.S175
1 files changed, 175 insertions, 0 deletions
diff --git a/arch/metag/tbx/tbidefr.S b/arch/metag/tbx/tbidefr.S
new file mode 100644
index 00000000000..3eb165ebf54
--- /dev/null
+++ b/arch/metag/tbx/tbidefr.S
@@ -0,0 +1,175 @@
+/*
+ * 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 -- InstOrSWSId
+ * 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
+ */