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 // space for "extra" (user special registers and non-coprocessor TIE) state:
33 const unsigned int Xthal_extra_size = XCHAL_NCP_SA_SIZE;
34 
35 const unsigned int Xthal_extra_align = XCHAL_NCP_SA_ALIGN;
36 
37 // space for state of TIE coprocessors:
38 const unsigned int Xthal_cpregs_size[8] =
39 	{
40 	    XCHAL_CP0_SA_SIZE,
41 	    XCHAL_CP1_SA_SIZE,
42 	    XCHAL_CP2_SA_SIZE,
43 	    XCHAL_CP3_SA_SIZE,
44 	    XCHAL_CP4_SA_SIZE,
45 	    XCHAL_CP5_SA_SIZE,
46 	    XCHAL_CP6_SA_SIZE,
47 	    XCHAL_CP7_SA_SIZE
48 	};
49 
50 const unsigned int Xthal_cpregs_align[8] =
51 	{
52 	    XCHAL_CP0_SA_ALIGN,
53 	    XCHAL_CP1_SA_ALIGN,
54 	    XCHAL_CP2_SA_ALIGN,
55 	    XCHAL_CP3_SA_ALIGN,
56 	    XCHAL_CP4_SA_ALIGN,
57 	    XCHAL_CP5_SA_ALIGN,
58 	    XCHAL_CP6_SA_ALIGN,
59 	    XCHAL_CP7_SA_ALIGN
60 	};
61 
62 const char * const Xthal_cp_names[8] =
63 	{
64 	    XCHAL_CP0_NAME,
65 	    XCHAL_CP1_NAME,
66 	    XCHAL_CP2_NAME,
67 	    XCHAL_CP3_NAME,
68 	    XCHAL_CP4_NAME,
69 	    XCHAL_CP5_NAME,
70 	    XCHAL_CP6_NAME,
71 	    XCHAL_CP7_NAME
72 	};
73 
74 // total save area size (extra + all coprocessors + min 16-byte alignment everywhere)
75 const unsigned int Xthal_all_extra_size = XCHAL_TOTAL_SA_SIZE;
76 
77 // maximum required alignment for the total save area (this might be useful):
78 const unsigned int Xthal_all_extra_align = XCHAL_TOTAL_SA_ALIGN;
79 
80 // number of coprocessors starting contiguously from zero
81 // (same as Xthal_cp_max, but included for Tornado2):
82 const unsigned int Xthal_num_coprocessors = XCHAL_CP_MAX;
83 
84 // actual number of coprocessors:
85 const unsigned char Xthal_cp_num    = XCHAL_CP_NUM;
86 
87 // index of highest numbered coprocessor, plus one:
88 const unsigned char Xthal_cp_max    = XCHAL_CP_MAX;
89 
90 // index of highest allowed coprocessor number, per cfg, plus one:
91 //const unsigned char Xthal_cp_maxcfg = XCHAL_CP_MAXCFG;
92 
93 // bitmask of which coprocessors are present:
94 const unsigned int  Xthal_cp_mask   = XCHAL_CP_MASK;
95 
96 // Coprocessor ID from its name
97 
98 # ifdef XCHAL_CP0_IDENT
99 const unsigned char XCJOIN(Xthal_cp_id_,XCHAL_CP0_IDENT) = 0;
100 # endif
101 # ifdef XCHAL_CP1_IDENT
102 const unsigned char XCJOIN(Xthal_cp_id_,XCHAL_CP1_IDENT) = 1;
103 # endif
104 # ifdef XCHAL_CP2_IDENT
105 const unsigned char XCJOIN(Xthal_cp_id_,XCHAL_CP2_IDENT) = 2;
106 # endif
107 # ifdef XCHAL_CP3_IDENT
108 const unsigned char XCJOIN(Xthal_cp_id_,XCHAL_CP3_IDENT) = 3;
109 # endif
110 # ifdef XCHAL_CP4_IDENT
111 const unsigned char XCJOIN(Xthal_cp_id_,XCHAL_CP4_IDENT) = 4;
112 # endif
113 # ifdef XCHAL_CP5_IDENT
114 const unsigned char XCJOIN(Xthal_cp_id_,XCHAL_CP5_IDENT) = 5;
115 # endif
116 # ifdef XCHAL_CP6_IDENT
117 const unsigned char XCJOIN(Xthal_cp_id_,XCHAL_CP6_IDENT) = 6;
118 # endif
119 # ifdef XCHAL_CP7_IDENT
120 const unsigned char XCJOIN(Xthal_cp_id_,XCHAL_CP7_IDENT) = 7;
121 # endif
122 
123 // Coprocessor "mask" (1 << ID) from its name
124 
125 # ifdef XCHAL_CP0_IDENT
126 const unsigned int  XCJOIN(Xthal_cp_mask_,XCHAL_CP0_IDENT) = (1 << 0);
127 # endif
128 # ifdef XCHAL_CP1_IDENT
129 const unsigned int  XCJOIN(Xthal_cp_mask_,XCHAL_CP1_IDENT) = (1 << 1);
130 # endif
131 # ifdef XCHAL_CP2_IDENT
132 const unsigned int  XCJOIN(Xthal_cp_mask_,XCHAL_CP2_IDENT) = (1 << 2);
133 # endif
134 # ifdef XCHAL_CP3_IDENT
135 const unsigned int  XCJOIN(Xthal_cp_mask_,XCHAL_CP3_IDENT) = (1 << 3);
136 # endif
137 # ifdef XCHAL_CP4_IDENT
138 const unsigned int  XCJOIN(Xthal_cp_mask_,XCHAL_CP4_IDENT) = (1 << 4);
139 # endif
140 # ifdef XCHAL_CP5_IDENT
141 const unsigned int  XCJOIN(Xthal_cp_mask_,XCHAL_CP5_IDENT) = (1 << 5);
142 # endif
143 # ifdef XCHAL_CP6_IDENT
144 const unsigned int  XCJOIN(Xthal_cp_mask_,XCHAL_CP6_IDENT) = (1 << 6);
145 # endif
146 # ifdef XCHAL_CP7_IDENT
147 const unsigned int  XCJOIN(Xthal_cp_mask_,XCHAL_CP7_IDENT) = (1 << 7);
148 # endif
149 
150 //----------------------------------------------------------------------
151 
152 // CMS: I have made the assumptions that 0's are safe initial
153 // values. That may be wrong at some point.
154 //
155 // initialize the extra processor
156 void
xthal_init_mem_extra(void * address)157 xthal_init_mem_extra(void *address)
158 /* not clear that it is safe to call memcpy and also not clear
159    that performance is important. */
160 {
161     unsigned int *ptr;
162     unsigned int *end;
163 
164     ptr = (unsigned int *)address;
165     end = (unsigned int *)((int)address + XCHAL_NCP_SA_SIZE);
166     while( ptr < end )
167     {
168 	*ptr++ = 0;
169     }
170 }
171 
172 // initialize the TIE coprocessor
173 void
xthal_init_mem_cp(void * address,int cp)174 xthal_init_mem_cp(void *address, int cp)
175 {
176     unsigned int *ptr;
177     unsigned int *end;
178 
179     if( cp <= 7 )
180     {
181 	end = (unsigned int *)((int)address + Xthal_cpregs_size[cp]);
182 	ptr = (unsigned int *)address;
183 	while( ptr < end )
184 	{
185 	    *ptr++ = 0;
186 	}
187     }
188 }
189 
190 
191 
192 /*  Nothing implemented below this point.  */
193 /************************************************************************/
194 
195 // save all extra+cp processor state (NOT IMPLEMENTED)
196 /*void xthal_save_all_extra(void *base)
197 {
198     xthal_save_extra(base);
199     ... here we need to iterate over configured coprocessor register files ...
200 //    xthal_save_cpregs(base+XCHAL_NCP_SA_SIZE, 0);
201 }*/
202 
203 // restore all extra+cp processor state (NOT IMPLEMENTED)
204 /*void xthal_restore_all_extra(void *base)
205 {
206     xthal_restore_extra(base);
207     ... here we need to iterate over configured coprocessor register files ...
208 //    xthal_restore_cpregs(base+XCHAL_NCP_SA_SIZE, 0);
209 }*/
210 
211 
212 // initialize the extra processor (NOT IMPLEMENTED)
213 /*void xthal_init_extra()
214 {
215 }*/
216 
217 // initialize the TIE coprocessor (NOT IMPLEMENTED)
218 /*void xthal_init_cp(int cp)
219 {
220 }*/
221 
222 
223 #if 0
224 
225 /* read extra state register (NOT IMPLEMENTED) */
226 int xthal_read_extra(void *base, unsigned reg, unsigned *value)
227 {
228 	if (reg&0x1000) {
229 		switch(reg) {
230 #if XCHAL_HAVE_MAC16
231 			case 16:
232 				*value = ((unsigned *)base)[0];
233 				return reg;
234 			case 17:
235 				*value = ((unsigned *)base)[1];
236 				return reg;
237 			case 32:
238 				*value = ((unsigned *)base)[2];
239 				return reg;
240 			case 33:
241 				*value = ((unsigned *)base)[3];
242 				return reg;
243 			case 34:
244 				*value = ((unsigned *)base)[4];
245 				return reg;
246 			case 35:
247 				*value = ((unsigned *)base)[5];
248 				return reg;
249 #endif /* XCHAL_HAVE_MAC16 */
250 		}
251 	}
252 	return -1;
253 }
254 
255 /* write extra state register (NOT IMPLEMENTED) */
256 int xthal_write_extra(void *base, unsigned reg, unsigned value)
257 {
258 	if (reg&0x1000) {
259 	    switch(reg) {
260 #if XCHAL_HAVE_MAC16
261 			case 16:
262 				((unsigned *)base)[0] = value;
263 				return reg;
264 			case 17:
265 				((unsigned *)base)[1] = value;
266 				return reg;
267 			case 32:
268 				((unsigned *)base)[2] = value;
269 				return reg;
270 			case 33:
271 				((unsigned *)base)[3] = value;
272 				return reg;
273 			case 34:
274 				((unsigned *)base)[4] = value;
275 				return reg;
276 			case 35:
277 				((unsigned *)base)[5] = value;
278 				return reg;
279 #endif /* XCHAL_HAVE_MAC16 */
280 		}
281 	}
282 	return -1;
283 }
284 
285 #endif /*0*/
286 
287 
288 /* read TIE coprocessor register (NOT IMPLEMENTED) */
289 /*int xthal_read_cpreg(void *base, int cp, unsigned reg, unsigned *value)
290 {
291     return -1;
292 }*/
293 
294 /* write TIE coproessor register (NOT IMPLEMENTED) */
295 /*int xthal_write_cpreg(void *base, int cp, unsigned reg, unsigned value)
296 {
297 	return -1;
298 }*/
299 
300 /* return coprocessor number based on register (NOT IMPLEMENTED) */
301 /*int xthal_which_cp(unsigned reg)
302 {
303 	return -1;
304 }*/
305 
306