1 //
2 // processor_state.c - processor state management routines
3 //
4 
5 // Copyright (c) 2005-2010 Tensilica Inc.
6 //
7 // Permission is hereby granted, free of charge, to any person obtaining
8 // a copy of this software and associated documentation files (the
9 // "Software"), to deal in the Software without restriction, including
10 // without limitation the rights to use, copy, modify, merge, publish,
11 // distribute, sublicense, and/or sell copies of the Software, and to
12 // permit persons to whom the Software is furnished to do so, subject to
13 // the following conditions:
14 //
15 // The above copyright notice and this permission notice shall be included
16 // in all copies or substantial portions of the Software.
17 //
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 
26 #include <xtensa/hal.h>
27 #include <xtensa/config/core.h>
28 
29 
30 //----------------------------------------------------------------------
31 
32 #if defined(__SPLIT__extra_size)
33 // space for "extra" (user special registers and non-coprocessor TIE) state:
34 const unsigned int Xthal_extra_size = XCHAL_NCP_SA_SIZE;
35 
36 #elif defined(__SPLIT__extra_align)
37 const unsigned int Xthal_extra_align = XCHAL_NCP_SA_ALIGN;
38 
39 #elif defined(__SPLIT__cpregs_size)
40 // space for state of TIE coprocessors:
41 const unsigned int Xthal_cpregs_size[8] =
42 	{
43 	    XCHAL_CP0_SA_SIZE,
44 	    XCHAL_CP1_SA_SIZE,
45 	    XCHAL_CP2_SA_SIZE,
46 	    XCHAL_CP3_SA_SIZE,
47 	    XCHAL_CP4_SA_SIZE,
48 	    XCHAL_CP5_SA_SIZE,
49 	    XCHAL_CP6_SA_SIZE,
50 	    XCHAL_CP7_SA_SIZE
51 	};
52 
53 #elif defined(__SPLIT__cpregs_align)
54 const unsigned int Xthal_cpregs_align[8] =
55 	{
56 	    XCHAL_CP0_SA_ALIGN,
57 	    XCHAL_CP1_SA_ALIGN,
58 	    XCHAL_CP2_SA_ALIGN,
59 	    XCHAL_CP3_SA_ALIGN,
60 	    XCHAL_CP4_SA_ALIGN,
61 	    XCHAL_CP5_SA_ALIGN,
62 	    XCHAL_CP6_SA_ALIGN,
63 	    XCHAL_CP7_SA_ALIGN
64 	};
65 
66 #elif defined(__SPLIT__cp_names)
67 const char * const Xthal_cp_names[8] =
68 	{
69 	    XCHAL_CP0_NAME,
70 	    XCHAL_CP1_NAME,
71 	    XCHAL_CP2_NAME,
72 	    XCHAL_CP3_NAME,
73 	    XCHAL_CP4_NAME,
74 	    XCHAL_CP5_NAME,
75 	    XCHAL_CP6_NAME,
76 	    XCHAL_CP7_NAME
77 	};
78 
79 #elif defined(__SPLIT__all_extra_size)
80 // total save area size (extra + all coprocessors + min 16-byte alignment everywhere)
81 const unsigned int Xthal_all_extra_size = XCHAL_TOTAL_SA_SIZE;
82 
83 #elif defined(__SPLIT__all_extra_align)
84 // maximum required alignment for the total save area (this might be useful):
85 const unsigned int Xthal_all_extra_align = XCHAL_TOTAL_SA_ALIGN;
86 
87 #elif defined(__SPLIT__num_coprocessors)
88 // number of coprocessors starting contiguously from zero
89 // (same as Xthal_cp_max, but included for Tornado2):
90 const unsigned int Xthal_num_coprocessors = XCHAL_CP_MAX;
91 
92 #elif defined(__SPLIT__cp_num)
93 // actual number of coprocessors:
94 const unsigned char Xthal_cp_num    = XCHAL_CP_NUM;
95 
96 #elif defined(__SPLIT__cp_max)
97 // index of highest numbered coprocessor, plus one:
98 const unsigned char Xthal_cp_max    = XCHAL_CP_MAX;
99 
100 // index of highest allowed coprocessor number, per cfg, plus one:
101 //const unsigned char Xthal_cp_maxcfg = XCHAL_CP_MAXCFG;
102 
103 #elif defined(__SPLIT__cp_mask)
104 // bitmask of which coprocessors are present:
105 const unsigned int  Xthal_cp_mask   = XCHAL_CP_MASK;
106 
107 #elif defined(__SPLIT__cp_id_mappings)
108 // Coprocessor ID from its name
109 
110 # ifdef XCHAL_CP0_IDENT
111 const unsigned char XCJOIN(Xthal_cp_id_,XCHAL_CP0_IDENT) = 0;
112 # endif
113 # ifdef XCHAL_CP1_IDENT
114 const unsigned char XCJOIN(Xthal_cp_id_,XCHAL_CP1_IDENT) = 1;
115 # endif
116 # ifdef XCHAL_CP2_IDENT
117 const unsigned char XCJOIN(Xthal_cp_id_,XCHAL_CP2_IDENT) = 2;
118 # endif
119 # ifdef XCHAL_CP3_IDENT
120 const unsigned char XCJOIN(Xthal_cp_id_,XCHAL_CP3_IDENT) = 3;
121 # endif
122 # ifdef XCHAL_CP4_IDENT
123 const unsigned char XCJOIN(Xthal_cp_id_,XCHAL_CP4_IDENT) = 4;
124 # endif
125 # ifdef XCHAL_CP5_IDENT
126 const unsigned char XCJOIN(Xthal_cp_id_,XCHAL_CP5_IDENT) = 5;
127 # endif
128 # ifdef XCHAL_CP6_IDENT
129 const unsigned char XCJOIN(Xthal_cp_id_,XCHAL_CP6_IDENT) = 6;
130 # endif
131 # ifdef XCHAL_CP7_IDENT
132 const unsigned char XCJOIN(Xthal_cp_id_,XCHAL_CP7_IDENT) = 7;
133 # endif
134 
135 #elif defined(__SPLIT__cp_mask_mappings)
136 // Coprocessor "mask" (1 << ID) from its name
137 
138 # ifdef XCHAL_CP0_IDENT
139 const unsigned int  XCJOIN(Xthal_cp_mask_,XCHAL_CP0_IDENT) = (1 << 0);
140 # endif
141 # ifdef XCHAL_CP1_IDENT
142 const unsigned int  XCJOIN(Xthal_cp_mask_,XCHAL_CP1_IDENT) = (1 << 1);
143 # endif
144 # ifdef XCHAL_CP2_IDENT
145 const unsigned int  XCJOIN(Xthal_cp_mask_,XCHAL_CP2_IDENT) = (1 << 2);
146 # endif
147 # ifdef XCHAL_CP3_IDENT
148 const unsigned int  XCJOIN(Xthal_cp_mask_,XCHAL_CP3_IDENT) = (1 << 3);
149 # endif
150 # ifdef XCHAL_CP4_IDENT
151 const unsigned int  XCJOIN(Xthal_cp_mask_,XCHAL_CP4_IDENT) = (1 << 4);
152 # endif
153 # ifdef XCHAL_CP5_IDENT
154 const unsigned int  XCJOIN(Xthal_cp_mask_,XCHAL_CP5_IDENT) = (1 << 5);
155 # endif
156 # ifdef XCHAL_CP6_IDENT
157 const unsigned int  XCJOIN(Xthal_cp_mask_,XCHAL_CP6_IDENT) = (1 << 6);
158 # endif
159 # ifdef XCHAL_CP7_IDENT
160 const unsigned int  XCJOIN(Xthal_cp_mask_,XCHAL_CP7_IDENT) = (1 << 7);
161 # endif
162 
163 //----------------------------------------------------------------------
164 
165 #elif defined(__SPLIT__init_mem_extra)
166 // CMS: I have made the assumptions that 0's are safe initial
167 // values. That may be wrong at some point.
168 //
169 // initialize the extra processor
170 void
xthal_init_mem_extra(void * address)171 xthal_init_mem_extra(void *address)
172 /* not clear that it is safe to call memcpy and also not clear
173    that performance is important. */
174 {
175     unsigned int *ptr;
176     unsigned int *end;
177 
178     ptr = (unsigned int *)address;
179     end = (unsigned int *)((int)address + XCHAL_NCP_SA_SIZE);
180     while( ptr < end )
181     {
182 	*ptr++ = 0;
183     }
184 }
185 
186 #elif defined(__SPLIT__init_mem_cp)
187 // initialize the TIE coprocessor
188 void
xthal_init_mem_cp(void * address,int cp)189 xthal_init_mem_cp(void *address, int cp)
190 {
191     unsigned int *ptr;
192     unsigned int *end;
193 
194     if( cp <= 7 )
195     {
196 	end = (unsigned int *)((int)address + Xthal_cpregs_size[cp]);
197 	ptr = (unsigned int *)address;
198 	while( ptr < end )
199 	{
200 	    *ptr++ = 0;
201 	}
202     }
203 }
204 
205 #endif /*splitting*/
206 
207 
208 /*  Nothing implemented below this point.  */
209 /************************************************************************/
210 
211 // save all extra+cp processor state (NOT IMPLEMENTED)
212 /*void xthal_save_all_extra(void *base)
213 {
214     xthal_save_extra(base);
215     ... here we need to iterate over configured coprocessor register files ...
216 //    xthal_save_cpregs(base+XCHAL_NCP_SA_SIZE, 0);
217 }*/
218 
219 // restore all extra+cp processor state (NOT IMPLEMENTED)
220 /*void xthal_restore_all_extra(void *base)
221 {
222     xthal_restore_extra(base);
223     ... here we need to iterate over configured coprocessor register files ...
224 //    xthal_restore_cpregs(base+XCHAL_NCP_SA_SIZE, 0);
225 }*/
226 
227 
228 // initialize the extra processor (NOT IMPLEMENTED)
229 /*void xthal_init_extra()
230 {
231 }*/
232 
233 // initialize the TIE coprocessor (NOT IMPLEMENTED)
234 /*void xthal_init_cp(int cp)
235 {
236 }*/
237 
238 
239 #if 0
240 
241 /* read extra state register (NOT IMPLEMENTED) */
242 int xthal_read_extra(void *base, unsigned reg, unsigned *value)
243 {
244 	if (reg&0x1000) {
245 		switch(reg) {
246 #if XCHAL_HAVE_MAC16
247 			case 16:
248 				*value = ((unsigned *)base)[0];
249 				return reg;
250 			case 17:
251 				*value = ((unsigned *)base)[1];
252 				return reg;
253 			case 32:
254 				*value = ((unsigned *)base)[2];
255 				return reg;
256 			case 33:
257 				*value = ((unsigned *)base)[3];
258 				return reg;
259 			case 34:
260 				*value = ((unsigned *)base)[4];
261 				return reg;
262 			case 35:
263 				*value = ((unsigned *)base)[5];
264 				return reg;
265 #endif /* XCHAL_HAVE_MAC16 */
266 		}
267 	}
268 	return -1;
269 }
270 
271 /* write extra state register (NOT IMPLEMENTED) */
272 int xthal_write_extra(void *base, unsigned reg, unsigned value)
273 {
274 	if (reg&0x1000) {
275 	    switch(reg) {
276 #if XCHAL_HAVE_MAC16
277 			case 16:
278 				((unsigned *)base)[0] = value;
279 				return reg;
280 			case 17:
281 				((unsigned *)base)[1] = value;
282 				return reg;
283 			case 32:
284 				((unsigned *)base)[2] = value;
285 				return reg;
286 			case 33:
287 				((unsigned *)base)[3] = value;
288 				return reg;
289 			case 34:
290 				((unsigned *)base)[4] = value;
291 				return reg;
292 			case 35:
293 				((unsigned *)base)[5] = value;
294 				return reg;
295 #endif /* XCHAL_HAVE_MAC16 */
296 		}
297 	}
298 	return -1;
299 }
300 
301 #endif /*0*/
302 
303 
304 /* read TIE coprocessor register (NOT IMPLEMENTED) */
305 /*int xthal_read_cpreg(void *base, int cp, unsigned reg, unsigned *value)
306 {
307     return -1;
308 }*/
309 
310 /* write TIE coproessor register (NOT IMPLEMENTED) */
311 /*int xthal_write_cpreg(void *base, int cp, unsigned reg, unsigned value)
312 {
313 	return -1;
314 }*/
315 
316 /* return coprocessor number based on register (NOT IMPLEMENTED) */
317 /*int xthal_which_cp(unsigned reg)
318 {
319 	return -1;
320 }*/
321 
322