diff options
author | James Hogan <james.hogan@imgtec.com> | 2012-09-21 12:40:06 -0400 |
---|---|---|
committer | James Hogan <james.hogan@imgtec.com> | 2013-03-02 15:09:18 -0500 |
commit | 027f891f7640144d4b7b15113f3ae9af2c8b095d (patch) | |
tree | cee318450f4782ca3a471f83ef3fd3557e8c3a9d /arch | |
parent | 4ca151b20803eb2e31bb6d840d01eec461158e14 (diff) |
metag: TBX source
Add source files from the Thread Binary Interface (TBI) library which
provides useful low level operations and traps/context management.
Among other things it handles interrupt/exception/syscall entry (in
tbipcx.S).
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/metag/tbx/tbicore.S | 136 | ||||
-rw-r--r-- | arch/metag/tbx/tbictx.S | 366 | ||||
-rw-r--r-- | arch/metag/tbx/tbictxfpu.S | 190 | ||||
-rw-r--r-- | arch/metag/tbx/tbidefr.S | 175 | ||||
-rw-r--r-- | arch/metag/tbx/tbidspram.S | 161 | ||||
-rw-r--r-- | arch/metag/tbx/tbilogf.S | 48 | ||||
-rw-r--r-- | arch/metag/tbx/tbipcx.S | 451 | ||||
-rw-r--r-- | arch/metag/tbx/tbiroot.S | 87 | ||||
-rw-r--r-- | arch/metag/tbx/tbisoft.S | 237 | ||||
-rw-r--r-- | arch/metag/tbx/tbistring.c | 114 | ||||
-rw-r--r-- | arch/metag/tbx/tbitimer.S | 207 |
11 files changed, 2172 insertions, 0 deletions
diff --git a/arch/metag/tbx/tbicore.S b/arch/metag/tbx/tbicore.S new file mode 100644 index 000000000000..a0838ebcb433 --- /dev/null +++ b/arch/metag/tbx/tbicore.S | |||
@@ -0,0 +1,136 @@ | |||
1 | /* | ||
2 | * tbicore.S | ||
3 | * | ||
4 | * Copyright (C) 2001, 2002, 2007, 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 | * Core functions needed to support use of the thread binary interface for META | ||
11 | * processors | ||
12 | */ | ||
13 | |||
14 | .file "tbicore.S" | ||
15 | /* Get data structures and defines from the TBI C header */ | ||
16 | #include <asm/metag_mem.h> | ||
17 | #include <asm/metag_regs.h> | ||
18 | #include <asm/tbx.h> | ||
19 | |||
20 | .data | ||
21 | .balign 8 | ||
22 | .global ___pTBISegs | ||
23 | .type ___pTBISegs,object | ||
24 | ___pTBISegs: | ||
25 | .quad 0 /* Segment list pointer with it's */ | ||
26 | .size ___pTBISegs,.-___pTBISegs | ||
27 | /* own id or spin-lock location */ | ||
28 | /* | ||
29 | * Return ___pTBISegs value specific to privilege level - not very complicated | ||
30 | * at the moment | ||
31 | * | ||
32 | * Register Usage: D0Re0 is the result, D1Re0 is used as a scratch | ||
33 | */ | ||
34 | .text | ||
35 | .balign 4 | ||
36 | .global ___TBISegList | ||
37 | .type ___TBISegList,function | ||
38 | ___TBISegList: | ||
39 | MOVT A1LbP,#HI(___pTBISegs) | ||
40 | ADD A1LbP,A1LbP,#LO(___pTBISegs) | ||
41 | GETL D0Re0,D1Re0,[A1LbP] | ||
42 | MOV PC,D1RtP | ||
43 | .size ___TBISegList,.-___TBISegList | ||
44 | |||
45 | /* | ||
46 | * Search the segment list for a match given Id, pStart can be NULL | ||
47 | * | ||
48 | * Register Usage: D1Ar1 is pSeg, D0Ar2 is Id, D0Re0 is the result | ||
49 | * D0Ar4, D1Ar3 are used as a scratch | ||
50 | * NB: The PSTAT bit if Id in D0Ar2 may be toggled | ||
51 | */ | ||
52 | .text | ||
53 | .balign 4 | ||
54 | .global ___TBIFindSeg | ||
55 | .type ___TBIFindSeg,function | ||
56 | ___TBIFindSeg: | ||
57 | MOVT A1LbP,#HI(___pTBISegs) | ||
58 | ADD A1LbP,A1LbP,#LO(___pTBISegs) | ||
59 | GETL D1Ar3,D0Ar4,[A1LbP] /* Read segment list head */ | ||
60 | MOV D0Re0,TXSTATUS /* What priv level are we at? */ | ||
61 | CMP D1Ar1,#0 /* Is pStart provided? */ | ||
62 | /* Disable privilege adaption for now */ | ||
63 | ANDT D0Re0,D0Re0,#0 /*HI(TXSTATUS_PSTAT_BIT) ; Is PSTAT set? Zero if not */ | ||
64 | LSL D0Re0,D0Re0,#(TBID_PSTAT_S-TXSTATUS_PSTAT_S) | ||
65 | XOR D0Ar2,D0Ar2,D0Re0 /* Toggle Id PSTAT if privileged */ | ||
66 | MOVNZ D1Ar3,D1Ar1 /* Use pStart if provided */ | ||
67 | $LFindSegLoop: | ||
68 | ADDS D0Re0,D1Ar3,#0 /* End of list? Load result into D0Re0 */ | ||
69 | MOVZ PC,D1RtP /* If result is NULL we leave */ | ||
70 | GETL D1Ar3,D0Ar4,[D1Ar3] /* Read pLink and Id */ | ||
71 | CMP D0Ar4,D0Ar2 /* Does it match? */ | ||
72 | BNZ $LFindSegLoop /* Loop if there is no match */ | ||
73 | TST D0Re0,D0Re0 /* Clear zero flag - we found it! */ | ||
74 | MOV PC,D1RtP /* Return */ | ||
75 | .size ___TBIFindSeg,.-___TBIFindSeg | ||
76 | |||
77 | /* Useful offsets to encode the lower bits of the lock/unlock addresses */ | ||
78 | #define UON (LINSYSEVENT_WR_ATOMIC_LOCK & 0xFFF8) | ||
79 | #define UOFF (LINSYSEVENT_WR_ATOMIC_UNLOCK & 0xFFF8) | ||
80 | |||
81 | /* | ||
82 | * Perform a whole spin-lock sequence as used by the TBISignal routine | ||
83 | * | ||
84 | * Register Usage: D1Ar1 is pLock, D0Ar2 is Mask, D0Re0 is the result | ||
85 | * (All other usage due to ___TBIPoll - D0Ar6, D1Re0) | ||
86 | */ | ||
87 | .text | ||
88 | .balign 4 | ||
89 | .global ___TBISpin | ||
90 | .type ___TBISpin,function | ||
91 | ___TBISpin: | ||
92 | SETL [A0StP++],D0FrT,D1RtP /* Save our return address */ | ||
93 | ORS D0Re0,D0Re0,#1 /* Clear zero flag */ | ||
94 | MOV D1RtP,PC /* Setup return address to form loop */ | ||
95 | $LSpinLoop: | ||
96 | BNZ ___TBIPoll /* Keep repeating if fail to set */ | ||
97 | GETL D0FrT,D1RtP,[--A0StP] /* Restore return address */ | ||
98 | MOV PC,D1RtP /* Return */ | ||
99 | .size ___TBISpin,.-___TBISpin | ||
100 | |||
101 | /* | ||
102 | * Perform an attempt to gain access to a spin-lock and set some bits | ||
103 | * | ||
104 | * Register Usage: D1Ar1 is pLock, D0Ar2 is Mask, D0Re0 is the result | ||
105 | * !!On return Zero flag is SET if we are sucessfull!! | ||
106 | * A0.3 is used to hold base address of system event region | ||
107 | * D1Re0 use to hold TXMASKI while interrupts are off | ||
108 | */ | ||
109 | .text | ||
110 | .balign 4 | ||
111 | .global ___TBIPoll | ||
112 | .type ___TBIPoll,function | ||
113 | ___TBIPoll: | ||
114 | MOV D1Re0,#0 /* Prepare to disable ints */ | ||
115 | MOVT A0.3,#HI(LINSYSEVENT_WR_ATOMIC_LOCK) | ||
116 | SWAP D1Re0,TXMASKI /* Really stop ints */ | ||
117 | LOCK2 /* Gain all locks */ | ||
118 | SET [A0.3+#UON],D1RtP /* Stop shared memory access too */ | ||
119 | DCACHE [D1Ar1],A0.3 /* Flush Cache line */ | ||
120 | GETD D0Re0,[D1Ar1] /* Get new state from memory or hit */ | ||
121 | DCACHE [D1Ar1],A0.3 /* Flush Cache line */ | ||
122 | GETD D0Re0,[D1Ar1] /* Get current state */ | ||
123 | TST D0Re0,D0Ar2 /* Are we clear to send? */ | ||
124 | ORZ D0Re0,D0Re0,D0Ar2 /* Yes: So set bits and */ | ||
125 | SETDZ [D1Ar1],D0Re0 /* transmit new state */ | ||
126 | SET [A0.3+#UOFF],D1RtP /* Allow shared memory access */ | ||
127 | LOCK0 /* Release all locks */ | ||
128 | MOV TXMASKI,D1Re0 /* Allow ints */ | ||
129 | $LPollEnd: | ||
130 | XORNZ D0Re0,D0Re0,D0Re0 /* No: Generate zero result */ | ||
131 | MOV PC,D1RtP /* Return (NZ indicates failure) */ | ||
132 | .size ___TBIPoll,.-___TBIPoll | ||
133 | |||
134 | /* | ||
135 | * End of tbicore.S | ||
136 | */ | ||
diff --git a/arch/metag/tbx/tbictx.S b/arch/metag/tbx/tbictx.S new file mode 100644 index 000000000000..19af983a13ae --- /dev/null +++ b/arch/metag/tbx/tbictx.S | |||
@@ -0,0 +1,366 @@ | |||
1 | /* | ||
2 | * tbictx.S | ||
3 | * | ||
4 | * Copyright (C) 2001, 2002, 2007, 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 | * Explicit state save and restore routines forming part of the thread binary | ||
11 | * interface for META processors | ||
12 | */ | ||
13 | |||
14 | .file "tbictx.S" | ||
15 | #include <asm/metag_regs.h> | ||
16 | #include <asm/tbx.h> | ||
17 | |||
18 | #ifdef METAC_1_0 | ||
19 | /* Ax.4 is NOT saved in XAX3 */ | ||
20 | #define A0_4 | ||
21 | #else | ||
22 | /* Ax.4 is saved in XAX4 */ | ||
23 | #define A0_4 A0.4, | ||
24 | #endif | ||
25 | |||
26 | |||
27 | /* Size of the TBICTX structure */ | ||
28 | #define TBICTX_BYTES ((TBICTX_AX_REGS*8)+TBICTX_AX) | ||
29 | |||
30 | /* | ||
31 | * TBIRES __TBINestInts( TBIRES State, void *pExt, int NoNestMask ) | ||
32 | */ | ||
33 | .text | ||
34 | .balign 4 | ||
35 | .global ___TBINestInts | ||
36 | .type ___TBINestInts,function | ||
37 | ___TBINestInts: | ||
38 | XOR D0Ar4,D0Ar4,#-1 /* D0Ar4 = ~TrigBit */ | ||
39 | AND D0Ar4,D0Ar4,#0xFFFF /* D0Ar4 &= 0xFFFF */ | ||
40 | MOV D0Ar6,TXMASKI /* BGNDHALT currently enabled? */ | ||
41 | TSTT D0Ar2,#TBICTX_XDX8_BIT+TBICTX_XAXX_BIT+TBICTX_XHL2_BIT+TBICTX_XTDP_BIT+TBICTX_XCBF_BIT | ||
42 | AND D0Ar4,D0Ar2,D0Ar4 /* D0Ar4 = Ints to allow */ | ||
43 | XOR D0Ar2,D0Ar2,D0Ar4 /* Less Ints in TrigMask */ | ||
44 | BNZ ___TBINestInts2 /* Jump if ctx save required! */ | ||
45 | TSTT D0Ar2,#TBICTX_CBUF_BIT+TBICTX_CBRP_BIT /* Is catch state dirty? */ | ||
46 | OR D0Ar4,D0Ar4,D0Ar6 /* Or in TXMASKI BGNDHALT if set */ | ||
47 | TSTNZ D0Ar4,D0Ar4 /* Yes: AND triggers enabled */ | ||
48 | MOV D0Re0,D0Ar2 /* Update State argument */ | ||
49 | MOV D1Re0,D1Ar1 /* with less Ints in TrigMask */ | ||
50 | MOVZ TXMASKI,D0Ar4 /* Early return: Enable Ints */ | ||
51 | MOVZ PC,D1RtP /* Early return */ | ||
52 | .size ___TBINestInts,.-___TBINestInts | ||
53 | /* | ||
54 | * Drop thru into sub-function- | ||
55 | */ | ||
56 | .global ___TBINestInts2 | ||
57 | .type ___TBINestInts2,function | ||
58 | ___TBINestInts2: | ||
59 | MOV D0FrT,A0FrP /* Full entry sequence so we */ | ||
60 | ADD A0FrP,A0StP,#0 /* can make sub-calls */ | ||
61 | MSETL [A0StP],D0FrT,D0.5,D0.6 /* and preserve our result */ | ||
62 | ORT D0Ar2,D0Ar2,#TBICTX_XCBF_BIT /* Add in XCBF save request */ | ||
63 | MOV D0.5,D0Ar2 /* Save State in DX.5 */ | ||
64 | MOV D1.5,D1Ar1 | ||
65 | OR D0.6,D0Ar4,D0Ar6 /* Save TrigMask in D0.6 */ | ||
66 | MOVT D1RtP,#HI(___TBICtxSave) /* Save catch buffer */ | ||
67 | CALL D1RtP,#LO(___TBICtxSave) | ||
68 | MOV TXMASKI,D0.6 /* Allow Ints */ | ||
69 | MOV D0Re0,D0.5 /* Return State */ | ||
70 | MOV D1Re0,D1.5 | ||
71 | MGETL D0FrT,D0.5,D0.6,[A0FrP] /* Full exit sequence */ | ||
72 | SUB A0StP,A0FrP,#(8*3) | ||
73 | MOV A0FrP,D0FrT | ||
74 | MOV PC,D1RtP | ||
75 | .size ___TBINestInts2,.-___TBINestInts2 | ||
76 | |||
77 | /* | ||
78 | * void *__TBICtxSave( TBIRES State, void *pExt ) | ||
79 | * | ||
80 | * D0Ar2 contains TBICTX_*_BIT values that control what | ||
81 | * extended data is to be saved beyond the end of D1Ar1. | ||
82 | * These bits must be ored into the SaveMask of this structure. | ||
83 | * | ||
84 | * Virtually all possible scratch registers are used. | ||
85 | * | ||
86 | * The D1Ar1 parameter is only used as the basis for saving | ||
87 | * CBUF state. | ||
88 | */ | ||
89 | /* | ||
90 | * If TBICTX_XEXT_BIT is specified in State. then State.pCtx->Ext is | ||
91 | * utilised to save the base address of the context save area and | ||
92 | * the extended states saved. The XEXT flag then indicates that the | ||
93 | * original state of the A0.2 and A1.2 registers from TBICTX.Ext.AX2 | ||
94 | * are stored as the first part of the extended state structure. | ||
95 | */ | ||
96 | .balign 4 | ||
97 | .global ___TBICtxSave | ||
98 | .type ___TBICtxSave,function | ||
99 | ___TBICtxSave: | ||
100 | GETD D0Re0,[D1Ar1+#TBICTX_SaveMask-2] /* Get SaveMask */ | ||
101 | TSTT D0Ar2,#TBICTX_XDX8_BIT+TBICTX_XAXX_BIT+TBICTX_XHL2_BIT+TBICTX_XTDP_BIT+TBICTX_XEXT_BIT | ||
102 | /* Just XCBF to save? */ | ||
103 | MOV A0.2,D1Ar3 /* Save pointer into A0.2 */ | ||
104 | MOV A1.2,D1RtP /* Free off D0FrT:D1RtP pair */ | ||
105 | BZ $LCtxSaveCBUF /* Yes: Only XCBF may be saved */ | ||
106 | TSTT D0Ar2,#TBICTX_XEXT_BIT /* Extended base-state model? */ | ||
107 | BZ $LCtxSaveXDX8 | ||
108 | GETL D0Ar6,D1Ar5,[D1Ar1+#TBICTX_Ext_AX2] /* Get A0.2, A1.2 state */ | ||
109 | MOV D0Ar4,D0Ar2 /* Extract Ctx.SaveFlags value */ | ||
110 | ANDMT D0Ar4,D0Ar4,#TBICTX_XDX8_BIT+TBICTX_XAXX_BIT+TBICTX_XHL2_BIT+TBICTX_XTDP_BIT+TBICTX_XEXT_BIT | ||
111 | SETD [D1Ar1+#TBICTX_Ext_Ctx_pExt],A0.2 | ||
112 | SETD [D1Ar1+#TBICTX_Ext_Ctx_SaveMask-2],D0Ar4 | ||
113 | SETL [A0.2++],D0Ar6,D1Ar5 /* Save A0.2, A1.2 state */ | ||
114 | $LCtxSaveXDX8: | ||
115 | TSTT D0Ar2,#TBICTX_XDX8_BIT /* Save extended DX regs? */ | ||
116 | BZ $LCtxSaveXAXX | ||
117 | /* | ||
118 | * Save 8 extra DX registers | ||
119 | */ | ||
120 | MSETL [A0.2],D0.8,D0.9,D0.10,D0.11,D0.12,D0.13,D0.14,D0.15 | ||
121 | $LCtxSaveXAXX: | ||
122 | TSTT D0Ar2,#TBICTX_XAXX_BIT /* Save extended AX regs? */ | ||
123 | SWAP D0Re0,A0.2 /* pDst into D0Re0 */ | ||
124 | BZ $LCtxSaveXHL2 | ||
125 | /* | ||
126 | * Save 4 extra AX registers | ||
127 | */ | ||
128 | MSETL [D0Re0], A0_4 A0.5,A0.6,A0.7 /* Save 8*3 bytes */ | ||
129 | $LCtxSaveXHL2: | ||
130 | TSTT D0Ar2,#TBICTX_XHL2_BIT /* Save hardware-loop regs? */ | ||
131 | SWAP D0Re0,A0.2 /* pDst back into A0.2 */ | ||
132 | MOV D0Ar6,TXL1START | ||
133 | MOV D1Ar5,TXL2START | ||
134 | BZ $LCtxSaveXTDP | ||
135 | /* | ||
136 | * Save hardware loop registers | ||
137 | */ | ||
138 | SETL [A0.2++],D0Ar6,D1Ar5 /* Save 8*1 bytes */ | ||
139 | MOV D0Ar6,TXL1END | ||
140 | MOV D1Ar5,TXL2END | ||
141 | MOV D0FrT,TXL1COUNT | ||
142 | MOV D1RtP,TXL2COUNT | ||
143 | MSETL [A0.2],D0Ar6,D0FrT /* Save 8*2 bytes */ | ||
144 | /* | ||
145 | * Clear loop counters to disable any current loops | ||
146 | */ | ||
147 | XOR TXL1COUNT,D0FrT,D0FrT | ||
148 | XOR TXL2COUNT,D1RtP,D1RtP | ||
149 | $LCtxSaveXTDP: | ||
150 | TSTT D0Ar2,#TBICTX_XTDP_BIT /* Save per-thread DSP regs? */ | ||
151 | BZ $LCtxSaveCBUF | ||
152 | /* | ||
153 | * Save per-thread DSP registers; ACC.0, PR.0, PI.1-3 (PI.0 is zero) | ||
154 | */ | ||
155 | #ifndef CTX_NO_DSP | ||
156 | D SETL [A0.2++],AC0.0,AC1.0 /* Save ACx.0 lower 32-bits */ | ||
157 | DH SETL [A0.2++],AC0.0,AC1.0 /* Save ACx.0 upper 32-bits */ | ||
158 | D SETL [A0.2++],D0AR.0,D1AR.0 /* Save DSP RAM registers */ | ||
159 | D SETL [A0.2++],D0AR.1,D1AR.1 | ||
160 | D SETL [A0.2++],D0AW.0,D1AW.0 | ||
161 | D SETL [A0.2++],D0AW.1,D1AW.1 | ||
162 | D SETL [A0.2++],D0BR.0,D1BR.0 | ||
163 | D SETL [A0.2++],D0BR.1,D1BR.1 | ||
164 | D SETL [A0.2++],D0BW.0,D1BW.0 | ||
165 | D SETL [A0.2++],D0BW.1,D1BW.1 | ||
166 | D SETL [A0.2++],D0ARI.0,D1ARI.0 | ||
167 | D SETL [A0.2++],D0ARI.1,D1ARI.1 | ||
168 | D SETL [A0.2++],D0AWI.0,D1AWI.0 | ||
169 | D SETL [A0.2++],D0AWI.1,D1AWI.1 | ||
170 | D SETL [A0.2++],D0BRI.0,D1BRI.0 | ||
171 | D SETL [A0.2++],D0BRI.1,D1BRI.1 | ||
172 | D SETL [A0.2++],D0BWI.0,D1BWI.0 | ||
173 | D SETL [A0.2++],D0BWI.1,D1BWI.1 | ||
174 | D SETD [A0.2++],T0 | ||
175 | D SETD [A0.2++],T1 | ||
176 | D SETD [A0.2++],T2 | ||
177 | D SETD [A0.2++],T3 | ||
178 | D SETD [A0.2++],T4 | ||
179 | D SETD [A0.2++],T5 | ||
180 | D SETD [A0.2++],T6 | ||
181 | D SETD [A0.2++],T7 | ||
182 | D SETD [A0.2++],T8 | ||
183 | D SETD [A0.2++],T9 | ||
184 | D SETD [A0.2++],TA | ||
185 | D SETD [A0.2++],TB | ||
186 | D SETD [A0.2++],TC | ||
187 | D SETD [A0.2++],TD | ||
188 | D SETD [A0.2++],TE | ||
189 | D SETD [A0.2++],TF | ||
190 | #else | ||
191 | ADD A0.2,A0.2,#(8*18+4*16) | ||
192 | #endif | ||
193 | MOV D0Ar6,TXMRSIZE | ||
194 | MOV D1Ar5,TXDRSIZE | ||
195 | SETL [A0.2++],D0Ar6,D1Ar5 /* Save 8*1 bytes */ | ||
196 | |||
197 | $LCtxSaveCBUF: | ||
198 | #ifdef TBI_1_3 | ||
199 | MOV D0Ar4,D0Re0 /* Copy Ctx Flags */ | ||
200 | ANDT D0Ar4,D0Ar4,#TBICTX_XCBF_BIT /* mask XCBF if already set */ | ||
201 | XOR D0Ar4,D0Ar4,#-1 | ||
202 | AND D0Ar2,D0Ar2,D0Ar4 /* remove XCBF if already set */ | ||
203 | #endif | ||
204 | TSTT D0Ar2,#TBICTX_XCBF_BIT /* Want to save CBUF? */ | ||
205 | ANDT D0Ar2,D0Ar2,#TBICTX_XDX8_BIT+TBICTX_XAXX_BIT+TBICTX_XHL2_BIT+TBICTX_XTDP_BIT+TBICTX_XEXT_BIT | ||
206 | OR D0Ar2,D0Ar2,D0Re0 /* Generate new SaveMask */ | ||
207 | SETD [D1Ar1+#TBICTX_SaveMask-2],D0Ar2/* Add in bits saved to TBICTX */ | ||
208 | MOV D0Re0,A0.2 /* Return end of save area */ | ||
209 | MOV D0Ar4,TXDIVTIME /* Get TXDIVTIME */ | ||
210 | MOVZ PC,A1.2 /* No: Early return */ | ||
211 | TSTT D0Ar2,#TBICTX_CBUF_BIT+TBICTX_CBRP_BIT /* Need to save CBUF? */ | ||
212 | MOVZ PC,A1.2 /* No: Early return */ | ||
213 | ORT D0Ar2,D0Ar2,#TBICTX_XCBF_BIT | ||
214 | SETD [D1Ar1+#TBICTX_SaveMask-2],D0Ar2/* Add in XCBF bit to TBICTX */ | ||
215 | ADD A0.2,D1Ar1,#TBICTX_BYTES /* Dump CBUF state after TBICTX */ | ||
216 | /* | ||
217 | * Save CBUF | ||
218 | */ | ||
219 | SETD [A0.2+# 0],TXCATCH0 /* Restore TXCATCHn */ | ||
220 | SETD [A0.2+# 4],TXCATCH1 | ||
221 | TSTT D0Ar2,#TBICTX_CBRP_BIT /* ... RDDIRTY was/is set */ | ||
222 | SETD [A0.2+# 8],TXCATCH2 | ||
223 | SETD [A0.2+#12],TXCATCH3 | ||
224 | BZ $LCtxSaveComplete | ||
225 | SETL [A0.2+#(2*8)],RD /* Save read pipeline */ | ||
226 | SETL [A0.2+#(3*8)],RD /* Save read pipeline */ | ||
227 | SETL [A0.2+#(4*8)],RD /* Save read pipeline */ | ||
228 | SETL [A0.2+#(5*8)],RD /* Save read pipeline */ | ||
229 | SETL [A0.2+#(6*8)],RD /* Save read pipeline */ | ||
230 | SETL [A0.2+#(7*8)],RD /* Save read pipeline */ | ||
231 | AND TXDIVTIME,D0Ar4,#TXDIVTIME_DIV_BITS /* Clear RPDIRTY */ | ||
232 | $LCtxSaveComplete: | ||
233 | MOV PC,A1.2 /* Return */ | ||
234 | .size ___TBICtxSave,.-___TBICtxSave | ||
235 | |||
236 | /* | ||
237 | * void *__TBICtxRestore( TBIRES State, void *pExt ) | ||
238 | * | ||
239 | * D0Ar2 contains TBICTX_*_BIT values that control what | ||
240 | * extended data is to be recovered from D1Ar3 (pExt). | ||
241 | * | ||
242 | * Virtually all possible scratch registers are used. | ||
243 | */ | ||
244 | /* | ||
245 | * If TBICTX_XEXT_BIT is specified in State. Then the saved state of | ||
246 | * the orginal A0.2 and A1.2 is restored from pExt and the XEXT | ||
247 | * related flags are removed from State.pCtx->SaveMask. | ||
248 | * | ||
249 | */ | ||
250 | .balign 4 | ||
251 | .global ___TBICtxRestore | ||
252 | .type ___TBICtxRestore,function | ||
253 | ___TBICtxRestore: | ||
254 | GETD D0Ar6,[D1Ar1+#TBICTX_CurrMODE] /* Get TXMODE Value */ | ||
255 | ANDST D0Ar2,D0Ar2,#TBICTX_XDX8_BIT+TBICTX_XAXX_BIT+TBICTX_XHL2_BIT+TBICTX_XTDP_BIT+TBICTX_XEXT_BIT | ||
256 | MOV D1Re0,D0Ar2 /* Keep flags in D1Re0 */ | ||
257 | MOV D0Re0,D1Ar3 /* D1Ar3 is default result */ | ||
258 | MOVZ PC,D1RtP /* Early return, nothing to do */ | ||
259 | ANDT D0Ar6,D0Ar6,#0xE000 /* Top bits of TXMODE required */ | ||
260 | MOV A0.3,D0Ar6 /* Save TXMODE for later */ | ||
261 | TSTT D1Re0,#TBICTX_XEXT_BIT /* Check for XEXT bit */ | ||
262 | BZ $LCtxRestXDX8 | ||
263 | GETD D0Ar4,[D1Ar1+#TBICTX_SaveMask-2]/* Get current SaveMask */ | ||
264 | GETL D0Ar6,D1Ar5,[D0Re0++] /* Restore A0.2, A1.2 state */ | ||
265 | ANDMT D0Ar4,D0Ar4,#(0xFFFF-(TBICTX_XDX8_BIT+TBICTX_XAXX_BIT+TBICTX_XHL2_BIT+TBICTX_XTDP_BIT+TBICTX_XEXT_BIT)) | ||
266 | SETD [D1Ar1+#TBICTX_SaveMask-2],D0Ar4/* New SaveMask */ | ||
267 | #ifdef METAC_1_0 | ||
268 | SETD [D1Ar1+#TBICTX_Ext_AX2_U0],D0Ar6 | ||
269 | MOV D0Ar6,D1Ar1 | ||
270 | SETD [D0Ar6+#TBICTX_Ext_AX2_U1],D1Ar5 | ||
271 | #else | ||
272 | SETL [D1Ar1+#TBICTX_Ext_AX2],D0Ar6,D1Ar5 | ||
273 | #endif | ||
274 | $LCtxRestXDX8: | ||
275 | TSTT D1Re0,#TBICTX_XDX8_BIT /* Get extended DX regs? */ | ||
276 | MOV A1.2,D1RtP /* Free off D1RtP register */ | ||
277 | BZ $LCtxRestXAXX | ||
278 | /* | ||
279 | * Restore 8 extra DX registers | ||
280 | */ | ||
281 | MGETL D0.8,D0.9,D0.10,D0.11,D0.12,D0.13,D0.14,D0.15,[D0Re0] | ||
282 | $LCtxRestXAXX: | ||
283 | TSTT D1Re0,#TBICTX_XAXX_BIT /* Get extended AX regs? */ | ||
284 | BZ $LCtxRestXHL2 | ||
285 | /* | ||
286 | * Restore 3 extra AX registers | ||
287 | */ | ||
288 | MGETL A0_4 A0.5,A0.6,A0.7,[D0Re0] /* Get 8*3 bytes */ | ||
289 | $LCtxRestXHL2: | ||
290 | TSTT D1Re0,#TBICTX_XHL2_BIT /* Get hardware-loop regs? */ | ||
291 | BZ $LCtxRestXTDP | ||
292 | /* | ||
293 | * Get hardware loop registers | ||
294 | */ | ||
295 | MGETL D0Ar6,D0Ar4,D0Ar2,[D0Re0] /* Get 8*3 bytes */ | ||
296 | MOV TXL1START,D0Ar6 | ||
297 | MOV TXL2START,D1Ar5 | ||
298 | MOV TXL1END,D0Ar4 | ||
299 | MOV TXL2END,D1Ar3 | ||
300 | MOV TXL1COUNT,D0Ar2 | ||
301 | MOV TXL2COUNT,D1Ar1 | ||
302 | $LCtxRestXTDP: | ||
303 | TSTT D1Re0,#TBICTX_XTDP_BIT /* Get per-thread DSP regs? */ | ||
304 | MOVZ PC,A1.2 /* No: Early return */ | ||
305 | /* | ||
306 | * Get per-thread DSP registers; ACC.0, PR.0, PI.1-3 (PI.0 is zero) | ||
307 | */ | ||
308 | MOV A0.2,D0Re0 | ||
309 | GETL D0Ar6,D1Ar5,[D0Re0++#((16*4)+(18*8))] | ||
310 | #ifndef CTX_NO_DSP | ||
311 | D GETL AC0.0,AC1.0,[A0.2++] /* Restore ACx.0 lower 32-bits */ | ||
312 | DH GETL AC0.0,AC1.0,[A0.2++] /* Restore ACx.0 upper 32-bits */ | ||
313 | #else | ||
314 | ADD A0.2,A0.2,#(2*8) | ||
315 | #endif | ||
316 | ADD D0Re0,D0Re0,#(2*4) | ||
317 | MOV TXMODE,A0.3 /* Some TXMODE bits needed */ | ||
318 | MOV TXMRSIZE,D0Ar6 | ||
319 | MOV TXDRSIZE,D1Ar5 | ||
320 | #ifndef CTX_NO_DSP | ||
321 | D GETL D0AR.0,D1AR.0,[A0.2++] /* Restore DSP RAM registers */ | ||
322 | D GETL D0AR.1,D1AR.1,[A0.2++] | ||
323 | D GETL D0AW.0,D1AW.0,[A0.2++] | ||
324 | D GETL D0AW.1,D1AW.1,[A0.2++] | ||
325 | D GETL D0BR.0,D1BR.0,[A0.2++] | ||
326 | D GETL D0BR.1,D1BR.1,[A0.2++] | ||
327 | D GETL D0BW.0,D1BW.0,[A0.2++] | ||
328 | D GETL D0BW.1,D1BW.1,[A0.2++] | ||
329 | #else | ||
330 | ADD A0.2,A0.2,#(8*8) | ||
331 | #endif | ||
332 | MOV TXMODE,#0 /* Restore TXMODE */ | ||
333 | #ifndef CTX_NO_DSP | ||
334 | D GETL D0ARI.0,D1ARI.0,[A0.2++] | ||
335 | D GETL D0ARI.1,D1ARI.1,[A0.2++] | ||
336 | D GETL D0AWI.0,D1AWI.0,[A0.2++] | ||
337 | D GETL D0AWI.1,D1AWI.1,[A0.2++] | ||
338 | D GETL D0BRI.0,D1BRI.0,[A0.2++] | ||
339 | D GETL D0BRI.1,D1BRI.1,[A0.2++] | ||
340 | D GETL D0BWI.0,D1BWI.0,[A0.2++] | ||
341 | D GETL D0BWI.1,D1BWI.1,[A0.2++] | ||
342 | D GETD T0,[A0.2++] | ||
343 | D GETD T1,[A0.2++] | ||
344 | D GETD T2,[A0.2++] | ||
345 | D GETD T3,[A0.2++] | ||
346 | D GETD T4,[A0.2++] | ||
347 | D GETD T5,[A0.2++] | ||
348 | D GETD T6,[A0.2++] | ||
349 | D GETD T7,[A0.2++] | ||
350 | D GETD T8,[A0.2++] | ||
351 | D GETD T9,[A0.2++] | ||
352 | D GETD TA,[A0.2++] | ||
353 | D GETD TB,[A0.2++] | ||
354 | D GETD TC,[A0.2++] | ||
355 | D GETD TD,[A0.2++] | ||
356 | D GETD TE,[A0.2++] | ||
357 | D GETD TF,[A0.2++] | ||
358 | #else | ||
359 | ADD A0.2,A0.2,#(8*8+4*16) | ||
360 | #endif | ||
361 | MOV PC,A1.2 /* Return */ | ||
362 | .size ___TBICtxRestore,.-___TBICtxRestore | ||
363 | |||
364 | /* | ||
365 | * End of tbictx.S | ||
366 | */ | ||
diff --git a/arch/metag/tbx/tbictxfpu.S b/arch/metag/tbx/tbictxfpu.S new file mode 100644 index 000000000000..e773bea3e7bd --- /dev/null +++ b/arch/metag/tbx/tbictxfpu.S | |||
@@ -0,0 +1,190 @@ | |||
1 | /* | ||
2 | * tbictxfpu.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 | * Explicit state save and restore routines forming part of the thread binary | ||
11 | * interface for META processors | ||
12 | */ | ||
13 | |||
14 | .file "tbifpuctx.S" | ||
15 | |||
16 | #include <asm/metag_regs.h> | ||
17 | #include <asm/tbx.h> | ||
18 | |||
19 | #ifdef TBI_1_4 | ||
20 | /* | ||
21 | * void *__TBICtxFPUSave( TBIRES State, void *pExt ) | ||
22 | * | ||
23 | * D0Ar2 contains TBICTX_*_BIT values that control what | ||
24 | * extended data is to be saved. | ||
25 | * These bits must be ored into the SaveMask of this structure. | ||
26 | * | ||
27 | * Virtually all possible scratch registers are used. | ||
28 | */ | ||
29 | .text | ||
30 | .balign 4 | ||
31 | .global ___TBICtxFPUSave | ||
32 | .type ___TBICtxFPUSave,function | ||
33 | ___TBICtxFPUSave: | ||
34 | |||
35 | /* D1Ar1:D0Ar2 - State | ||
36 | * D1Ar3 - pExt | ||
37 | * D0Ar4 - Value of METAC_CORE_ID | ||
38 | * D1Ar5 - Scratch | ||
39 | * D0Ar6 - Scratch | ||
40 | */ | ||
41 | |||
42 | /* If the FPAC bit isnt set then there is nothing to do */ | ||
43 | TSTT D0Ar2,#TBICTX_FPAC_BIT | ||
44 | MOVZ PC, D1RtP | ||
45 | |||
46 | /* Obtain the Core config */ | ||
47 | MOVT D0Ar4, #HI(METAC_CORE_ID) | ||
48 | ADD D0Ar4, D0Ar4, #LO(METAC_CORE_ID) | ||
49 | GETD D0Ar4, [D0Ar4] | ||
50 | |||
51 | /* Detect FX.8 - FX.15 and add to core config */ | ||
52 | MOV D0Ar6, TXENABLE | ||
53 | AND D0Ar6, D0Ar6, #(TXENABLE_CLASSALT_FPUR8 << TXENABLE_CLASS_S) | ||
54 | AND D0Ar4, D0Ar4, #LO(0x0000FFFF) | ||
55 | ORT D0Ar4, D0Ar4, #HI(TBICTX_CFGFPU_FX16_BIT) | ||
56 | XOR D0Ar4, D0Ar4, D0Ar6 | ||
57 | |||
58 | /* Save the relevant bits to the buffer */ | ||
59 | SETD [D1Ar3++], D0Ar4 | ||
60 | |||
61 | /* Save the relevant bits of TXDEFR (Assumes TXDEFR is coherent) ... */ | ||
62 | MOV D0Ar6, TXDEFR | ||
63 | LSR D0Re0, D0Ar6, #8 | ||
64 | AND D0Re0, D0Re0, #LO(TXDEFR_FPE_FE_BITS>>8) | ||
65 | AND D0Ar6, D0Ar6, #LO(TXDEFR_FPE_ICTRL_BITS) | ||
66 | OR D0Re0, D0Re0, D0Ar6 | ||
67 | |||
68 | /* ... along with relevant bits of TXMODE to buffer */ | ||
69 | MOV D0Ar6, TXMODE | ||
70 | ANDT D0Ar6, D0Ar6, #HI(TXMODE_FPURMODE_BITS) | ||
71 | ORT D0Ar6, D0Ar6, #HI(TXMODE_FPURMODEWRITE_BIT) | ||
72 | OR D0Ar6, D0Ar6, D0Re0 | ||
73 | SETD [D1Ar3++], D0Ar6 | ||
74 | |||
75 | GETD D0Ar6,[D1Ar1+#TBICTX_SaveMask-2] /* Get the current SaveMask */ | ||
76 | /* D0Ar6 - pCtx->SaveMask */ | ||
77 | |||
78 | TSTT D0Ar4, #HI(TBICTX_CFGFPU_FX16_BIT) /* Perform test here for extended FPU registers | ||
79 | * to avoid stalls | ||
80 | */ | ||
81 | /* Save the standard FPU registers */ | ||
82 | F MSETL [D1Ar3++], FX.0, FX.2, FX.4, FX.6 | ||
83 | |||
84 | /* Save the extended FPU registers if they are present */ | ||
85 | BZ $Lskip_save_fx8_fx16 | ||
86 | F MSETL [D1Ar3++], FX.8, FX.10, FX.12, FX.14 | ||
87 | $Lskip_save_fx8_fx16: | ||
88 | |||
89 | /* Save the FPU Accumulator if it is present */ | ||
90 | TST D0Ar4, #METAC_COREID_NOFPACC_BIT | ||
91 | BNZ $Lskip_save_fpacc | ||
92 | F SETL [D1Ar3++], ACF.0 | ||
93 | F SETL [D1Ar3++], ACF.1 | ||
94 | F SETL [D1Ar3++], ACF.2 | ||
95 | $Lskip_save_fpacc: | ||
96 | |||
97 | /* Update pCtx->SaveMask */ | ||
98 | ANDT D0Ar2, D0Ar2, #TBICTX_FPAC_BIT | ||
99 | OR D0Ar6, D0Ar6, D0Ar2 | ||
100 | SETD [D1Ar1+#TBICTX_SaveMask-2],D0Ar6/* Add in XCBF bit to TBICTX */ | ||
101 | |||
102 | MOV D0Re0, D1Ar3 /* Return end of save area */ | ||
103 | MOV PC, D1RtP | ||
104 | |||
105 | .size ___TBICtxFPUSave,.-___TBICtxFPUSave | ||
106 | |||
107 | /* | ||
108 | * void *__TBICtxFPURestore( TBIRES State, void *pExt ) | ||
109 | * | ||
110 | * D0Ar2 contains TBICTX_*_BIT values that control what | ||
111 | * extended data is to be recovered from D1Ar3 (pExt). | ||
112 | * | ||
113 | * Virtually all possible scratch registers are used. | ||
114 | */ | ||
115 | /* | ||
116 | * If TBICTX_XEXT_BIT is specified in State. Then the saved state of | ||
117 | * the orginal A0.2 and A1.2 is restored from pExt and the XEXT | ||
118 | * related flags are removed from State.pCtx->SaveMask. | ||
119 | * | ||
120 | */ | ||
121 | .balign 4 | ||
122 | .global ___TBICtxFPURestore | ||
123 | .type ___TBICtxFPURestore,function | ||
124 | ___TBICtxFPURestore: | ||
125 | |||
126 | /* D1Ar1:D0Ar2 - State | ||
127 | * D1Ar3 - pExt | ||
128 | * D0Ar4 - Value of METAC_CORE_ID | ||
129 | * D1Ar5 - Scratch | ||
130 | * D0Ar6 - Scratch | ||
131 | * D1Re0 - Scratch | ||
132 | */ | ||
133 | |||
134 | /* If the FPAC bit isnt set then there is nothing to do */ | ||
135 | TSTT D0Ar2,#TBICTX_FPAC_BIT | ||
136 | MOVZ PC, D1RtP | ||
137 | |||
138 | /* Obtain the relevant bits of the Core config */ | ||
139 | GETD D0Ar4, [D1Ar3++] | ||
140 | |||
141 | /* Restore FPU related parts of TXDEFR. Assumes TXDEFR is coherent */ | ||
142 | GETD D1Ar5, [D1Ar3++] | ||
143 | MOV D0Ar6, D1Ar5 | ||
144 | LSL D1Re0, D1Ar5, #8 | ||
145 | ANDT D1Re0, D1Re0, #HI(TXDEFR_FPE_FE_BITS|TXDEFR_FPE_ICTRL_BITS) | ||
146 | AND D1Ar5, D1Ar5, #LO(TXDEFR_FPE_FE_BITS|TXDEFR_FPE_ICTRL_BITS) | ||
147 | OR D1Re0, D1Re0, D1Ar5 | ||
148 | |||
149 | MOV D1Ar5, TXDEFR | ||
150 | ANDMT D1Ar5, D1Ar5, #HI(~(TXDEFR_FPE_FE_BITS|TXDEFR_FPE_ICTRL_BITS)) | ||
151 | ANDMB D1Ar5, D1Ar5, #LO(~(TXDEFR_FPE_FE_BITS|TXDEFR_FPE_ICTRL_BITS)) | ||
152 | OR D1Re0, D1Re0, D1Ar5 | ||
153 | MOV TXDEFR, D1Re0 | ||
154 | |||
155 | /* Restore relevant bits of TXMODE */ | ||
156 | MOV D1Ar5, TXMODE | ||
157 | ANDMT D1Ar5, D1Ar5, #HI(~TXMODE_FPURMODE_BITS) | ||
158 | ANDT D0Ar6, D0Ar6, #HI(TXMODE_FPURMODE_BITS|TXMODE_FPURMODEWRITE_BIT) | ||
159 | OR D0Ar6, D0Ar6, D1Ar5 | ||
160 | MOV TXMODE, D0Ar6 | ||
161 | |||
162 | TSTT D0Ar4, #HI(TBICTX_CFGFPU_FX16_BIT) /* Perform test here for extended FPU registers | ||
163 | * to avoid stalls | ||
164 | */ | ||
165 | /* Save the standard FPU registers */ | ||
166 | F MGETL FX.0, FX.2, FX.4, FX.6, [D1Ar3++] | ||
167 | |||
168 | /* Save the extended FPU registers if they are present */ | ||
169 | BZ $Lskip_restore_fx8_fx16 | ||
170 | F MGETL FX.8, FX.10, FX.12, FX.14, [D1Ar3++] | ||
171 | $Lskip_restore_fx8_fx16: | ||
172 | |||
173 | /* Save the FPU Accumulator if it is present */ | ||
174 | TST D0Ar4, #METAC_COREID_NOFPACC_BIT | ||
175 | BNZ $Lskip_restore_fpacc | ||
176 | F GETL ACF.0, [D1Ar3++] | ||
177 | F GETL ACF.1, [D1Ar3++] | ||
178 | F GETL ACF.2, [D1Ar3++] | ||
179 | $Lskip_restore_fpacc: | ||
180 | |||
181 | MOV D0Re0, D1Ar3 /* Return end of save area */ | ||
182 | MOV PC, D1RtP | ||
183 | |||
184 | .size ___TBICtxFPURestore,.-___TBICtxFPURestore | ||
185 | |||
186 | #endif /* TBI_1_4 */ | ||
187 | |||
188 | /* | ||
189 | * End of tbictx.S | ||
190 | */ | ||
diff --git a/arch/metag/tbx/tbidefr.S b/arch/metag/tbx/tbidefr.S new file mode 100644 index 000000000000..3eb165ebf540 --- /dev/null +++ b/arch/metag/tbx/tbidefr.S | |||
@@ -0,0 +1,175 @@ | |||
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 | */ | ||
12 | |||
13 | #include <asm/metag_regs.h> | ||
14 | #include <asm/tbx.h> | ||
15 | |||
16 | .text | ||
17 | .balign 4 | ||
18 | .global ___TBIHandleDFR | ||
19 | .type ___TBIHandleDFR,function | ||
20 | /* D1Ar1:D0Ar2 -- State | ||
21 | * D0Ar3 -- SigNum | ||
22 | * D0Ar4 -- Triggers | ||
23 | * D1Ar5 -- InstOrSWSId | ||
24 | * D0Ar6 -- pTBI (volatile) | ||
25 | */ | ||
26 | ___TBIHandleDFR: | ||
27 | #ifdef META_BUG_MBN100212 | ||
28 | MSETL [A0StP++], D0FrT, D0.5 | ||
29 | |||
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 | */ | ||
36 | |||
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 | ||
55 | |||
56 | /* Mask off anything unrelated to the deferred exception triggers */ | ||
57 | ANDT D1Ar3, D1Ar3, #HI(TXSTAT_BUSERR_BIT | TXSTAT_FPE_BITS) | ||
58 | |||
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 | ||
76 | |||
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] | ||
89 | |||
90 | /* Acknowledge triggers */ | ||
91 | AND D1.5, D1.5, D1Re0 | ||
92 | |||
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 | ||
99 | |||
100 | /* Call the handler */ | ||
101 | SWAP D1RtP, PC | ||
102 | |||
103 | GETL D0.5, D1.5, [--A0StP] | ||
104 | GETL D0FrT, D1RtP, [--A0StP] | ||
105 | MOV PC,D1RtP | ||
106 | #else /* META_BUG_MBN100212 */ | ||
107 | |||
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 | */ | ||
112 | |||
113 | /* - Collect the pending deferred exceptions using TXSTAT, | ||
114 | * (ack's the interrupt exceptions as a side-effect) | ||
115 | */ | ||
116 | DEFR D0Ar4, TXSTATI | ||
117 | |||
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) | ||
121 | |||
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 | ||
146 | |||
147 | SUB D1Ar3, D1Ar3, #(TXSTAT_FPE_INVALID_S - TBID_SIGNUM_FPE) | ||
148 | |||
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 | ||
158 | |||
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] | ||
167 | |||
168 | /* Tailcall the handler */ | ||
169 | MOV PC,D0Re0 | ||
170 | |||
171 | #endif /* META_BUG_MBN100212 */ | ||
172 | .size ___TBIHandleDFR,.-___TBIHandleDFR | ||
173 | /* | ||
174 | * End of tbidefr.S | ||
175 | */ | ||
diff --git a/arch/metag/tbx/tbidspram.S b/arch/metag/tbx/tbidspram.S new file mode 100644 index 000000000000..2f27c0372212 --- /dev/null +++ b/arch/metag/tbx/tbidspram.S | |||
@@ -0,0 +1,161 @@ | |||
1 | /* | ||
2 | * tbidspram.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 | * Explicit state save and restore routines forming part of the thread binary | ||
11 | * interface for META processors | ||
12 | */ | ||
13 | |||
14 | .file "tbidspram.S" | ||
15 | |||
16 | /* These aren't generally useful to a user so for now, they arent publically available */ | ||
17 | #define _TBIECH_DSPRAM_DUA_S 8 | ||
18 | #define _TBIECH_DSPRAM_DUA_BITS 0x7f00 | ||
19 | #define _TBIECH_DSPRAM_DUB_S 0 | ||
20 | #define _TBIECH_DSPRAM_DUB_BITS 0x007f | ||
21 | |||
22 | /* | ||
23 | * void *__TBIDspramSaveA( short DspramSizes, void *pExt ) | ||
24 | */ | ||
25 | .text | ||
26 | .balign 4 | ||
27 | .global ___TBIDspramSaveA | ||
28 | .type ___TBIDspramSaveA,function | ||
29 | ___TBIDspramSaveA: | ||
30 | |||
31 | SETL [A0StP++], D0.5, D1.5 | ||
32 | MOV A0.3, D0Ar2 | ||
33 | |||
34 | /* D1Ar1 - Dspram Sizes | ||
35 | * A0.4 - Pointer to buffer | ||
36 | */ | ||
37 | |||
38 | /* Save the specified amount of dspram DUA */ | ||
39 | DL MOV D0AR.0, #0 | ||
40 | LSR D1Ar1, D1Ar1, #_TBIECH_DSPRAM_DUA_S | ||
41 | AND D1Ar1, D1Ar1, #(_TBIECH_DSPRAM_DUA_BITS >> _TBIECH_DSPRAM_DUA_S) | ||
42 | SUB TXRPT, D1Ar1, #1 | ||
43 | $L1: | ||
44 | DL MOV D0Re0, [D0AR.0++] | ||
45 | DL MOV D0Ar6, [D0AR.0++] | ||
46 | DL MOV D0Ar4, [D0AR.0++] | ||
47 | DL MOV D0.5, [D0AR.0++] | ||
48 | MSETL [A0.3++], D0Re0, D0Ar6, D0Ar4, D0.5 | ||
49 | |||
50 | BR $L1 | ||
51 | |||
52 | GETL D0.5, D1.5, [--A0StP] | ||
53 | MOV PC, D1RtP | ||
54 | |||
55 | .size ___TBIDspramSaveA,.-___TBIDspramSaveA | ||
56 | |||
57 | /* | ||
58 | * void *__TBIDspramSaveB( short DspramSizes, void *pExt ) | ||
59 | */ | ||
60 | .balign 4 | ||
61 | .global ___TBIDspramSaveB | ||
62 | .type ___TBIDspramSaveB,function | ||
63 | ___TBIDspramSaveB: | ||
64 | |||
65 | SETL [A0StP++], D0.5, D1.5 | ||
66 | MOV A0.3, D0Ar2 | ||
67 | |||
68 | /* D1Ar1 - Dspram Sizes | ||
69 | * A0.3 - Pointer to buffer | ||
70 | */ | ||
71 | |||
72 | /* Save the specified amount of dspram DUA */ | ||
73 | DL MOV D0BR.0, #0 | ||
74 | LSR D1Ar1, D1Ar1, #_TBIECH_DSPRAM_DUB_S | ||
75 | AND D1Ar1, D1Ar1, #(_TBIECH_DSPRAM_DUB_BITS >> _TBIECH_DSPRAM_DUB_S) | ||
76 | SUB TXRPT, D1Ar1, #1 | ||
77 | $L2: | ||
78 | DL MOV D0Re0, [D0BR.0++] | ||
79 | DL MOV D0Ar6, [D0BR.0++] | ||
80 | DL MOV D0Ar4, [D0BR.0++] | ||
81 | DL MOV D0.5, [D0BR.0++] | ||
82 | MSETL [A0.3++], D0Re0, D0Ar6, D0Ar4, D0.5 | ||
83 | |||
84 | BR $L2 | ||
85 | |||
86 | GETL D0.5, D1.5, [--A0StP] | ||
87 | MOV PC, D1RtP | ||
88 | |||
89 | .size ___TBIDspramSaveB,.-___TBIDspramSaveB | ||
90 | |||
91 | /* | ||
92 | * void *__TBIDspramRestoreA( short DspramSizes, void *pExt ) | ||
93 | */ | ||
94 | .balign 4 | ||
95 | .global ___TBIDspramRestoreA | ||
96 | .type ___TBIDspramRestoreA,function | ||
97 | ___TBIDspramRestoreA: | ||
98 | |||
99 | SETL [A0StP++], D0.5, D1.5 | ||
100 | MOV A0.3, D0Ar2 | ||
101 | |||
102 | /* D1Ar1 - Dspram Sizes | ||
103 | * A0.3 - Pointer to buffer | ||
104 | */ | ||
105 | |||
106 | /* Restore the specified amount of dspram DUA */ | ||
107 | DL MOV D0AW.0, #0 | ||
108 | LSR D1Ar1, D1Ar1, #_TBIECH_DSPRAM_DUA_S | ||
109 | AND D1Ar1, D1Ar1, #(_TBIECH_DSPRAM_DUA_BITS >> _TBIECH_DSPRAM_DUA_S) | ||
110 | SUB TXRPT, D1Ar1, #1 | ||
111 | $L3: | ||
112 | MGETL D0Re0, D0Ar6, D0Ar4, D0.5, [A0.3++] | ||
113 | DL MOV [D0AW.0++], D0Re0 | ||
114 | DL MOV [D0AW.0++], D0Ar6 | ||
115 | DL MOV [D0AW.0++], D0Ar4 | ||
116 | DL MOV [D0AW.0++], D0.5 | ||
117 | |||
118 | BR $L3 | ||
119 | |||
120 | GETL D0.5, D1.5, [--A0StP] | ||
121 | MOV PC, D1RtP | ||
122 | |||
123 | .size ___TBIDspramRestoreA,.-___TBIDspramRestoreA | ||
124 | |||
125 | /* | ||
126 | * void *__TBIDspramRestoreB( short DspramSizes, void *pExt ) | ||
127 | */ | ||
128 | .balign 4 | ||
129 | .global ___TBIDspramRestoreB | ||
130 | .type ___TBIDspramRestoreB,function | ||
131 | ___TBIDspramRestoreB: | ||
132 | |||
133 | SETL [A0StP++], D0.5, D1.5 | ||
134 | MOV A0.3, D0Ar2 | ||
135 | |||
136 | /* D1Ar1 - Dspram Sizes | ||
137 | * A0.3 - Pointer to buffer | ||
138 | */ | ||
139 | |||
140 | /* Restore the specified amount of dspram DUA */ | ||
141 | DL MOV D0BW.0, #0 | ||
142 | LSR D1Ar1, D1Ar1, #_TBIECH_DSPRAM_DUB_S | ||
143 | AND D1Ar1, D1Ar1, #(_TBIECH_DSPRAM_DUB_BITS >> _TBIECH_DSPRAM_DUB_S) | ||
144 | SUB TXRPT, D1Ar1, #1 | ||
145 | $L4: | ||
146 | MGETL D0Re0, D0Ar6, D0Ar4, D0.5, [A0.3++] | ||
147 | DL MOV [D0BW.0++], D0Re0 | ||
148 | DL MOV [D0BW.0++], D0Ar6 | ||
149 | DL MOV [D0BW.0++], D0Ar4 | ||
150 | DL MOV [D0BW.0++], D0.5 | ||
151 | |||
152 | BR $L4 | ||
153 | |||
154 | GETL D0.5, D1.5, [--A0StP] | ||
155 | MOV PC, D1RtP | ||
156 | |||
157 | .size ___TBIDspramRestoreB,.-___TBIDspramRestoreB | ||
158 | |||
159 | /* | ||
160 | * End of tbidspram.S | ||
161 | */ | ||
diff --git a/arch/metag/tbx/tbilogf.S b/arch/metag/tbx/tbilogf.S new file mode 100644 index 000000000000..4a34d80657db --- /dev/null +++ b/arch/metag/tbx/tbilogf.S | |||
@@ -0,0 +1,48 @@ | |||
1 | /* | ||
2 | * tbilogf.S | ||
3 | * | ||
4 | * Copyright (C) 2001, 2002, 2007, 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 | * Defines __TBILogF trap code for debugging messages and __TBICont for debug | ||
11 | * assert to be implemented on. | ||
12 | */ | ||
13 | |||
14 | .file "tbilogf.S" | ||
15 | |||
16 | /* | ||
17 | * Perform console printf using external debugger or host support | ||
18 | */ | ||
19 | .text | ||
20 | .balign 4 | ||
21 | .global ___TBILogF | ||
22 | .type ___TBILogF,function | ||
23 | ___TBILogF: | ||
24 | MSETL [A0StP],D0Ar6,D0Ar4,D0Ar2 | ||
25 | SWITCH #0xC10020 | ||
26 | MOV D0Re0,#0 | ||
27 | SUB A0StP,A0StP,#24 | ||
28 | MOV PC,D1RtP | ||
29 | .size ___TBILogF,.-___TBILogF | ||
30 | |||
31 | /* | ||
32 | * Perform wait for continue under control of the debugger | ||
33 | */ | ||
34 | .text | ||
35 | .balign 4 | ||
36 | .global ___TBICont | ||
37 | .type ___TBICont,function | ||
38 | ___TBICont: | ||
39 | MOV D0Ar6,#1 | ||
40 | MSETL [A0StP],D0Ar6,D0Ar4,D0Ar2 | ||
41 | SWITCH #0xC30006 /* Returns if we are to continue */ | ||
42 | SUB A0StP,A0StP,#(8*3) | ||
43 | MOV PC,D1RtP /* Return */ | ||
44 | .size ___TBICont,.-___TBICont | ||
45 | |||
46 | /* | ||
47 | * End of tbilogf.S | ||
48 | */ | ||
diff --git a/arch/metag/tbx/tbipcx.S b/arch/metag/tbx/tbipcx.S new file mode 100644 index 000000000000..de0626fdad25 --- /dev/null +++ b/arch/metag/tbx/tbipcx.S | |||
@@ -0,0 +1,451 @@ | |||
1 | /* | ||
2 | * tbipcx.S | ||
3 | * | ||
4 | * Copyright (C) 2001, 2002, 2007, 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 | * Asyncronous trigger handling including exceptions | ||
11 | */ | ||
12 | |||
13 | .file "tbipcx.S" | ||
14 | #include <asm/metag_regs.h> | ||
15 | #include <asm/tbx.h> | ||
16 | |||
17 | /* BEGIN HACK */ | ||
18 | /* define these for now while doing inital conversion to GAS | ||
19 | will fix properly later */ | ||
20 | |||
21 | /* Signal identifiers always have the TBID_SIGNAL_BIT set and contain the | ||
22 | following related bit-fields */ | ||
23 | #define TBID_SIGNUM_S 2 | ||
24 | |||
25 | /* END HACK */ | ||
26 | |||
27 | #ifdef METAC_1_0 | ||
28 | /* Ax.4 is saved in TBICTX */ | ||
29 | #define A0_4 ,A0.4 | ||
30 | #else | ||
31 | /* Ax.4 is NOT saved in TBICTX */ | ||
32 | #define A0_4 | ||
33 | #endif | ||
34 | |||
35 | /* Size of the TBICTX structure */ | ||
36 | #define TBICTX_BYTES ((TBICTX_AX_REGS*8)+TBICTX_AX) | ||
37 | |||
38 | #ifdef METAC_1_1 | ||
39 | #ifndef BOOTROM | ||
40 | #ifndef SPECIAL_BUILD | ||
41 | /* Jump straight into the boot ROM version of this code */ | ||
42 | #define CODE_USES_BOOTROM | ||
43 | #endif | ||
44 | #endif | ||
45 | #endif | ||
46 | |||
47 | /* Define space needed for CATCH buffer state in traditional units */ | ||
48 | #define CATCH_ENTRIES 5 | ||
49 | #define CATCH_ENTRY_BYTES 16 | ||
50 | |||
51 | #ifndef CODE_USES_BOOTROM | ||
52 | #define A0GblIStP A0.15 /* PTBICTX for current thread in PRIV system */ | ||
53 | #define A1GblIGbP A1.15 /* Interrupt A1GbP value in PRIV system */ | ||
54 | #endif | ||
55 | |||
56 | /* | ||
57 | * TBIRES __TBIASyncTrigger( TBIRES State ) | ||
58 | */ | ||
59 | .text | ||
60 | .balign 4 | ||
61 | .global ___TBIASyncTrigger | ||
62 | .type ___TBIASyncTrigger,function | ||
63 | ___TBIASyncTrigger: | ||
64 | #ifdef CODE_USES_BOOTROM | ||
65 | MOVT D0Re0,#HI(LINCORE_BASE) | ||
66 | JUMP D0Re0,#0xA0 | ||
67 | #else | ||
68 | MOV D0FrT,A0FrP /* Boing entry sequence */ | ||
69 | ADD A0FrP,A0StP,#0 | ||
70 | SETL [A0StP++],D0FrT,D1RtP | ||
71 | MOV D0Re0,PCX /* Check for repeat call */ | ||
72 | MOVT D0FrT,#HI(___TBIBoingRTI+4) | ||
73 | ADD D0FrT,D0FrT,#LO(___TBIBoingRTI+4) | ||
74 | CMP D0Re0,D0FrT | ||
75 | BEQ ___TBIBoingExit /* Already set up - come out */ | ||
76 | ADD D1Ar1,D1Ar1,#7 /* PRIV system stack here */ | ||
77 | MOV A0.2,A0StP /* else push context here */ | ||
78 | MOVS D0Re0,D0Ar2 /* Return in user mode? */ | ||
79 | ANDMB D1Ar1,D1Ar1,#0xfff8 /* align priv stack to 64-bit */ | ||
80 | MOV D1Re0,D1Ar1 /* and set result to arg */ | ||
81 | MOVMI A0.2,D1Ar1 /* use priv stack if PRIV set */ | ||
82 | /* | ||
83 | * Generate an initial TBICTX to return to our own current call context | ||
84 | */ | ||
85 | MOVT D1Ar5,#HI(___TBIBoingExit) /* Go here to return */ | ||
86 | ADD D1Ar5,D1Ar5,#LO(___TBIBoingExit) | ||
87 | ADD A0.3,A0.2,#TBICTX_DX /* DX Save area */ | ||
88 | ANDT D0Ar2,D0Ar2,#TBICTX_PRIV_BIT /* Extract PRIV bit */ | ||
89 | MOVT D0Ar6,#TBICTX_SOFT_BIT /* Only soft thread state */ | ||
90 | ADD D0Ar6,D0Ar6,D0Ar2 /* Add in PRIV bit if requested */ | ||
91 | SETL [A0.2],D0Ar6,D1Ar5 /* Push header fields */ | ||
92 | ADD D0FrT,A0.2,#TBICTX_AX /* Address AX save area */ | ||
93 | MSETL [A0.3],D0Re0,D0Ar6,D0Ar4,D0Ar2,D0FrT,D0.5,D0.6,D0.7 | ||
94 | MOV D0Ar6,#0 | ||
95 | MOV D1Ar5,#0 | ||
96 | SETL [A0.3++],D0Ar6,D1Ar5 /* Zero CT register states */ | ||
97 | SETL [A0.3++],D0Ar6,D1Ar5 | ||
98 | MSETL [D0FrT],A0StP,A0FrP,A0.2,A0.3 A0_4 /* Save AX regs */ | ||
99 | MOV A0FrP,A0.2 /* Restore me! */ | ||
100 | B ___TBIResume | ||
101 | .size ___TBIASyncTrigger,.-___TBIASyncTrigger | ||
102 | |||
103 | /* | ||
104 | * Optimised return to handler for META Core | ||
105 | */ | ||
106 | ___TBIBoingRTH: | ||
107 | RTH /* Go to background level */ | ||
108 | MOVT A0.2, #HI($Lpcx_target) | ||
109 | ADD A0.2,A0.2,#LO($Lpcx_target) | ||
110 | MOV PCX,A0.2 /* Setup PCX for interrupts */ | ||
111 | MOV PC,D1Re0 /* Jump to handler */ | ||
112 | /* | ||
113 | * This is where the code below needs to jump to wait for outermost interrupt | ||
114 | * event in a non-privilege mode system (single shared interrupt stack). | ||
115 | */ | ||
116 | ___TBIBoingPCX: | ||
117 | MGETL A0StP,A0FrP,A0.2,A0.3 A0_4,[D1Re0] /* Restore AX regs */ | ||
118 | MOV TXSTATUS,D0Re0 /* Restore flags */ | ||
119 | GETL D0Re0,D1Re0,[D1Re0+#TBICTX_DX-TBICTX_BYTES] | ||
120 | ___TBIBoingRTI: | ||
121 | RTI /* Wait for interrupt */ | ||
122 | $Lpcx_target: | ||
123 | /* | ||
124 | * Save initial interrupt state on current stack | ||
125 | */ | ||
126 | SETL [A0StP+#TBICTX_DX],D0Re0,D1Re0 /* Save key registers */ | ||
127 | ADD D1Re0,A0StP,#TBICTX_AX /* Address AX save area */ | ||
128 | MOV D0Re0,TXSTATUS /* Read TXSTATUS into D0Re0 */ | ||
129 | MOV TXSTATUS,#0 /* Clear TXSTATUS */ | ||
130 | MSETL [D1Re0],A0StP,A0FrP,A0.2,A0.3 A0_4 /* Save AX critical regs */ | ||
131 | /* | ||
132 | * Register state at this point is- | ||
133 | * | ||
134 | * D0Re0 - Old TXSTATUS with PRIV and CBUF bits set if appropriate | ||
135 | * A0StP - Is call stack frame and base of TBICTX being generated | ||
136 | * A1GbP - Is valid static access link | ||
137 | */ | ||
138 | ___TBIBoing: | ||
139 | LOCK0 /* Make sure we have no locks! */ | ||
140 | ADD A1.2,A0StP,#TBICTX_DX+(8*1) /* Address DX.1 save area */ | ||
141 | MOV A0FrP,A0StP /* Setup frame pointer */ | ||
142 | MSETL [A1.2],D0Ar6,D0Ar4,D0Ar2,D0FrT,D0.5,D0.6,D0.7 | ||
143 | MOV D0Ar4,TXRPT /* Save critical CT regs */ | ||
144 | MOV D1Ar3,TXBPOBITS | ||
145 | MOV D1Ar1,TXDIVTIME /* Calc catch buffer pSrc */ | ||
146 | MOV D0Ar2,TXMODE | ||
147 | MOV TXMODE,#0 /* Clear TXMODE */ | ||
148 | #ifdef TXDIVTIME_RPDIRTY_BIT | ||
149 | TSTT D1Ar1,#HI(TXDIVTIME_RPDIRTY_BIT)/* NZ = RPDIRTY */ | ||
150 | MOVT D0Ar6,#TBICTX_CBRP_BIT | ||
151 | ORNZ D0Re0,D0Re0,D0Ar6 /* Set CBRP if RPDIRTY set */ | ||
152 | #endif | ||
153 | MSETL [A1.2],D0Ar4,D0Ar2 /* Save CT regs state */ | ||
154 | MOV D0Ar2,D0Re0 /* Copy TXSTATUS */ | ||
155 | ANDMT D0Ar2,D0Ar2,#TBICTX_CBUF_BIT+TBICTX_CBRP_BIT | ||
156 | #ifdef TBI_1_4 | ||
157 | MOVT D1Ar1,#TBICTX_FPAC_BIT /* Copy FPActive into FPAC */ | ||
158 | TSTT D0Re0,#HI(TXSTATUS_FPACTIVE_BIT) | ||
159 | ORNZ D0Ar2,D0Ar2,D1Ar1 | ||
160 | #endif | ||
161 | MOV D1Ar1,PCX /* Read CurrPC */ | ||
162 | ORT D0Ar2,D0Ar2,#TBICTX_CRIT_BIT /* SaveMask + CRIT bit */ | ||
163 | SETL [A0FrP+#TBICTX_Flags],D0Ar2,D1Ar1 /* Set pCtx header fields */ | ||
164 | /* | ||
165 | * Completed context save, now we need to make a call to an interrupt handler | ||
166 | * | ||
167 | * D0Re0 - holds PRIV, WAIT, CBUF flags, HALT reason if appropriate | ||
168 | * A0FrP - interrupt stack frame and base of TBICTX being generated | ||
169 | * A0StP - same as A0FrP | ||
170 | */ | ||
171 | ___TBIBoingWait: | ||
172 | /* Reserve space for TBICTX and CBUF */ | ||
173 | ADD A0StP,A0StP,#TBICTX_BYTES+(CATCH_ENTRY_BYTES*CATCH_ENTRIES) | ||
174 | MOV D0Ar4,TXSTATI /* Read the Triggers data */ | ||
175 | MOV D1Ar3,TXDIVTIME /* Read IRQEnc bits */ | ||
176 | MOV D0Ar2,D0Re0 /* Copy PRIV and WAIT flags */ | ||
177 | ANDT D0Ar2,D0Ar2,#TBICTX_PRIV_BIT+TBICTX_WAIT_BIT+TBICTX_CBUF_BIT | ||
178 | #ifdef TBI_1_4 | ||
179 | MOVT D1Ar5,#TBICTX_FPAC_BIT /* Copy FPActive into FPAC */ | ||
180 | TSTT D0Re0,#HI(TXSTATUS_FPACTIVE_BIT) | ||
181 | ORNZ D0Ar2,D0Ar2,D1Ar5 | ||
182 | #endif | ||
183 | ANDT D1Ar3,D1Ar3,#HI(TXDIVTIME_IRQENC_BITS) | ||
184 | LSR D1Ar3,D1Ar3,#TXDIVTIME_IRQENC_S | ||
185 | AND TXSTATI,D0Ar4,#TXSTATI_BGNDHALT_BIT/* Ack any HALT seen */ | ||
186 | ANDS D0Ar4,D0Ar4,#0xFFFF-TXSTATI_BGNDHALT_BIT /* Only seen HALT? */ | ||
187 | ORT D0Ar2,D0Ar2,#TBICTX_CRIT_BIT /* Set CRIT */ | ||
188 | #ifndef BOOTROM | ||
189 | MOVT A1LbP,#HI(___pTBIs) | ||
190 | ADD A1LbP,A1LbP,#LO(___pTBIs) | ||
191 | GETL D1Ar5,D0Ar6,[A1LbP] /* D0Ar6 = ___pTBIs[1] */ | ||
192 | #else | ||
193 | /* | ||
194 | * For BOOTROM support ___pTBIs must be allocated at offset 0 vs A1GbP | ||
195 | */ | ||
196 | GETL D1Ar5,D0Ar6,[A1GbP] /* D0Ar6 = ___pTBIs[1] */ | ||
197 | #endif | ||
198 | BZ ___TBIBoingHalt /* Yes: Service HALT */ | ||
199 | /* | ||
200 | * Encode interrupt as signal vector, strip away same/lower TXMASKI bits | ||
201 | */ | ||
202 | MOV D1Ar1,#1 /* Generate mask for this bit */ | ||
203 | MOV D0Re0,TXMASKI /* Get interrupt mask */ | ||
204 | LSL TXSTATI,D1Ar1,D1Ar3 /* Acknowledge trigger */ | ||
205 | AND TXMASKI,D0Re0,#TXSTATI_BGNDHALT_BIT /* Only allow HALTs */ | ||
206 | OR D0Ar2,D0Ar2,D0Re0 /* Set TBIRES.Sig.TrigMask */ | ||
207 | ADD D1Ar3,D1Ar3,#TBID_SIGNUM_TRT /* Offset into interrupt sigs */ | ||
208 | LSL D0Re0,D1Ar3,#TBID_SIGNUM_S /* Generate offset from SigNum */ | ||
209 | /* | ||
210 | * This is a key moment we are about to call the handler, register state is | ||
211 | * as follows- | ||
212 | * | ||
213 | * D0Re0 - Handler vector (SigNum<<TBID_SIGNUM_S) | ||
214 | * D0Ar2 - TXMASKI:TBICTX_CRIT_BIT with optional CBUF and PRIV bits | ||
215 | * D1Ar3 - SigNum | ||
216 | * D0Ar4 - State read from TXSTATI | ||
217 | * D1Ar5 - Inst for SWITCH trigger case only, otherwise undefined | ||
218 | * D0Ar6 - pTBI | ||
219 | */ | ||
220 | ___TBIBoingVec: | ||
221 | ADD D0Re0,D0Re0,#TBI_fnSigs /* Offset into signal table */ | ||
222 | GETD D1Re0,[D0Ar6+D0Re0] /* Get address for Handler */ | ||
223 | /* | ||
224 | * Call handler at interrupt level, when it returns simply resume execution | ||
225 | * of state indicated by D1Re0. | ||
226 | */ | ||
227 | MOV D1Ar1,A0FrP /* Pass in pCtx */ | ||
228 | CALLR D1RtP,___TBIBoingRTH /* Use RTH to invoke handler */ | ||
229 | |||
230 | /* | ||
231 | * Perform critical state restore and execute background thread. | ||
232 | * | ||
233 | * A0FrP - is pointer to TBICTX structure to resume | ||
234 | * D0Re0 - contains additional TXMASKI triggers | ||
235 | */ | ||
236 | .text | ||
237 | .balign 4 | ||
238 | #ifdef BOOTROM | ||
239 | .global ___TBIResume | ||
240 | #endif | ||
241 | ___TBIResume: | ||
242 | /* | ||
243 | * New META IP method | ||
244 | */ | ||
245 | RTH /* Go to interrupt level */ | ||
246 | MOV D0Ar4,TXMASKI /* Read TXMASKI */ | ||
247 | OR TXMASKI,D0Ar4,D0Re0 /* -Write-Modify TXMASKI */ | ||
248 | GETL D0Re0,D1Re0,[A0FrP+#TBICTX_Flags]/* Get Flags:SaveMask, CurrPC */ | ||
249 | MOV A0StP,A0FrP /* Position stack pointer */ | ||
250 | MOV D0Ar2,TXPOLLI /* Read pending triggers */ | ||
251 | MOV PCX,D1Re0 /* Set resumption PC */ | ||
252 | TST D0Ar2,#0xFFFF /* Any pending triggers? */ | ||
253 | BNZ ___TBIBoingWait /* Yes: Go for triggers */ | ||
254 | TSTT D0Re0,#TBICTX_WAIT_BIT /* Do we WAIT anyway? */ | ||
255 | BNZ ___TBIBoingWait /* Yes: Go for triggers */ | ||
256 | LSLS D1Ar5,D0Re0,#1 /* Test XCBF (MI) & PRIV (CS)? */ | ||
257 | ADD D1Re0,A0FrP,#TBICTX_CurrRPT /* Address CT save area */ | ||
258 | ADD A0StP,A0FrP,#TBICTX_DX+(8*1) /* Address DX.1 save area */ | ||
259 | MGETL A0.2,A0.3,[D1Re0] /* Get CT reg states */ | ||
260 | MOV D1Ar3,A1.3 /* Copy old TXDIVTIME */ | ||
261 | BPL ___TBIResCrit /* No: Skip logic */ | ||
262 | ADD D0Ar4,A0FrP,#TBICTX_BYTES /* Source is after TBICTX */ | ||
263 | ANDST D1Ar3,D1Ar3,#HI(TXDIVTIME_RPMASK_BITS)/* !Z if RPDIRTY */ | ||
264 | MGETL D0.5,D0.6,[D0Ar4] /* Read Catch state */ | ||
265 | MOV TXCATCH0,D0.5 /* Restore TXCATCHn */ | ||
266 | MOV TXCATCH1,D1.5 | ||
267 | MOV TXCATCH2,D0.6 | ||
268 | MOV TXCATCH3,D1.6 | ||
269 | BZ ___TBIResCrit | ||
270 | MOV D0Ar2,#(1*8) | ||
271 | LSRS D1Ar3,D1Ar3,#TXDIVTIME_RPMASK_S+1 /* 2nd RPMASK bit -> bit 0 */ | ||
272 | ADD RA,D0Ar4,#(0*8) /* Re-read read pipeline */ | ||
273 | ADDNZ RA,D0Ar4,D0Ar2 /* If Bit 0 set issue RA */ | ||
274 | LSRS D1Ar3,D1Ar3,#2 /* Bit 1 -> C, Bit 2 -> Bit 0 */ | ||
275 | ADD D0Ar2,D0Ar2,#8 | ||
276 | ADDCS RA,D0Ar4,D0Ar2 /* If C issue RA */ | ||
277 | ADD D0Ar2,D0Ar2,#8 | ||
278 | ADDNZ RA,D0Ar4,D0Ar2 /* If Bit 0 set issue RA */ | ||
279 | LSRS D1Ar3,D1Ar3,#2 /* Bit 1 -> C, Bit 2 -> Bit 0 */ | ||
280 | ADD D0Ar2,D0Ar2,#8 | ||
281 | ADDCS RA,D0Ar4,D0Ar2 /* If C issue RA */ | ||
282 | ADD D0Ar2,D0Ar2,#8 | ||
283 | ADDNZ RA,D0Ar4,D0Ar2 /* If Bit 0 set issue RA */ | ||
284 | MOV TXDIVTIME,A1.3 /* Set RPDIRTY again */ | ||
285 | ___TBIResCrit: | ||
286 | LSLS D1Ar5,D0Re0,#1 /* Test XCBF (MI) & PRIV (CS)? */ | ||
287 | #ifdef TBI_1_4 | ||
288 | ANDT D1Ar5,D1Ar5,#(TBICTX_FPAC_BIT*2) | ||
289 | LSL D0Ar6,D1Ar5,#3 /* Convert FPAC into FPACTIVE */ | ||
290 | #endif | ||
291 | ANDMT D0Re0,D0Re0,#TBICTX_CBUF_BIT /* Keep CBUF bit from SaveMask */ | ||
292 | #ifdef TBI_1_4 | ||
293 | OR D0Re0,D0Re0,D0Ar6 /* Combine FPACTIVE with others */ | ||
294 | #endif | ||
295 | MGETL D0Ar6,D0Ar4,D0Ar2,D0FrT,D0.5,D0.6,D0.7,[A0StP] /* Restore DX */ | ||
296 | MOV TXRPT,A0.2 /* Restore CT regs */ | ||
297 | MOV TXBPOBITS,A1.2 | ||
298 | MOV TXMODE,A0.3 | ||
299 | BCC ___TBIBoingPCX /* Do non-PRIV wait! */ | ||
300 | MOV A1GblIGbP,A1GbP /* Save A1GbP too */ | ||
301 | MGETL A0StP,A0FrP,A0.2,A0.3 A0_4,[D1Re0] /* Restore AX regs */ | ||
302 | /* | ||
303 | * Wait for the first interrupt/exception trigger in a privilege mode system | ||
304 | * (interrupt stack area for current TASK to be pointed to by A0GblIStP | ||
305 | * or per_cpu__stack_save[hwthread_id]). | ||
306 | */ | ||
307 | MOV TXSTATUS,D0Re0 /* Restore flags */ | ||
308 | MOV D0Re0,TXPRIVEXT /* Set TXPRIVEXT_TXTOGGLEI_BIT */ | ||
309 | SUB D1Re0,D1Re0,#TBICTX_BYTES /* TBICTX is top of int stack */ | ||
310 | #ifdef TBX_PERCPU_SP_SAVE | ||
311 | SWAP D1Ar3,A1GbP | ||
312 | MOV D1Ar3,TXENABLE /* Which thread are we? */ | ||
313 | AND D1Ar3,D1Ar3,#TXENABLE_THREAD_BITS | ||
314 | LSR D1Ar3,D1Ar3,#TXENABLE_THREAD_S-2 | ||
315 | ADDT D1Ar3,D1Ar3,#HI(_per_cpu__stack_save) | ||
316 | ADD D1Ar3,D1Ar3,#LO(_per_cpu__stack_save) | ||
317 | SETD [D1Ar3],D1Re0 | ||
318 | SWAP D1Ar3,A1GbP | ||
319 | #else | ||
320 | MOV A0GblIStP, D1Re0 | ||
321 | #endif | ||
322 | OR D0Re0,D0Re0,#TXPRIVEXT_TXTOGGLEI_BIT | ||
323 | MOV TXPRIVEXT,D0Re0 /* Cannot set TXPRIVEXT if !priv */ | ||
324 | GETL D0Re0,D1Re0,[D1Re0+#TBICTX_DX] | ||
325 | RTI /* Wait for interrupt */ | ||
326 | /* | ||
327 | * Save initial interrupt state on A0GblIStP, switch to A0GblIStP if | ||
328 | * BOOTROM code, save and switch to [A1GbP] otherwise. | ||
329 | */ | ||
330 | ___TBIBoingPCXP: | ||
331 | #ifdef TBX_PERCPU_SP_SAVE | ||
332 | SWAP D1Ar3,A1GbP /* Get PRIV stack base */ | ||
333 | MOV D1Ar3,TXENABLE /* Which thread are we? */ | ||
334 | AND D1Ar3,D1Ar3,#TXENABLE_THREAD_BITS | ||
335 | LSR D1Ar3,D1Ar3,#TXENABLE_THREAD_S-2 | ||
336 | ADDT D1Ar3,D1Ar3,#HI(_per_cpu__stack_save) | ||
337 | ADD D1Ar3,D1Ar3,#LO(_per_cpu__stack_save) | ||
338 | GETD D1Ar3,[D1Ar3] | ||
339 | #else | ||
340 | SWAP D1Ar3,A0GblIStP /* Get PRIV stack base */ | ||
341 | #endif | ||
342 | SETL [D1Ar3+#TBICTX_DX],D0Re0,D1Re0 /* Save key registers */ | ||
343 | MOV D0Re0,TXPRIVEXT /* Clear TXPRIVEXT_TXTOGGLEI_BIT */ | ||
344 | ADD D1Re0,D1Ar3,#TBICTX_AX /* Address AX save area */ | ||
345 | ANDMB D0Re0,D0Re0,#0xFFFF-TXPRIVEXT_TXTOGGLEI_BIT | ||
346 | MOV TXPRIVEXT,D0Re0 /* Cannot set TXPRIVEXT if !priv */ | ||
347 | MOV D0Re0,TXSTATUS /* Read TXSTATUS into D0Re0 */ | ||
348 | MOV TXSTATUS,#0 /* Clear TXSTATUS */ | ||
349 | MSETL [D1Re0],A0StP,A0FrP,A0.2,A0.3 A0_4 /* Save AX critical regs */ | ||
350 | MOV A0StP,D1Ar3 /* Switch stacks */ | ||
351 | #ifdef TBX_PERCPU_SP_SAVE | ||
352 | MOV D1Ar3,A1GbP /* Get D1Ar2 back */ | ||
353 | #else | ||
354 | MOV D1Ar3,A0GblIStP /* Get D1Ar2 back */ | ||
355 | #endif | ||
356 | ORT D0Re0,D0Re0,#TBICTX_PRIV_BIT /* Add PRIV to TXSTATUS */ | ||
357 | MOV A1GbP,A1GblIGbP /* Restore A1GbP */ | ||
358 | B ___TBIBoing /* Enter common handler code */ | ||
359 | /* | ||
360 | * At this point we know it's a background HALT case we are handling. | ||
361 | * The restored TXSTATUS always needs to have zero in the reason bits. | ||
362 | */ | ||
363 | ___TBIBoingHalt: | ||
364 | MOV D0Ar4,TXMASKI /* Get interrupt mask */ | ||
365 | ANDST D0Re0,D0Re0,#HI(TXSTATUS_MAJOR_HALT_BITS+TXSTATUS_MEM_FAULT_BITS) | ||
366 | AND TXMASKI,D0Ar4,#TXSTATI_BGNDHALT_BIT /* Only allow HALTs */ | ||
367 | AND D0Ar4,D0Ar4,#0xFFFF-TXSTATI_BGNDHALT_BIT /* What ints are off? */ | ||
368 | OR D0Ar2,D0Ar2,D0Ar4 /* Set TBIRES.Sig.TrigMask */ | ||
369 | MOV D0Ar4,#TXSTATI_BGNDHALT_BIT /* This was the trigger state */ | ||
370 | LSR D1Ar3,D0Re0,#TXSTATUS_MAJOR_HALT_S | ||
371 | MOV D0Re0,#TBID_SIGNUM_XXF<<TBID_SIGNUM_S | ||
372 | BNZ ___TBIBoingVec /* Jump to XXF exception handler */ | ||
373 | /* | ||
374 | * Only the SWITCH cases are left, PCX must be valid | ||
375 | */ | ||
376 | #ifdef TBI_1_4 | ||
377 | MOV D1Ar5,TXPRIVEXT | ||
378 | TST D1Ar5,#TXPRIVEXT_MINIMON_BIT | ||
379 | LSR D1Ar3,D1Ar1,#1 /* Shift needed for MINIM paths (fill stall) */ | ||
380 | BZ $Lmeta /* If META only, skip */ | ||
381 | TSTT D1Ar1,#HI(0x00800000) | ||
382 | ANDMT D1Ar3,D1Ar3,#HI(0x007FFFFF >> 1)/* Shifted mask for large MINIM */ | ||
383 | ANDT D1Ar1,D1Ar1,#HI(0xFFE00000) /* Static mask for small MINIM */ | ||
384 | BZ $Llarge_minim /* If large MINIM */ | ||
385 | $Lsmall_minim: | ||
386 | TSTT D1Ar3,#HI(0x00100000 >> 1) | ||
387 | ANDMT D1Ar3,D1Ar3,#HI(0x001FFFFF >> 1)/* Correct shifted mask for large MINIM */ | ||
388 | ADDZ D1Ar1,D1Ar1,D1Ar3 /* If META rgn, add twice to undo LSR #1 */ | ||
389 | B $Lrecombine | ||
390 | $Llarge_minim: | ||
391 | ANDST D1Ar1,D1Ar1,#HI(0xFF800000) /* Correct static mask for small MINIM */ | ||
392 | /* Z=0 (Cannot place code at NULL) */ | ||
393 | $Lrecombine: | ||
394 | ADD D1Ar1,D1Ar1,D1Ar3 /* Combine static and shifted parts */ | ||
395 | $Lmeta: | ||
396 | GETW D1Ar5,[D1Ar1++] /* META: lo-16, MINIM: lo-16 (all-16 if short) */ | ||
397 | GETW D1Ar3,[D1Ar1] /* META: hi-16, MINIM: hi-16 (only if long) */ | ||
398 | MOV D1Re0,D1Ar5 | ||
399 | XOR D1Re0,D1Re0,#0x4000 | ||
400 | LSLSNZ D1Re0,D1Re0,#(32-14) /* MINIM: If long C=0, if short C=1 */ | ||
401 | LSLCC D1Ar3,D1Ar3,#16 /* META/MINIM long: Move hi-16 up */ | ||
402 | LSLCS D1Ar3,D1Ar5,#16 /* MINIM short: Dup all-16 */ | ||
403 | ADD D1Ar5,D1Ar5,D1Ar3 /* ALL: Combine both 16-bit parts */ | ||
404 | #else | ||
405 | GETD D1Ar5,[D1Ar1] /* Read instruction for switch */ | ||
406 | #endif | ||
407 | LSR D1Ar3,D1Ar5,#22 /* Convert into signal number */ | ||
408 | AND D1Ar3,D1Ar3,#TBID_SIGNUM_SW3-TBID_SIGNUM_SW0 | ||
409 | LSL D0Re0,D1Ar3,#TBID_SIGNUM_S /* Generate offset from SigNum */ | ||
410 | B ___TBIBoingVec /* Jump to switch handler */ | ||
411 | /* | ||
412 | * Exit from TBIASyncTrigger call | ||
413 | */ | ||
414 | ___TBIBoingExit: | ||
415 | GETL D0FrT,D1RtP,[A0FrP++] /* Restore state from frame */ | ||
416 | SUB A0StP,A0FrP,#8 /* Unwind stack */ | ||
417 | MOV A0FrP,D0FrT /* Last memory read completes */ | ||
418 | MOV PC,D1RtP /* Return to caller */ | ||
419 | #endif /* ifdef CODE_USES_BOOTROM */ | ||
420 | .size ___TBIResume,.-___TBIResume | ||
421 | |||
422 | #ifndef BOOTROM | ||
423 | /* | ||
424 | * void __TBIASyncResume( TBIRES State ) | ||
425 | */ | ||
426 | .text | ||
427 | .balign 4 | ||
428 | .global ___TBIASyncResume | ||
429 | .type ___TBIASyncResume,function | ||
430 | ___TBIASyncResume: | ||
431 | /* | ||
432 | * Perform CRIT|SOFT state restore and execute background thread. | ||
433 | */ | ||
434 | MOV D1Ar3,D1Ar1 /* Restore this context */ | ||
435 | MOV D0Re0,D0Ar2 /* Carry in additional triggers */ | ||
436 | /* Reserve space for TBICTX */ | ||
437 | ADD D1Ar3,D1Ar3,#TBICTX_BYTES+(CATCH_ENTRY_BYTES*CATCH_ENTRIES) | ||
438 | MOV A0StP,D1Ar3 /* Enter with protection of */ | ||
439 | MOV A0FrP,D1Ar1 /* TBICTX on our stack */ | ||
440 | #ifdef CODE_USES_BOOTROM | ||
441 | MOVT D1Ar1,#HI(LINCORE_BASE) | ||
442 | JUMP D1Ar1,#0xA4 | ||
443 | #else | ||
444 | B ___TBIResume | ||
445 | #endif | ||
446 | .size ___TBIASyncResume,.-___TBIASyncResume | ||
447 | #endif /* ifndef BOOTROM */ | ||
448 | |||
449 | /* | ||
450 | * End of tbipcx.S | ||
451 | */ | ||
diff --git a/arch/metag/tbx/tbiroot.S b/arch/metag/tbx/tbiroot.S new file mode 100644 index 000000000000..7d84daf1340b --- /dev/null +++ b/arch/metag/tbx/tbiroot.S | |||
@@ -0,0 +1,87 @@ | |||
1 | /* | ||
2 | * tbiroot.S | ||
3 | * | ||
4 | * Copyright (C) 2001, 2002, 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 | * Module that creates and via ___TBI function returns a TBI Root Block for | ||
11 | * interrupt and background processing on the current thread. | ||
12 | */ | ||
13 | |||
14 | .file "tbiroot.S" | ||
15 | #include <asm/metag_regs.h> | ||
16 | |||
17 | /* | ||
18 | * Get data structures and defines from the TBI C header | ||
19 | */ | ||
20 | #include <asm/tbx.h> | ||
21 | |||
22 | |||
23 | /* If signals need to be exchanged we must create a TBI Root Block */ | ||
24 | |||
25 | .data | ||
26 | .balign 8 | ||
27 | .global ___pTBIs | ||
28 | .type ___pTBIs,object | ||
29 | ___pTBIs: | ||
30 | .long 0 /* Bgnd+Int root block ptrs */ | ||
31 | .long 0 | ||
32 | .size ___pTBIs,.-___pTBIs | ||
33 | |||
34 | |||
35 | /* | ||
36 | * Return ___pTBIs value specific to execution level with promotion/demotion | ||
37 | * | ||
38 | * Register Usage: D1Ar1 is Id, D0Re0 is the primary result | ||
39 | * D1Re0 is secondary result (___pTBIs for other exec level) | ||
40 | */ | ||
41 | .text | ||
42 | .balign 4 | ||
43 | .global ___TBI | ||
44 | .type ___TBI,function | ||
45 | ___TBI: | ||
46 | TSTT D1Ar1,#HI(TBID_ISTAT_BIT) /* Bgnd or Int level? */ | ||
47 | MOVT A1LbP,#HI(___pTBIs) | ||
48 | ADD A1LbP,A1LbP,#LO(___pTBIs) | ||
49 | GETL D0Re0,D1Re0,[A1LbP] /* Base of root block table */ | ||
50 | SWAPNZ D0Re0,D1Re0 /* Swap if asked */ | ||
51 | MOV PC,D1RtP | ||
52 | .size ___TBI,.-___TBI | ||
53 | |||
54 | |||
55 | /* | ||
56 | * Return identifier of the current thread in TBI segment or signal format with | ||
57 | * secondary mask to indicate privilege and interrupt level of thread | ||
58 | */ | ||
59 | .text | ||
60 | .balign 4 | ||
61 | .global ___TBIThrdPrivId | ||
62 | .type ___TBIThrdPrivId,function | ||
63 | ___TBIThrdPrivId: | ||
64 | .global ___TBIThreadId | ||
65 | .type ___TBIThreadId,function | ||
66 | ___TBIThreadId: | ||
67 | #ifndef METAC_0_1 | ||
68 | MOV D1Re0,TXSTATUS /* Are we privileged or int? */ | ||
69 | MOV D0Re0,TXENABLE /* Which thread are we? */ | ||
70 | /* Disable privilege adaption for now */ | ||
71 | ANDT D1Re0,D1Re0,#HI(TXSTATUS_ISTAT_BIT) /* +TXSTATUS_PSTAT_BIT) */ | ||
72 | LSL D1Re0,D1Re0,#TBID_ISTAT_S-TXSTATUS_ISTAT_S | ||
73 | AND D0Re0,D0Re0,#TXENABLE_THREAD_BITS | ||
74 | LSL D0Re0,D0Re0,#TBID_THREAD_S-TXENABLE_THREAD_S | ||
75 | #else | ||
76 | /* Thread 0 only */ | ||
77 | XOR D0Re0,D0Re0,D0Re0 | ||
78 | XOR D1Re0,D1Re0,D1Re0 | ||
79 | #endif | ||
80 | MOV PC,D1RtP /* Return */ | ||
81 | .size ___TBIThrdPrivId,.-___TBIThrdPrivId | ||
82 | .size ___TBIThreadId,.-___TBIThreadId | ||
83 | |||
84 | |||
85 | /* | ||
86 | * End of tbiroot.S | ||
87 | */ | ||
diff --git a/arch/metag/tbx/tbisoft.S b/arch/metag/tbx/tbisoft.S new file mode 100644 index 000000000000..0346fe8a53b1 --- /dev/null +++ b/arch/metag/tbx/tbisoft.S | |||
@@ -0,0 +1,237 @@ | |||
1 | /* | ||
2 | * tbisoft.S | ||
3 | * | ||
4 | * Copyright (C) 2001, 2002, 2007, 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 | * Support for soft threads and soft context switches | ||
11 | */ | ||
12 | |||
13 | .file "tbisoft.S" | ||
14 | |||
15 | #include <asm/tbx.h> | ||
16 | |||
17 | #ifdef METAC_1_0 | ||
18 | /* Ax.4 is saved in TBICTX */ | ||
19 | #define A0_4 ,A0.4 | ||
20 | #define D0_5 ,D0.5 | ||
21 | #else | ||
22 | /* Ax.4 is NOT saved in TBICTX */ | ||
23 | #define A0_4 | ||
24 | #define D0_5 | ||
25 | #endif | ||
26 | |||
27 | /* Size of the TBICTX structure */ | ||
28 | #define TBICTX_BYTES ((TBICTX_AX_REGS*8)+TBICTX_AX) | ||
29 | |||
30 | .text | ||
31 | .balign 4 | ||
32 | .global ___TBISwitchTail | ||
33 | .type ___TBISwitchTail,function | ||
34 | ___TBISwitchTail: | ||
35 | B $LSwitchTail | ||
36 | .size ___TBISwitchTail,.-___TBISwitchTail | ||
37 | |||
38 | /* | ||
39 | * TBIRES __TBIJumpX( TBIX64 ArgsA, PTBICTX *rpSaveCtx, int TrigsMask, | ||
40 | * void (*fnMain)(), void *pStack ); | ||
41 | * | ||
42 | * This is a combination of __TBISwitch and __TBIJump with the context of | ||
43 | * the calling thread being saved in the rpSaveCtx location with a drop-thru | ||
44 | * effect into the __TBIJump logic. ArgsB passes via __TBIJump to the | ||
45 | * routine eventually invoked will reflect the rpSaveCtx value specified. | ||
46 | */ | ||
47 | .text | ||
48 | .balign 4 | ||
49 | .global ___TBIJumpX | ||
50 | .type ___TBIJumpX,function | ||
51 | ___TBIJumpX: | ||
52 | CMP D1RtP,#-1 | ||
53 | B $LSwitchStart | ||
54 | .size ___TBIJumpX,.-___TBIJumpX | ||
55 | |||
56 | /* | ||
57 | * TBIRES __TBISwitch( TBIRES Switch, PTBICTX *rpSaveCtx ) | ||
58 | * | ||
59 | * Software syncronous context switch between soft threads, save only the | ||
60 | * registers which are actually valid on call entry. | ||
61 | * | ||
62 | * A0FrP, D0RtP, D0.5, D0.6, D0.7 - Saved on stack | ||
63 | * A1GbP is global to all soft threads so not virtualised | ||
64 | * A0StP is then saved as the base of the TBICTX of the thread | ||
65 | * | ||
66 | */ | ||
67 | .text | ||
68 | .balign 4 | ||
69 | .global ___TBISwitch | ||
70 | .type ___TBISwitch,function | ||
71 | ___TBISwitch: | ||
72 | XORS D0Re0,D0Re0,D0Re0 /* Set ZERO flag */ | ||
73 | $LSwitchStart: | ||
74 | MOV D0FrT,A0FrP /* Boing entry sequence */ | ||
75 | ADD A0FrP,A0StP,#0 | ||
76 | SETL [A0StP+#8++],D0FrT,D1RtP | ||
77 | /* | ||
78 | * Save current frame state - we save all regs because we don't want | ||
79 | * uninitialised crap in the TBICTX structure that the asyncronous resumption | ||
80 | * of a thread will restore. | ||
81 | */ | ||
82 | MOVT D1Re0,#HI($LSwitchExit) /* ASync resume point here */ | ||
83 | ADD D1Re0,D1Re0,#LO($LSwitchExit) | ||
84 | SETD [D1Ar3],A0StP /* Record pCtx of this thread */ | ||
85 | MOVT D0Re0,#TBICTX_SOFT_BIT /* Only soft thread state */ | ||
86 | SETL [A0StP++],D0Re0,D1Re0 /* Push header fields */ | ||
87 | ADD D0FrT,A0StP,#TBICTX_AX-TBICTX_DX /* Address AX save area */ | ||
88 | MOV D0Re0,#0 /* Setup 0:0 result for ASync */ | ||
89 | MOV D1Re0,#0 /* resume of the thread */ | ||
90 | MSETL [A0StP],D0Re0,D0Ar6,D0Ar4,D0Ar2,D0FrT,D0.5,D0.6,D0.7 | ||
91 | SETL [A0StP++],D0Re0,D1Re0 /* Zero CurrRPT, CurrBPOBITS, */ | ||
92 | SETL [A0StP++],D0Re0,D1Re0 /* Zero CurrMODE, CurrDIVTIME */ | ||
93 | ADD A0StP,A0StP,#(TBICTX_AX_REGS*8) /* Reserve AX save space */ | ||
94 | MSETL [D0FrT],A0StP,A0FrP,A0.2,A0.3 A0_4 /* Save AX regs */ | ||
95 | BNZ ___TBIJump | ||
96 | /* | ||
97 | * NextThread MUST be in TBICTX_SOFT_BIT state! | ||
98 | */ | ||
99 | $LSwitchTail: | ||
100 | MOV D0Re0,D0Ar2 /* Result from args */ | ||
101 | MOV D1Re0,D1Ar1 | ||
102 | ADD D1RtP,D1Ar1,#TBICTX_AX | ||
103 | MGETL A0StP,A0FrP,[D1RtP] /* Get frame values */ | ||
104 | $LSwitchCmn: | ||
105 | ADD A0.2,D1Ar1,#TBICTX_DX+(8*5) | ||
106 | MGETL D0.5,D0.6,D0.7,[A0.2] /* Get caller-saved DX regs */ | ||
107 | $LSwitchExit: | ||
108 | GETL D0FrT,D1RtP,[A0FrP++] /* Restore state from frame */ | ||
109 | SUB A0StP,A0FrP,#8 /* Unwind stack */ | ||
110 | MOV A0FrP,D0FrT /* Last memory read completes */ | ||
111 | MOV PC,D1RtP /* Return to caller */ | ||
112 | .size ___TBISwitch,.-___TBISwitch | ||
113 | |||
114 | /* | ||
115 | * void __TBISyncResume( TBIRES State, int TrigMask ); | ||
116 | * | ||
117 | * This routine causes the TBICTX structure specified in State.Sig.pCtx to | ||
118 | * be restored. This implies that execution will not return to the caller. | ||
119 | * The State.Sig.TrigMask field will be ored into TXMASKI during the | ||
120 | * context switch such that any immediately occuring interrupts occur in | ||
121 | * the context of the newly specified task. The State.Sig.SaveMask parameter | ||
122 | * is ignored. | ||
123 | */ | ||
124 | .text | ||
125 | .balign 4 | ||
126 | .global ___TBISyncResume | ||
127 | .type ___TBISyncResume,function | ||
128 | ___TBISyncResume: | ||
129 | MOV D0Re0,D0Ar2 /* Result from args */ | ||
130 | MOV D1Re0,D1Ar1 | ||
131 | XOR D1Ar5,D1Ar5,D1Ar5 /* D1Ar5 = 0 */ | ||
132 | ADD D1RtP,D1Ar1,#TBICTX_AX | ||
133 | SWAP D1Ar5,TXMASKI /* D1Ar5 <-> TXMASKI */ | ||
134 | MGETL A0StP,A0FrP,[D1RtP] /* Get frame values */ | ||
135 | OR TXMASKI,D1Ar5,D1Ar3 /* New TXMASKI */ | ||
136 | B $LSwitchCmn | ||
137 | .size ___TBISyncResume,.-___TBISyncResume | ||
138 | |||
139 | /* | ||
140 | * void __TBIJump( TBIX64 ArgsA, TBIX32 ArgsB, int TrigsMask, | ||
141 | * void (*fnMain)(), void *pStack ); | ||
142 | * | ||
143 | * Jump directly to a new routine on an arbitrary stack with arbitrary args | ||
144 | * oring bits back into TXMASKI on route. | ||
145 | */ | ||
146 | .text | ||
147 | .balign 4 | ||
148 | .global ___TBIJump | ||
149 | .type ___TBIJump,function | ||
150 | ___TBIJump: | ||
151 | XOR D0Re0,D0Re0,D0Re0 /* D0Re0 = 0 */ | ||
152 | MOV A0StP,D0Ar6 /* Stack = Frame */ | ||
153 | SWAP D0Re0,TXMASKI /* D0Re0 <-> TXMASKI */ | ||
154 | MOV A0FrP,D0Ar6 | ||
155 | MOVT A1LbP,#HI(__exit) | ||
156 | ADD A1LbP,A1LbP,#LO(__exit) | ||
157 | MOV D1RtP,A1LbP /* D1RtP = __exit */ | ||
158 | OR TXMASKI,D0Re0,D0Ar4 /* New TXMASKI */ | ||
159 | MOV PC,D1Ar5 /* Jump to fnMain */ | ||
160 | .size ___TBIJump,.-___TBIJump | ||
161 | |||
162 | /* | ||
163 | * PTBICTX __TBISwitchInit( void *pStack, int (*fnMain)(), | ||
164 | * .... 4 extra 32-bit args .... ); | ||
165 | * | ||
166 | * Generate a new soft thread context ready for it's first outing. | ||
167 | * | ||
168 | * D1Ar1 - Region of memory to be used as the new soft thread stack | ||
169 | * D0Ar2 - Main line routine for new soft thread | ||
170 | * D1Ar3, D0Ar4, D1Ar5, D0Ar6 - arguments to be passed on stack | ||
171 | * The routine returns the initial PTBICTX value for the new thread | ||
172 | */ | ||
173 | .text | ||
174 | .balign 4 | ||
175 | .global ___TBISwitchInit | ||
176 | .type ___TBISwitchInit,function | ||
177 | ___TBISwitchInit: | ||
178 | MOV D0FrT,A0FrP /* Need save return point */ | ||
179 | ADD A0FrP,A0StP,#0 | ||
180 | SETL [A0StP++],D0FrT,D1RtP /* Save return to caller */ | ||
181 | MOVT A1LbP,#HI(__exit) | ||
182 | ADD A1LbP,A1LbP,#LO(__exit) | ||
183 | MOV D1RtP,A1LbP /* Get address of __exit */ | ||
184 | ADD D1Ar1,D1Ar1,#7 /* Align stack to 64-bits */ | ||
185 | ANDMB D1Ar1,D1Ar1,#0xfff8 /* by rounding base up */ | ||
186 | MOV A0.2,D1Ar1 /* A0.2 is new stack */ | ||
187 | MOV D0FrT,D1Ar1 /* Initial puesdo-frame pointer */ | ||
188 | SETL [A0.2++],D0FrT,D1RtP /* Save return to __exit */ | ||
189 | MOV D1RtP,D0Ar2 | ||
190 | SETL [A0.2++],D0FrT,D1RtP /* Save return to fnMain */ | ||
191 | ADD D0FrT,D0FrT,#8 /* Advance puesdo-frame pointer */ | ||
192 | MSETL [A0.2],D0Ar6,D0Ar4 /* Save extra initial args */ | ||
193 | MOVT D1RtP,#HI(___TBIStart) /* Start up code for new stack */ | ||
194 | ADD D1RtP,D1RtP,#LO(___TBIStart) | ||
195 | SETL [A0.2++],D0FrT,D1RtP /* Save return to ___TBIStart */ | ||
196 | ADD D0FrT,D0FrT,#(8*3) /* Advance puesdo-frame pointer */ | ||
197 | MOV D0Re0,A0.2 /* Return pCtx for new thread */ | ||
198 | MOV D1Re0,#0 /* pCtx:0 is default Arg1:Arg2 */ | ||
199 | /* | ||
200 | * Generate initial TBICTX state | ||
201 | */ | ||
202 | MOVT D1Ar1,#HI($LSwitchExit) /* Async restore code */ | ||
203 | ADD D1Ar1,D1Ar1,#LO($LSwitchExit) | ||
204 | MOVT D0Ar2,#TBICTX_SOFT_BIT /* Only soft thread state */ | ||
205 | ADD D0Ar6,A0.2,#TBICTX_BYTES /* New A0StP */ | ||
206 | MOV D1Ar5,A1GbP /* Same A1GbP */ | ||
207 | MOV D0Ar4,D0FrT /* Initial A0FrP */ | ||
208 | MOV D1Ar3,A1LbP /* Same A1LbP */ | ||
209 | SETL [A0.2++],D0Ar2,D1Ar1 /* Set header fields */ | ||
210 | MSETL [A0.2],D0Re0,D0Ar6,D0Ar4,D0Ar2,D0FrT,D0.5,D0.6,D0.7 | ||
211 | MOV D0Ar2,#0 /* Zero values */ | ||
212 | MOV D1Ar1,#0 | ||
213 | SETL [A0.2++],D0Ar2,D1Ar1 /* Zero CurrRPT, CurrBPOBITS, */ | ||
214 | SETL [A0.2++],D0Ar2,D1Ar1 /* CurrMODE, and pCurrCBuf */ | ||
215 | MSETL [A0.2],D0Ar6,D0Ar4,D0Ar2,D0FrT D0_5 /* Set DX and then AX regs */ | ||
216 | B $LSwitchExit /* All done! */ | ||
217 | .size ___TBISwitchInit,.-___TBISwitchInit | ||
218 | |||
219 | .text | ||
220 | .balign 4 | ||
221 | .global ___TBIStart | ||
222 | .type ___TBIStart,function | ||
223 | ___TBIStart: | ||
224 | MOV D1Ar1,D1Re0 /* Pass TBIRES args to call */ | ||
225 | MOV D0Ar2,D0Re0 | ||
226 | MGETL D0Re0,D0Ar6,D0Ar4,[A0FrP] /* Get hidden args */ | ||
227 | SUB A0StP,A0FrP,#(8*3) /* Entry stack pointer */ | ||
228 | MOV A0FrP,D0Re0 /* Entry frame pointer */ | ||
229 | MOVT A1LbP,#HI(__exit) | ||
230 | ADD A1LbP,A1LbP,#LO(__exit) | ||
231 | MOV D1RtP,A1LbP /* D1RtP = __exit */ | ||
232 | MOV PC,D1Re0 /* Jump into fnMain */ | ||
233 | .size ___TBIStart,.-___TBIStart | ||
234 | |||
235 | /* | ||
236 | * End of tbisoft.S | ||
237 | */ | ||
diff --git a/arch/metag/tbx/tbistring.c b/arch/metag/tbx/tbistring.c new file mode 100644 index 000000000000..f90cd0822065 --- /dev/null +++ b/arch/metag/tbx/tbistring.c | |||
@@ -0,0 +1,114 @@ | |||
1 | /* | ||
2 | * tbistring.c | ||
3 | * | ||
4 | * Copyright (C) 2001, 2002, 2003, 2005, 2007, 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 | * String table functions provided as part of the thread binary interface for | ||
11 | * Meta processors | ||
12 | */ | ||
13 | |||
14 | #include <linux/export.h> | ||
15 | #include <linux/string.h> | ||
16 | #include <asm/tbx.h> | ||
17 | |||
18 | /* | ||
19 | * There are not any functions to modify the string table currently, if these | ||
20 | * are required at some later point I suggest having a seperate module and | ||
21 | * ensuring that creating new entries does not interfere with reading old | ||
22 | * entries in any way. | ||
23 | */ | ||
24 | |||
25 | const TBISTR *__TBIFindStr(const TBISTR *start, | ||
26 | const char *str, int match_len) | ||
27 | { | ||
28 | const TBISTR *search = start; | ||
29 | bool exact = true; | ||
30 | const TBISEG *seg; | ||
31 | |||
32 | if (match_len < 0) { | ||
33 | /* Make match_len always positive for the inner loop */ | ||
34 | match_len = -match_len; | ||
35 | exact = false; | ||
36 | } else { | ||
37 | /* | ||
38 | * Also support historic behaviour, which expected match_len to | ||
39 | * include null terminator | ||
40 | */ | ||
41 | if (match_len && str[match_len-1] == '\0') | ||
42 | match_len--; | ||
43 | } | ||
44 | |||
45 | if (!search) { | ||
46 | /* Find global string table segment */ | ||
47 | seg = __TBIFindSeg(NULL, TBID_SEG(TBID_THREAD_GLOBAL, | ||
48 | TBID_SEGSCOPE_GLOBAL, | ||
49 | TBID_SEGTYPE_STRING)); | ||
50 | |||
51 | if (!seg || seg->Bytes < sizeof(TBISTR)) | ||
52 | /* No string table! */ | ||
53 | return NULL; | ||
54 | |||
55 | /* Start of string table */ | ||
56 | search = seg->pGAddr; | ||
57 | } | ||
58 | |||
59 | for (;;) { | ||
60 | while (!search->Tag) | ||
61 | /* Allow simple gaps which are just zero initialised */ | ||
62 | search = (const TBISTR *)((const char *)search + 8); | ||
63 | |||
64 | if (search->Tag == METAG_TBI_STRE) { | ||
65 | /* Reached the end of the table */ | ||
66 | search = NULL; | ||
67 | break; | ||
68 | } | ||
69 | |||
70 | if ((search->Len >= match_len) && | ||
71 | (!exact || (search->Len == match_len + 1)) && | ||
72 | (search->Tag != METAG_TBI_STRG)) { | ||
73 | /* Worth searching */ | ||
74 | if (!strncmp(str, (const char *)search->String, | ||
75 | match_len)) | ||
76 | break; | ||
77 | } | ||
78 | |||
79 | /* Next entry */ | ||
80 | search = (const TBISTR *)((const char *)search + search->Bytes); | ||
81 | } | ||
82 | |||
83 | return search; | ||
84 | } | ||
85 | |||
86 | const void *__TBITransStr(const char *str, int len) | ||
87 | { | ||
88 | const TBISTR *search = NULL; | ||
89 | const void *res = NULL; | ||
90 | |||
91 | for (;;) { | ||
92 | /* Search onwards */ | ||
93 | search = __TBIFindStr(search, str, len); | ||
94 | |||
95 | /* No translation returns NULL */ | ||
96 | if (!search) | ||
97 | break; | ||
98 | |||
99 | /* Skip matching entries with no translation data */ | ||
100 | if (search->TransLen != METAG_TBI_STRX) { | ||
101 | /* Calculate base of translation string */ | ||
102 | res = (const char *)search->String + | ||
103 | ((search->Len + 7) & ~7); | ||
104 | break; | ||
105 | } | ||
106 | |||
107 | /* Next entry */ | ||
108 | search = (const TBISTR *)((const char *)search + search->Bytes); | ||
109 | } | ||
110 | |||
111 | /* Return base address of translation data or NULL */ | ||
112 | return res; | ||
113 | } | ||
114 | EXPORT_SYMBOL(__TBITransStr); | ||
diff --git a/arch/metag/tbx/tbitimer.S b/arch/metag/tbx/tbitimer.S new file mode 100644 index 000000000000..5dbeddeee7ba --- /dev/null +++ b/arch/metag/tbx/tbitimer.S | |||
@@ -0,0 +1,207 @@ | |||
1 | /* | ||
2 | * tbitimer.S | ||
3 | * | ||
4 | * Copyright (C) 2001, 2002, 2007, 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 | * TBI timer support routines and data values | ||
11 | */ | ||
12 | |||
13 | .file "tbitimer.S" | ||
14 | /* | ||
15 | * Get data structures and defines from the main C header | ||
16 | */ | ||
17 | #include <asm/tbx.h> | ||
18 | |||
19 | .data | ||
20 | .balign 8 | ||
21 | .global ___TBITimeB | ||
22 | .type ___TBITimeB,object | ||
23 | ___TBITimeB: | ||
24 | .quad 0 /* Background 'lost' ticks */ | ||
25 | .size ___TBITimeB,.-___TBITimeB | ||
26 | |||
27 | .data | ||
28 | .balign 8 | ||
29 | .global ___TBITimeI | ||
30 | .type ___TBITimeI,object | ||
31 | ___TBITimeI: | ||
32 | .quad 0 /* Interrupt 'lost' ticks */ | ||
33 | .size ___TBITimeI,.-___TBITimeI | ||
34 | |||
35 | .data | ||
36 | .balign 8 | ||
37 | .global ___TBITimes | ||
38 | .type ___TBITimes,object | ||
39 | ___TBITimes: | ||
40 | .long ___TBITimeB /* Table of 'lost' tick values */ | ||
41 | .long ___TBITimeI | ||
42 | .size ___TBITimes,.-___TBITimes | ||
43 | |||
44 | /* | ||
45 | * Flag bits for control of ___TBITimeCore | ||
46 | */ | ||
47 | #define TIMER_SET_BIT 1 | ||
48 | #define TIMER_ADD_BIT 2 | ||
49 | |||
50 | /* | ||
51 | * Initialise or stop timer support | ||
52 | * | ||
53 | * Register Usage: D1Ar1 holds Id, D1Ar2 is initial delay or 0 | ||
54 | * D0FrT is used to call ___TBITimeCore | ||
55 | * D0Re0 is used for the result which is TXSTAT_TIMER_BIT | ||
56 | * D0Ar4, D1Ar5, D0Ar6 are all used as scratch | ||
57 | * Other registers are those set by ___TBITimeCore | ||
58 | * A0.3 is assumed to point at ___TBITime(I/B) | ||
59 | */ | ||
60 | .text | ||
61 | .balign 4 | ||
62 | .global ___TBITimerCtrl | ||
63 | .type ___TBITimerCtrl,function | ||
64 | ___TBITimerCtrl: | ||
65 | MOV D1Ar5,#TIMER_SET_BIT /* Timer SET request */ | ||
66 | MOVT D0FrT,#HI(___TBITimeCore) /* Get timer core reg values */ | ||
67 | CALL D0FrT,#LO(___TBITimeCore) /* and perform register update */ | ||
68 | NEGS D0Ar6,D0Ar2 /* Set flags from time-stamp */ | ||
69 | ASR D1Ar5,D0Ar6,#31 /* Sign extend D0Ar6 into D1Ar5 */ | ||
70 | SETLNZ [A0.3],D0Ar6,D1Ar5 /* ___TBITime(B/I)=-Start if enable */ | ||
71 | MOV PC,D1RtP /* Return */ | ||
72 | .size ___TBITimerCtrl,.-___TBITimerCtrl | ||
73 | |||
74 | /* | ||
75 | * Return ___TBITimeStamp value | ||
76 | * | ||
77 | * Register Usage: D1Ar1 holds Id | ||
78 | * D0FrT is used to call ___TBITimeCore | ||
79 | * D0Re0, D1Re0 is used for the result | ||
80 | * D1Ar3, D0Ar4, D1Ar5 | ||
81 | * Other registers are those set by ___TBITimeCore | ||
82 | * D0Ar6 is assumed to be the timer value read | ||
83 | * A0.3 is assumed to point at ___TBITime(I/B) | ||
84 | */ | ||
85 | .text | ||
86 | .balign 4 | ||
87 | .global ___TBITimeStamp | ||
88 | .type ___TBITimeStamp,function | ||
89 | ___TBITimeStamp: | ||
90 | MOV D1Ar5,#0 /* Timer GET request */ | ||
91 | MOVT D0FrT,#HI(___TBITimeCore) /* Get timer core reg values */ | ||
92 | CALL D0FrT,#LO(___TBITimeCore) /* with no register update */ | ||
93 | ADDS D0Re0,D0Ar4,D0Ar6 /* Add current time value */ | ||
94 | ADD D1Re0,D1Ar3,D1Ar5 /* to 64-bit signed extend time */ | ||
95 | ADDCS D1Re0,D1Re0,#1 /* Support borrow too */ | ||
96 | MOV PC,D1RtP /* Return */ | ||
97 | .size ___TBITimeStamp,.-___TBITimeStamp | ||
98 | |||
99 | /* | ||
100 | * Perform ___TBITimerAdd logic | ||
101 | * | ||
102 | * Register Usage: D1Ar1 holds Id, D0Ar2 holds value to be added to the timer | ||
103 | * D0Re0 is used for the result - new TIMER value | ||
104 | * D1Ar5, D0Ar6 are used as scratch | ||
105 | * Other registers are those set by ___TBITimeCore | ||
106 | * D0Ar6 is assumed to be the timer value read | ||
107 | * D0Ar4, D1Ar3 is the current value of ___TBITime(B/I) | ||
108 | */ | ||
109 | .text | ||
110 | .balign 4 | ||
111 | .global ___TBITimerAdd | ||
112 | .type ___TBITimerAdd,function | ||
113 | ___TBITimerAdd: | ||
114 | MOV D1Ar5,#TIMER_ADD_BIT /* Timer ADD request */ | ||
115 | MOVT D0FrT,#HI(___TBITimeCore) /* Get timer core reg values */ | ||
116 | CALL D0FrT,#LO(___TBITimeCore) /* with no register update */ | ||
117 | ADD D0Re0,D0Ar2,D0Ar6 /* Regenerate new value = result */ | ||
118 | NEG D0Ar2,D0Ar2 /* Negate delta */ | ||
119 | ASR D1Re0,D0Ar2,#31 /* Sign extend negated delta */ | ||
120 | ADDS D0Ar4,D0Ar4,D0Ar2 /* Add time added to ... */ | ||
121 | ADD D1Ar3,D1Ar3,D1Re0 /* ... real timer ... */ | ||
122 | ADDCS D1Ar3,D1Ar3,#1 /* ... with carry */ | ||
123 | SETL [A0.3],D0Ar4,D1Ar3 /* Update ___TBITime(B/I) */ | ||
124 | MOV PC,D1RtP /* Return */ | ||
125 | .size ___TBITimerAdd,.-___TBITimerAdd | ||
126 | |||
127 | #ifdef TBI_1_4 | ||
128 | /* | ||
129 | * Perform ___TBITimerDeadline logic | ||
130 | * NB: Delays are positive compared to the Wait values which are -ive | ||
131 | * | ||
132 | * Register Usage: D1Ar1 holds Id | ||
133 | * D0Ar2 holds Delay requested | ||
134 | * D0Re0 is used for the result - old TIMER Delay value | ||
135 | * D1Ar5, D0Ar6 are used as scratch | ||
136 | * Other registers are those set by ___TBITimeCore | ||
137 | * D0Ar6 is assumed to be the timer value read | ||
138 | * D0Ar4, D1Ar3 is the current value of ___TBITime(B/I) | ||
139 | * | ||
140 | */ | ||
141 | .text | ||
142 | .type ___TBITimerDeadline,function | ||
143 | .global ___TBITimerDeadline | ||
144 | .align 2 | ||
145 | ___TBITimerDeadline: | ||
146 | MOV D1Ar5,#TIMER_SET_BIT /* Timer SET request */ | ||
147 | MOVT D0FrT,#HI(___TBITimeCore) /* Get timer core reg values */ | ||
148 | CALL D0FrT,#LO(___TBITimeCore) /* with no register update */ | ||
149 | MOV D0Re0,D0Ar6 /* Old value read = result */ | ||
150 | SUB D0Ar2,D0Ar6,D0Ar2 /* Delta from (old - new) */ | ||
151 | ASR D1Re0,D0Ar2,#31 /* Sign extend delta */ | ||
152 | ADDS D0Ar4,D0Ar4,D0Ar2 /* Add time added to ... */ | ||
153 | ADD D1Ar3,D1Ar3,D1Re0 /* ... real timer ... */ | ||
154 | ADDCS D1Ar3,D1Ar3,#1 /* ... with carry */ | ||
155 | SETL [A0.3],D0Ar4,D1Ar3 /* Update ___TBITime(B/I) */ | ||
156 | MOV PC,D1RtP /* Return */ | ||
157 | .size ___TBITimerDeadline,.-___TBITimerDeadline | ||
158 | #endif /* TBI_1_4 */ | ||
159 | |||
160 | /* | ||
161 | * Perform core timer access logic | ||
162 | * | ||
163 | * Register Usage: D1Ar1 holds Id, D0Ar2 holds input value for SET and | ||
164 | * input value for ADD | ||
165 | * D1Ar5 controls op as SET or ADD as bit values | ||
166 | * On return D0Ar6, D1Ar5 holds the old 64-bit timer value | ||
167 | * A0.3 is setup to point at ___TBITime(I/B) | ||
168 | * A1.3 is setup to point at ___TBITimes | ||
169 | * D0Ar4, D1Ar3 is setup to value of ___TBITime(I/B) | ||
170 | */ | ||
171 | .text | ||
172 | .balign 4 | ||
173 | .global ___TBITimeCore | ||
174 | .type ___TBITimeCore,function | ||
175 | ___TBITimeCore: | ||
176 | #ifndef METAC_0_1 | ||
177 | TSTT D1Ar1,#HI(TBID_ISTAT_BIT) /* Interrupt level timer? */ | ||
178 | #endif | ||
179 | MOVT A1LbP,#HI(___TBITimes) | ||
180 | ADD A1LbP,A1LbP,#LO(___TBITimes) | ||
181 | MOV A1.3,A1LbP /* Get ___TBITimes address */ | ||
182 | #ifndef METAC_0_1 | ||
183 | BNZ $LTimeCoreI /* Yes: Service TXTIMERI! */ | ||
184 | #endif | ||
185 | LSRS D1Ar5,D1Ar5,#1 /* Carry = SET, Zero = !ADD */ | ||
186 | GETD A0.3,[A1.3+#0] /* A0.3 == &___TBITimeB */ | ||
187 | MOV D0Ar6,TXTIMER /* Always GET old value */ | ||
188 | MOVCS TXTIMER,D0Ar2 /* Conditional SET operation */ | ||
189 | ADDNZ TXTIMER,D0Ar2,D0Ar6 /* Conditional ADD operation */ | ||
190 | #ifndef METAC_0_1 | ||
191 | B $LTimeCoreEnd | ||
192 | $LTimeCoreI: | ||
193 | LSRS D1Ar5,D1Ar5,#1 /* Carry = SET, Zero = !ADD */ | ||
194 | GETD A0.3,[A1.3+#4] /* A0.3 == &___TBITimeI */ | ||
195 | MOV D0Ar6,TXTIMERI /* Always GET old value */ | ||
196 | MOVCS TXTIMERI,D0Ar2 /* Conditional SET operation */ | ||
197 | ADDNZ TXTIMERI,D0Ar2,D0Ar6 /* Conditional ADD operation */ | ||
198 | $LTimeCoreEnd: | ||
199 | #endif | ||
200 | ASR D1Ar5,D0Ar6,#31 /* Sign extend D0Ar6 into D1Ar5 */ | ||
201 | GETL D0Ar4,D1Ar3,[A0.3] /* Read ___TBITime(B/I) */ | ||
202 | MOV PC,D0FrT /* Return quickly */ | ||
203 | .size ___TBITimeCore,.-___TBITimeCore | ||
204 | |||
205 | /* | ||
206 | * End of tbitimer.S | ||
207 | */ | ||