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