1 //
2 // debug.c - debug related constants and functions
3 //
4 // $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/hal/debug.c#1 $
5 
6 // Copyright (c) 2002 Tensilica Inc.
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining
9 // a copy of this software and associated documentation files (the
10 // "Software"), to deal in the Software without restriction, including
11 // without limitation the rights to use, copy, modify, merge, publish,
12 // distribute, sublicense, and/or sell copies of the Software, and to
13 // permit persons to whom the Software is furnished to do so, subject to
14 // the following conditions:
15 //
16 // The above copyright notice and this permission notice shall be included
17 // in all copies or substantial portions of the Software.
18 //
19 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
23 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 
27 #include <xtensa/hal.h>
28 #include <xtensa/config/core.h>
29 
30 
31 /*  1 if debug option configured, 0 if not:  */
32 const int Xthal_debug_configured = XCHAL_HAVE_DEBUG;
33 
34 /*  Number of instruction and data break registers:  */
35 const int Xthal_num_ibreak = XCHAL_NUM_IBREAK;
36 const int Xthal_num_dbreak = XCHAL_NUM_DBREAK;
37 
38 
39 #ifdef INCLUDE_DEPRECATED_HAL_DEBUG_CODE
40 /*  This array is incorrect:  */
41 const unsigned short	Xthal_ill_inst_16[16] =
42 {
43 #if XCHAL_HAVE_BE
44     0xfd0f, 0xfd1f, 0xfd2f, 0xfd3f,
45     0xfd4f, 0xfd5f, 0xfd6f, 0xfd7f,
46     0xfd8f, 0xfd9f, 0xfdaf, 0xfdbf,
47     0xfdcf, 0xfddf, 0xfdef, 0xfdff
48 #else
49     0xf0fd, 0xf1fd, 0xf2fd, 0xf3fd,
50     0xf4fd, 0xf5fd, 0xf6fd, 0xf7fd,
51     0xf8fd, 0xf9fd, 0xfafd, 0xfbfd,
52     0xfcfd, 0xfdfd, 0xfefd, 0xfffd
53 #endif
54 };
55 #endif /* INCLUDE_DEPRECATED_HAL_DEBUG_CODE */
56 
57 
58 #undef XTHAL_24_BIT_BREAK
59 #undef XTHAL_16_BIT_BREAK
60 #define XTHAL_24_BIT_BREAK		0x80000000
61 #define XTHAL_16_BIT_BREAK		0x40000000
62 
63 
64 
65 // set software breakpoint and synchronize cache
66 unsigned int
xthal_set_soft_break(void * addr)67 xthal_set_soft_break(void *addr)
68 {
69     unsigned inst;
70     int is24bit = (xthal_disassemble_size( (unsigned char *)addr ) == 3);
71     unsigned int ret_val;
72 
73 #if XCHAL_HAVE_BE
74     inst =  ((((char *)addr)[0])<<24) +
75             ((((char *)addr)[1])<<16) +
76             ((((char *)addr)[2])<<8);
77 #else
78     inst =  ((((char *)addr)[0])) +
79             ((((char *)addr)[1])<<8) +
80             ((((char *)addr)[2])<<16);
81 #endif
82 #if XCHAL_HAVE_BE
83     if (is24bit) {
84 	ret_val = XTHAL_24_BIT_BREAK & ((inst>>8)&0xffffff);
85 	((unsigned char *)addr)[0] = 0x00;
86 	((unsigned char *)addr)[1] = 0x04;
87 	((unsigned char *)addr)[2] = 0x00;
88     } else {
89 	ret_val = XTHAL_16_BIT_BREAK & ((inst>>16)&0xffff);
90 	((unsigned char *)addr)[0] = 0xD2;
91 	((unsigned char *)addr)[1] = 0x0f;
92     }
93 #else
94     if (is24bit) {
95 	ret_val = XTHAL_24_BIT_BREAK & (inst&0xffffff);
96 	((unsigned char *)addr)[0] = 0x00;
97 	((unsigned char *)addr)[1] = 0x40;
98 	((unsigned char *)addr)[2] = 0x00;
99     } else {
100 	ret_val = XTHAL_16_BIT_BREAK & (inst&0xffff);
101 	((unsigned char *)addr)[0] = 0x2D;
102 	((unsigned char *)addr)[1] = 0xf0;
103     }
104 #endif
105     *((unsigned int *)addr) = inst;
106 #if XCHAL_DCACHE_IS_WRITEBACK
107     xthal_dcache_region_writeback((void*)addr, 3);
108 #endif
109 #if XCHAL_ICACHE_SIZE > 0
110     xthal_icache_region_invalidate((void*)addr, 3);
111 #endif
112     return ret_val;
113 }
114 
115 
116 // remove software breakpoint and synchronize cache
117 void
xthal_remove_soft_break(void * addr,unsigned int inst)118 xthal_remove_soft_break(void *addr, unsigned int inst)
119 {
120 #if XCHAL_HAVE_BE
121     if (inst&XTHAL_24_BIT_BREAK) {
122 	((unsigned char *)addr)[0] = (inst>>16)&0xff;
123 	((unsigned char *)addr)[1] = (inst>>8)&0xff;
124 	((unsigned char *)addr)[2] = inst&0xff;
125     } else {
126 	((unsigned char *)addr)[0] = (inst>>8)&0xff;
127 	((unsigned char *)addr)[1] = inst&0xff;
128     }
129 #else
130     ((unsigned char *)addr)[0] = inst&0xff;
131     ((unsigned char *)addr)[1] = (inst>>8)&0xff;
132     if (inst&XTHAL_24_BIT_BREAK)
133 	((unsigned char *)addr)[2] = (inst>>16)&0xff;
134 #endif
135 #if XCHAL_DCACHE_IS_WRITEBACK
136     xthal_dcache_region_writeback((void*)addr, 3);
137 #endif
138 #if XCHAL_ICACHE_SIZE > 0
139     xthal_icache_region_invalidate((void*)addr, 3);
140 #endif
141 }
142 
143 
144 
145 
146 #ifdef INCLUDE_DEPRECATED_HAL_DEBUG_CODE
147 
148 // return instruction type
149 unsigned int
xthal_inst_type(void * addr)150 xthal_inst_type(void *addr)
151 {
152     unsigned int inst_type = 0;
153     unsigned inst;
154 //    unsigned int inst = *((unsigned int *)addr);
155     unsigned char op0, op1, op2;
156     unsigned char i, m, n, r, s, t, z;
157 
158 #if XCHAL_HAVE_BE
159     inst =  ((((char *)addr)[0])<<24) +
160             ((((char *)addr)[1])<<16) +
161             ((((char *)addr)[2])<<8);
162     op0 = inst>>28;
163     op1 = (inst>>12)&0xf;
164     op2 = (inst>>16)&0xf;
165     i = (inst>>27)&0x1;
166     z = (inst>>26)&0x1;
167     m = (inst>>24)&0x3;
168     n = (inst>>26)&0x3;
169     r = (inst>>16)&0xf;
170     s = (inst>>20)&0xf;
171     t = (inst>>24)&0xf;
172 #else
173     inst =  ((((char *)addr)[0])) +
174             ((((char *)addr)[1])<<8) +
175             ((((char *)addr)[2])<<16);
176     op0 = inst&0xf;
177     op1 = (inst&0xf0000)>>16;
178     op2 = (inst&0xf00000)>>20;
179     i = (inst&0x80)>>7;
180     z = (inst&0x40)>>6;
181     m = (inst&0xc0)>>6;
182     n = (inst&0x30)>>4;
183     r = (inst&0xf000)>>12;
184     s = (inst&0xf00)>>8;
185     t = (inst&0xf0)>4;
186 #endif
187     switch (op0) {
188 	  case 0x0:
189 		inst_type |= XTHAL_24_BIT_INST;
190 		if ((op1==0)&&(op2==0))
191 			switch (r) {
192 			  case 0:
193 				if (m==0x2) {
194 				  if (!(n&0x2))		// RET, RETW
195 				    inst_type |= XTHAL_RET_INST;
196 				  else if (n==0x2)	// JX
197 				    inst_type |= (XTHAL_JUMP_INST|XTHAL_DEST_REG_INST);
198 					inst_type |= (s<<28);
199 				} else if (m==3)	// CALLX
200 				  inst_type |= (XTHAL_JUMP_INST|XTHAL_DEST_REG_INST);
201 				  inst_type |= (s<<28);
202 			  	break;
203 			  case 0x3:
204 			    if (t==0)
205 				  switch (s) {
206 				    case 0x0:	// RFE
207 					  inst_type |= XTHAL_RFE_INST;
208 					  break;
209 					case 0x1:   // RFUE
210 					  inst_type |= XTHAL_RFUE_INST;
211 					  break;
212 					case 0x4:	// RFW
213 					case 0x5:
214 					  inst_type |= XTHAL_RFW_INST;
215 					  break;
216 				  }
217 				else if (t==1)	// RFI
218 				  inst_type |= XTHAL_RFI_INST;
219 				break;
220 			  case 0x4:	// BREAK
221 		    	inst_type |= XTHAL_BREAK_INST;
222 				break;
223 			  case 0x5:	// SYSCALL
224 		    	inst_type |= XTHAL_SYSCALL_INST;
225 				break;
226 			}
227 		break;
228 	  case 0x5:	// CALL
229 	    inst_type |= XTHAL_24_BIT_INST;
230 	    inst_type |= (XTHAL_JUMP_INST|XTHAL_DEST_REL_INST);
231 	    break;
232 	  case 0x6:	// B
233 	    inst_type |= XTHAL_24_BIT_INST;
234 		if (n==0)	// J
235 		  inst_type |= (XTHAL_JUMP_INST|XTHAL_DEST_REL_INST);
236 		else if ((n==0x1)||(n==0x2))
237 		  inst_type |= (XTHAL_BRANCH_INST|XTHAL_DEST_REL_INST);
238 		else {
239 		  if (m&0x2)
240 		    inst_type |= (XTHAL_BRANCH_INST|XTHAL_DEST_REL_INST);
241 		  else if ((m==0x1)&&((r==0x0)||(r==0x1)))
242 		    inst_type |= (XTHAL_BRANCH_INST|XTHAL_DEST_REL_INST);
243 		}
244 	    break;
245 	  case 0x7:	// B
246 	    inst_type |= XTHAL_24_BIT_INST;
247 	    inst_type |= (XTHAL_BRANCH_INST|XTHAL_DEST_REL_INST);
248 	    break;
249 #if XCHAL_HAVE_DENSITY
250 	  case 0x8:	// L32I.N
251 	  case 0x9:	// S32I.N
252 	  case 0xA:	// ADD.N
253 	  case 0xb:	// ADDI.N
254 	    inst_type |= XTHAL_16_BIT_INST;
255 		break;
256 	  case 0xc:
257 		inst_type |= XTHAL_16_BIT_INST;	// MOVI.N BEQZ.N, BNEZ.N
258 		if (i)
259 			inst_type |= (XTHAL_BRANCH_INST|XTHAL_DEST_REL_INST);
260 		break;
261 	  case 0xd:			// MOV.N NOP.N
262 		inst_type |= XTHAL_16_BIT_INST;
263 		if (r==0xf)
264 			switch(t) {
265 			  case 0x0:
266 			  case 0x1:
267 				inst_type |= XTHAL_RET_INST;	// RET.N, RETW.N
268 				break;
269 			  case 0x2:
270 				inst_type |= XTHAL_BREAK_INST;	// BREAK.N
271 				break;
272 			}
273 		break;
274 #endif /* XCHAL_HAVE_DENSITY */
275 	  default:
276 		inst_type |= XTHAL_24_BIT_INST;
277 	}
278 	return inst_type;
279 }
280 
281 // returns branch address
282 unsigned int
xthal_branch_addr(void * addr)283 xthal_branch_addr(void *addr)
284 {
285     unsigned int b_addr = (unsigned int) addr;
286     unsigned inst;
287 //  unsigned int inst = *((unsigned int *)addr);
288     int offset;
289     unsigned int inst_type = xthal_inst_type(addr);
290     unsigned int inst_type_mask;
291 #if XCHAL_HAVE_BE
292     inst =  ((((char *)addr)[0])<<24) +
293             ((((char *)addr)[1])<<16) +
294             ((((char *)addr)[2])<<8);
295 #else
296     inst =  ((((char *)addr)[0])) +
297             ((((char *)addr)[1])<<8) +
298             ((((char *)addr)[2])<<16);
299 #endif
300 #if XCHAL_HAVE_DENSITY
301     inst_type_mask = XTHAL_16_BIT_INST|XTHAL_BRANCH_INST|XTHAL_DEST_REL_INST;
302     if ((inst_type&inst_type_mask)==inst_type_mask) {
303 # if XCHAL_HAVE_BE
304 	b_addr += (4+((inst&0x3000000)>>20)+((inst&0xf0000)>>16));
305 # else
306 	b_addr += (4+(inst&0x30)+((inst&0xf000)>>12));
307 # endif
308     }
309 #endif /* XCHAL_HAVE_DENSITY */
310 	inst_type_mask = XTHAL_24_BIT_INST|XTHAL_BRANCH_INST|XTHAL_DEST_REL_INST;
311 	if ((inst_type&inst_type_mask)==inst_type_mask) {
312 #if XCHAL_HAVE_BE
313 		if ((inst&0xf0000000)==0x70000000)
314 			offset = ((int)(inst<<16))>>24;
315 		else if ((inst&0xf2000000)==0x62000000)
316 			offset = ((int)(inst<<16))>>24;
317 		else
318 			offset = ((int)(inst<<12))>>20;
319 #else
320 		if ((inst&0xf)==0x7)
321 			offset = ((int)(inst<<8))>>24;
322 		else if ((inst&0x2f)==0x26)
323 			offset = ((int)(inst<<8))>>24;
324 		else
325 			offset = ((int)(inst<<8))>>20;
326 #endif
327 		b_addr += 4 + offset;
328 	}
329 	inst_type_mask = XTHAL_24_BIT_INST|XTHAL_JUMP_INST|XTHAL_DEST_REL_INST;
330 	if ((inst_type&inst_type_mask)==inst_type_mask) {
331 #if XCHAL_HAVE_BE
332 		if ((inst&0xfc000000)==0x60000000)
333 			offset = ((int)(inst<<6))>>14;
334 		else
335 		{
336 			b_addr &= 0xfffffffc;
337 			offset = ((int)(inst<<6))>>12;
338 		}
339 #else
340 		if ((inst&0x3f)==0x6)
341 			offset = ((int)(inst<<8))>>14;
342 		else
343 		{
344 			b_addr &= 0xfffffffc;
345 			offset = ((int)(inst<<8))>>12;
346 		}
347 #endif
348 		b_addr += 4 + offset;
349 	}
350     return b_addr;
351 }
352 
353 // return pc of next instruction for a given state
xthal_get_npc(XTHAL_STATE * user_state)354 unsigned int xthal_get_npc(XTHAL_STATE *user_state)
355 {
356     unsigned inst_type;
357     unsigned npc;
358     inst_type = xthal_inst_type((void *)user_state->pc);
359     if (inst_type & XTHAL_24_BIT_INST)
360         npc = user_state->pc + 3;
361     else
362         npc = user_state->pc + 2;
363     if (inst_type & XTHAL_RFW_INST) {
364 	/* Can not debug level 1 interrupts */
365 	// xt_panic();
366     } else if (inst_type & XTHAL_RFUE_INST) {
367 	/* Can not debug level 1 interrupts */
368 	// xt_panic();
369     } else if (inst_type & XTHAL_RFI_INST) {
370 	/* Can not debug level 1 interrupts */
371 	// xt_panic();
372     } else if (inst_type & XTHAL_RFE_INST) {
373 	/* Can not debug level 1 interrupts */
374 	// xt_panic();
375     } else if (inst_type & XTHAL_RET_INST) {
376 	npc = (user_state->pc&0xc0000000)+(user_state->ar[0]&0x3fffffff);
377     } else if (inst_type & XTHAL_BREAK_INST) {
378 	/* Can not debug break */
379 	// xt_panic();
380     } else if (inst_type & XTHAL_SYSCALL_INST) {
381 	/* Can not debug exceptions */
382 	// xt_panic();
383     } else if (inst_type & XTHAL_LOOP_END) {
384 	// xt_panic();
385     } else if (inst_type & XTHAL_JUMP_INST) {
386         if (inst_type & XTHAL_DEST_REG_INST) {
387              return user_state->ar[inst_type>>28];
388 	} else if (inst_type & XTHAL_DEST_REL_INST) {
389              return xthal_branch_addr((void *)user_state->pc);
390         }
391     } else if (inst_type & XTHAL_BRANCH_INST) {
392 	int branch_taken = 0;
393 	unsigned short inst;
394 	unsigned char op0, t, s, r, m, n;
395 	memcpy(&inst, (void *)user_state->pc, 2);
396 #if XCHAL_HAVE_BE
397 	op0 = (inst&0xf000)>>12;
398 	t   = (inst&0x0f00)>>8;
399 	s   = (inst&0x00f0)>>4;
400 	r   = (inst&0x000f);
401 	m   = t&3;
402 	n   = t>>2;
403 #else
404 	op0 = (inst&0x000f);
405 	t   = (inst&0x00f0)>>4;
406 	s   = (inst&0x0f00)>>8;
407 	r   = (inst&0xf000)>>12;
408 	m   = t>>2;
409 	n   = t&3;
410 #endif
411 	if (inst_type &XTHAL_16_BIT_INST) {
412 #if XCHAL_HAVE_BE
413 	    if (inst&0x400)	/* BNEZ.N */
414 		branch_taken = (user_state->ar[(inst>>4)&0xf]!=0);
415 	    else		/* BEQZ.N */
416 		branch_taken = (user_state->ar[(inst>>4)&0xf]==0);
417 #else
418 	    if (inst&0x40)	/* BNEZ.N */
419 		branch_taken = (user_state->ar[(inst>>8)&0xf]!=0);
420 	    else		/* BEQZ.N */
421 		branch_taken = (user_state->ar[(inst>>8)&0xf]==0);
422 #endif
423 	}
424 	if (op0==0x6) {
425 	    if (n==1) {
426 		if (m==0) {		/* BEQZ */
427 		    branch_taken = (user_state->ar[s]==0);
428 		} else if (m==1) {	/* BNEZ */
429 		    branch_taken = (user_state->ar[s]!=0);
430 		} else if (m==2) {	/* BLTZ */
431 		    branch_taken = (((int)user_state->ar[s])<0);
432 		} else if (m==3) {	/* BGEZ */
433 		    branch_taken = (((int)user_state->ar[s])>=0);
434 		}
435 	    } else if (n==2) {
436 		int b4const[16] =
437 		    { -1, 1, 2, 3, 4, 5, 6, 7,
438 		      8, 10, 12, 16, 32, 62, 128, 256 };
439 		if (m==0) {		/* BEQI */
440 		    branch_taken = (user_state->ar[s]==b4const[r]);
441 		} else if (m==1) {	/* BNEI */
442 		    branch_taken = (user_state->ar[s]!=b4const[r]);
443 		} else if (m==2) {	/* BLTI */
444 		    branch_taken = (((int)user_state->ar[s])<b4const[r]);
445 		} else if (m==3) {	/* BGEI */
446 		    branch_taken = (((int)user_state->ar[s])>=b4const[r]);
447 		}
448 	    } else if (n==3) {
449 		int b4constu[16] =
450 		    { 32768, 65536, 2, 3, 4, 5, 6, 7,
451 		      8, 10, 12, 16, 32, 62, 128, 256 };
452 		if (m==2) {		/* BLTUI */
453 		    branch_taken = (user_state->ar[s]<b4constu[r]);
454 		} else if (m==3) {	/* BGEUI */
455 		    branch_taken = (user_state->ar[s]>=b4constu[r]);
456 		}
457 	    }
458 	} else if (op0==0x7) {
459 	    if (r==0) {			/* BNONE */
460 		branch_taken = ((user_state->ar[s]&user_state->ar[t])==0);
461 	    } else if (r==1) {		/* BEQ */
462 		branch_taken = (user_state->ar[s]==user_state->ar[t]);
463 	    } else if (r==2) {		/* BLT */
464 		branch_taken = ((int)user_state->ar[s]<(int)user_state->ar[t]);
465 	    } else if (r==3) {		/* BLTU */
466 		branch_taken = (user_state->ar[s]<user_state->ar[t]);
467 	    } else if (r==4) {		/* BALL */
468 		branch_taken = (((~user_state->ar[s])&user_state->ar[t])==0);
469 	    } else if (r==5) {		/* BBC */
470 #if XCHAL_HAVE_BE
471 		branch_taken = ((user_state->ar[s]&(0x80000000>>user_state->ar[t]))==0);
472 	    } else if (r==6) {		/* BBCI */
473 		branch_taken = ((user_state->ar[s]&(0x80000000>>t))==0);
474 	    } else if (r==7) {		/* BBCI */
475 		branch_taken = ((user_state->ar[s]&(0x80000000>>(t+16)))==0);
476 #else
477 		branch_taken = ((user_state->ar[s]&(1<<user_state->ar[t]))==0);
478 	    } else if (r==6) {		/* BBCI */
479 		branch_taken = ((user_state->ar[s]&(1<<t))==0);
480 	    } else if (r==7) {		/* BBCI */
481 		branch_taken = ((user_state->ar[s]&(1<<(t+16)))==0);
482 #endif
483 	    } else if (r==8) {		/* BANY */
484 		branch_taken = ((user_state->ar[s]&user_state->ar[t])!=0);
485 	    } else if (r==9) {		/* BNE */
486 		branch_taken = (user_state->ar[s]!=user_state->ar[t]);
487 	    } else if (r==10) {		/* BGE */
488 		branch_taken = ((int)user_state->ar[s]>=(int)user_state->ar[t]);
489 	    } else if (r==11) {		/* BGEU */
490 		branch_taken = (user_state->ar[s]>=user_state->ar[t]);
491 	    } else if (r==12) {		/* BNALL */
492 		branch_taken = (((~user_state->ar[s])&user_state->ar[t])!=0);
493 	    } else if (r==13) {		/* BBS */
494 #if XCHAL_HAVE_BE
495 		branch_taken = ((user_state->ar[s]&(0x80000000>>user_state->ar[t]))!=0);
496 	    } else if (r==14) {		/* BBSI */
497 		branch_taken = ((user_state->ar[s]&(0x80000000>>t))!=0);
498 	    } else if (r==15) {		/* BBSI */
499 		branch_taken = ((user_state->ar[s]&(0x80000000>>(t+16)))!=0);
500 #else
501 		branch_taken = ((user_state->ar[s]&(1<<user_state->ar[t]))!=0);
502 	    } else if (r==14) {		/* BBSI */
503 		branch_taken = ((user_state->ar[s]&(1<<t))!=0);
504 	    } else if (r==15) {		/* BBSI */
505 		branch_taken = ((user_state->ar[s]&(1<<(t+16)))!=0);
506 #endif
507 	    }
508 	}
509 	if (branch_taken) {
510 	    if (inst_type & XTHAL_DEST_REG_INST) {
511         	return user_state->ar[inst_type>>24];
512 	    } else if (inst_type & XTHAL_DEST_REL_INST) {
513         	return xthal_branch_addr((void *)user_state->pc);
514 	    }
515 	}
516 #if XCHAL_HAVE_LOOPS
517 	else if (user_state->lcount && (npc==user_state->lend))
518 	    return user_state->lbeg;
519 #endif
520     }
521     return npc;
522 }
523 
524 #endif /* INCLUDE_DEPRECATED_HAL_DEBUG_CODE */
525 
526