Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
[cris-mirror.git] / arch / metag / tbx / tbidefr.S
blob8f0902b22f70343791ea4fbbb906a37d09406c19
1 /*
2  * tbidefr.S
3  *
4  * Copyright (C) 2009, 2012 Imagination Technologies.
5  *
6  * This program is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License version 2 as published by the
8  * Free Software Foundation.
9  *
10  * Routing deferred exceptions
11  */
13 #include <asm/metag_regs.h>
14 #include <asm/tbx.h>
16         .text
17         .balign 4
18         .global ___TBIHandleDFR
19         .type   ___TBIHandleDFR,function
20 /* D1Ar1:D0Ar2 -- State
21  * D0Ar3       -- SigNum
22  * D0Ar4       -- Triggers
23  * D1Ar5       -- Inst
24  * D0Ar6       -- pTBI (volatile)
25  */
26 ___TBIHandleDFR:
27 #ifdef META_BUG_MBN100212
28         MSETL   [A0StP++], D0FrT, D0.5
30         /* D1Ar1,D0Ar2,D1Ar5,D0Ar6 -- Arguments to handler, must be preserved
31          * D0Ar4       -- The deferred exceptions
32          * D1Ar3       -- As per D0Ar4 but just the trigger bits
33          * D0.5        -- The bgnd deferred exceptions
34          * D1.5        -- TXDEFR with bgnd re-added
35          */
37         /* - Collect the pending deferred exceptions using TXSTAT,
38          *   (ack's the bgnd exceptions as a side-effect)
39          * - Manually collect remaining (interrupt) deferred exceptions
40          *   using TXDEFR
41          * - Replace the triggers (from TXSTATI) with the int deferred
42          *   exceptions DEFR ..., TXSTATI would have returned if it was valid
43          *   from bgnd code
44          * - Reconstruct TXDEFR by or'ing bgnd deferred exceptions (except
45          *   the DEFER bit) and the int deferred exceptions. This will be
46          *   restored later
47          */
48         DEFR    D0.5,  TXSTAT
49         MOV     D1.5,  TXDEFR
50         ANDT    D0.5,  D0.5, #HI(0xFFFF0000)
51         MOV     D1Ar3, D1.5
52         ANDT    D1Ar3, D1Ar3, #HI(0xFFFF0000)
53         OR      D0Ar4, D1Ar3, #TXSTAT_DEFER_BIT
54         OR      D1.5, D1.5, D0.5
56         /* Mask off anything unrelated to the deferred exception triggers */
57         ANDT    D1Ar3, D1Ar3, #HI(TXSTAT_BUSERR_BIT | TXSTAT_FPE_BITS)
59         /* Can assume that at least one exception happened since this
60          * handler wouldnt have been called otherwise.
61          * 
62          * Replace the signal number and at the same time, prepare
63          * the mask to acknowledge the exception
64          *
65          * D1Re0 -- The bits to acknowledge
66          * D1Ar3 -- The signal number
67          * D1RtP -- Scratch to deal with non-conditional insns
68          */
69         MOVT    D1Re0, #HI(TXSTAT_FPE_BITS & ~TXSTAT_FPE_DENORMAL_BIT)
70         MOV     D1RtP, #TXSTAT_FPE_INVALID_S
71         FFB     D1Ar3, D1Ar3
72         CMP     D1Ar3, #TXSTAT_FPE_INVALID_S
73         MOVLE   D1Ar3, D1RtP /* Collapse FPE triggers to a single signal */
74         MOV     D1RtP, #1
75         LSLGT   D1Re0, D1RtP, D1Ar3
77         /* Get the handler using the signal number
78          *
79          * D1Ar3 -- The signal number
80          * D0Re0 -- Offset into TBI struct containing handler address
81          * D1Re0 -- Mask of triggers to keep
82          * D1RtP -- Address of handler
83          */
84         SUB     D1Ar3, D1Ar3, #(TXSTAT_FPE_INVALID_S - TBID_SIGNUM_FPE)
85         LSL     D0Re0, D1Ar3, #2
86         XOR     D1Re0, D1Re0, #-1   /* Prepare mask for acknowledge (avoids stall) */
87         ADD     D0Re0,D0Re0,#TBI_fnSigs
88         GETD    D1RtP, [D0Ar6+D0Re0]
90         /* Acknowledge triggers */
91         AND     D1.5, D1.5, D1Re0
93         /* Restore remaining exceptions
94          * Do this here in case the handler enables nested interrupts
95          *
96          * D1.5 -- TXDEFR with this exception ack'd
97          */
98         MOV     TXDEFR, D1.5
100         /* Call the handler */
101         SWAP    D1RtP, PC
103         GETL    D0.5,  D1.5,  [--A0StP]
104         GETL    D0FrT, D1RtP, [--A0StP]
105         MOV     PC,D1RtP
106 #else  /* META_BUG_MBN100212 */
108         /* D1Ar1,D0Ar2,D1Ar5,D0Ar6 -- Arguments to handler, must be preserved
109          * D0Ar4       -- The deferred exceptions
110          * D1Ar3       -- As per D0Ar4 but just the trigger bits
111          */
113         /* - Collect the pending deferred exceptions using TXSTAT,
114          *   (ack's the interrupt exceptions as a side-effect)
115          */
116         DEFR    D0Ar4, TXSTATI
118         /* Mask off anything unrelated to the deferred exception triggers */
119         MOV     D1Ar3, D0Ar4
120         ANDT    D1Ar3, D1Ar3, #HI(TXSTAT_BUSERR_BIT | TXSTAT_FPE_BITS)
122         /* Can assume that at least one exception happened since this
123          * handler wouldnt have been called otherwise.
124          * 
125          * Replace the signal number and at the same time, prepare
126          * the mask to acknowledge the exception
127          *
128          * The unusual code for 1<<D1Ar3 may need explanation.
129          * Normally this would be done using 'MOV rs,#1' and 'LSL rd,rs,D1Ar3'
130          * but only D1Re0 is available in D1 and no crossunit insns are available
131          * Even worse, there is no conditional 'MOV r,#uimm8'.
132          * Since the CMP proves that D1Ar3 >= 20, we can reuse the bottom 12-bits
133          * of D1Re0 (using 'ORGT r,#1') in the knowledge that the top 20-bits will
134          * be discarded without affecting the result.
135          *
136          * D1Re0 -- The bits to acknowledge
137          * D1Ar3 -- The signal number
138          */
139         MOVT    D1Re0, #HI(TXSTAT_FPE_BITS & ~TXSTAT_FPE_DENORMAL_BIT)
140         MOV     D0Re0, #TXSTAT_FPE_INVALID_S
141         FFB     D1Ar3, D1Ar3
142         CMP     D1Ar3, #TXSTAT_FPE_INVALID_S
143         MOVLE   D1Ar3, D0Re0 /* Collapse FPE triggers to a single signal */
144         ORGT    D1Re0, D1Re0, #1
145         LSLGT   D1Re0, D1Re0, D1Ar3
147         SUB     D1Ar3, D1Ar3, #(TXSTAT_FPE_INVALID_S - TBID_SIGNUM_FPE)
149         /* Acknowledge triggers and restore remaining exceptions
150          * Do this here in case the handler enables nested interrupts
151          *
152          * (x | y) ^ y == x & ~y. It avoids the restrictive XOR ...,#-1 insn
153          * and is the same length
154          */
155         MOV     D0Re0, TXDEFR
156         OR      D0Re0, D0Re0, D1Re0
157         XOR     TXDEFR, D0Re0, D1Re0
159         /* Get the handler using the signal number
160          *
161          * D1Ar3 -- The signal number
162          * D0Re0 -- Address of handler
163          */
164         LSL     D0Re0, D1Ar3, #2
165         ADD     D0Re0,D0Re0,#TBI_fnSigs
166         GETD    D0Re0, [D0Ar6+D0Re0]
168         /* Tailcall the handler */
169         MOV     PC,D0Re0
171 #endif /* META_BUG_MBN100212 */
172         .size   ___TBIHandleDFR,.-___TBIHandleDFR
174  * End of tbidefr.S
175  */