1 /*******************************************************************************
2 * Copyright (C) 2018 Cadence Design Systems, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to use this Software with Cadence processor cores only and
7 * not with any other processors and platforms, subject to
8 * the following conditions:
9 *
10 * The above copyright notice and this permission notice shall be included
11 * in all copies or substantial portions of the Software.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
14 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
15 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
16 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
17 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
18 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
19 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21 ******************************************************************************/
22
23 /****************************************************************************
24
25 THIS SOFTWARE IS NOT COPYRIGHTED
26
27 HP offers the following for use in the public domain. HP makes no
28 warranty with regard to the software or it's performance and the
29 user accepts the software "AS IS" with all faults.
30
31 HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
32 TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
33 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
34
35 ****************************************************************************/
36
37 /****************************************************************************
38 * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
39 *
40 * Module name: remcom.c $
41 * Revision: 1.34 $
42 * Date: 91/03/09 12:29:49 $
43 * Contributor: Lake Stevens Instrument Division$
44 *
45 * Description: low level support for gdb debugger. $
46 *
47 * Considerations: only works on target hardware $
48 *
49 * Written by: Glenn Engel $
50 * ModuleState: Experimental $
51 *
52 * NOTES: See Below $
53 *
54 * Modified for SPARC by Stu Grossman, Cygnus Support.
55 *
56 * This code has been extensively tested on the Fujitsu SPARClite demo board.
57 *
58 * To enable debugger support, two things need to happen. One, a
59 * call to set_debug_traps() is necessary in order to allow any breakpoints
60 * or error conditions to be properly intercepted and reported to gdb.
61 * Two, a breakpoint needs to be generated to begin communication. This
62 * is most easily accomplished by a call to breakpoint(). Breakpoint()
63 * simulates a breakpoint by executing a trap #1.
64 *
65 *************
66 *
67 * The following gdb commands are supported:
68 *
69 * command function Return value
70 *
71 * g return the value of the CPU registers hex data or ENN
72 * G set the value of the CPU registers OK or ENN
73 *
74 * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
75 * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
76 *
77 * c Resume at current address SNN ( signal NN)
78 * cAA..AA Continue at address AA..AA SNN
79 *
80 * s Step one instruction SNN
81 * sAA..AA Step one instruction from AA..AA SNN
82 *
83 * k kill
84 *
85 * ? What was the last sigval ? SNN (signal NN)
86 *
87 * All commands and responses are sent with a packet which includes a
88 * checksum. A packet consists of
89 *
90 * $<packet info>#<checksum>.
91 *
92 * where
93 * <packet info> :: <characters representing the command or response>
94 * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>>
95 *
96 * When a packet is received, it is first acknowledged with either '+' or '-'.
97 * '+' indicates a successful transfer. '-' indicates a failed transfer.
98 *
99 * Example:
100 *
101 * Host: Reply:
102 * $m0,10#2a +$00010203040506070809101112131415#42
103 *
104 ****************************************************************************/
105 #ifdef XAF_ENABLE_NON_HIKEY
106 #include "xf.h"
107 #else
108 #include <string.h>
109 #include <signal.h>
110 #include <stdint.h>
111 #include <xtensa/xtruntime.h>
112 #endif
113 #include "xtensa-defs.h"
114
115 /*******************************************************************************
116 * Ring-buffer definition
117 ******************************************************************************/
118
119 #define RING_SIZE 256
120
121 struct ring {
122 unsigned char head;
123 unsigned char fill1[63];
124 unsigned char tail;
125 unsigned char fill2[63];
126 unsigned char data[RING_SIZE];
127 };
128
129 #define GDB_INVALIDATE(p) \
130 xthal_dcache_region_invalidate((void *)(p), sizeof(*p))
131
132 #define GDB_FLUSH(p) \
133 xthal_dcache_region_writeback((void *)(p), sizeof(*p))
134
ring_next_head(const volatile struct ring * ring)135 static inline unsigned int ring_next_head(const volatile struct ring *ring)
136 {
137 return (ring->head + 1) & (RING_SIZE - 1);
138 }
139
ring_next_tail(const volatile struct ring * ring)140 static inline unsigned int ring_next_tail(const volatile struct ring *ring)
141 {
142 return (ring->tail + 1) & (RING_SIZE - 1);
143 }
144
ring_have_space(const volatile struct ring * ring)145 static inline int ring_have_space(const volatile struct ring *ring)
146 {
147 /* ...invalidate tail pointer of tx-ring (updated by host) */
148 GDB_INVALIDATE(&ring->tail);
149
150 return ring_next_head(ring) != ring->tail;
151 }
152
ring_have_data(const volatile struct ring * ring)153 static inline int ring_have_data(const volatile struct ring *ring)
154 {
155 /* ...invalidate head pointer of rx-ring (updated by host) */
156 GDB_INVALIDATE(&ring->head);
157
158 return ring->head != ring->tail;
159 }
160 #ifdef XAF_ENABLE_NON_HIKEY
161 #define DEBUG_RX_BASE XF_CFG_GDB_RING_RX
162 #define DEBUG_TX_BASE XF_CFG_GDB_RING_TX
163 #else
164 //#define DEBUG_RX_BASE (0x72000000)
165 //#define DEBUG_TX_BASE (0x72000800)
166 #define DEBUG_RX_BASE (0x6FFFF000)
167 #define DEBUG_TX_BASE (0x6FFFF800)
168 #endif
169
170 volatile struct ring * const rx = (void *)DEBUG_RX_BASE;
171 volatile struct ring * const tx = (void *)DEBUG_TX_BASE;
172
init_debug_comm(void)173 void init_debug_comm(void)
174 {
175 rx->head = rx->tail = 0;
176 tx->head = tx->tail = 0;
177 GDB_FLUSH(&rx->head);
178 GDB_FLUSH(&rx->tail);
179 GDB_FLUSH(&tx->head);
180 GDB_FLUSH(&tx->tail);
181 }
182
183 /* ...functions defined in asm code */
184 extern void breakpoint(void);
185 extern void init_debug_entry(void);
186
poll_debug_ring(void)187 void poll_debug_ring(void)
188 {
189 if (ring_have_data(rx)) {
190 breakpoint();
191 }
192 }
193
putDebugChar(char c)194 static void putDebugChar(char c)
195 {
196 while (!ring_have_space(tx))
197 ;
198
199 tx->data[tx->head] = c;
200
201 /* ...flush data buffer to main memory */
202 GDB_FLUSH(&tx->data[tx->head]);
203
204 tx->head = ring_next_head(tx);
205
206 /* ...flush head pointer to main memory */
207 GDB_FLUSH(&tx->head);
208 }
209
getDebugChar(void)210 static int getDebugChar(void)
211 {
212 int v;
213 while (!ring_have_data(rx))
214 ;
215
216 /* ...inavlidate data buffer */
217 GDB_INVALIDATE(&rx->data[rx->tail]);
218
219 v = rx->data[rx->tail];
220 rx->tail = ring_next_tail(rx);
221
222 /* ...update tail index */
223 GDB_FLUSH(&rx->tail);
224
225 return v;
226 }
227
228 /************************************************************************/
229 /* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
230 /* at least NUMREGBYTES*2 are needed for register packets */
231 #define BUFMAX 256
232
233 #ifdef USE_GDBSTUB
234 #define bulk_data __attribute__((section (".ddr0.data")))
235 #else
236 #define bulk_data
237 #endif
238 uint32_t stack[STACK_SIZE / sizeof(uint32_t)] bulk_data;
239 static uint8_t sregs_read[32] bulk_data;
240 static uint8_t sregs_mod[32] bulk_data;
241 static uint8_t sregs_late[32] bulk_data;
242 uint32_t sregs[256] bulk_data;
243 uint32_t aregs[XCHAL_NUM_AREGS] bulk_data;
244 static uint8_t remcomInBuffer[BUFMAX] bulk_data;
245 static uint8_t remcomOutBuffer[BUFMAX] bulk_data;
246
247 static const char hexchars[]="0123456789abcdef";
248
249 /* Convert ch from a hex digit to an int */
250
hex(unsigned char ch)251 static int hex(unsigned char ch)
252 {
253 if (ch >= 'a' && ch <= 'f')
254 return ch-'a'+10;
255 if (ch >= '0' && ch <= '9')
256 return ch-'0';
257 if (ch >= 'A' && ch <= 'F')
258 return ch-'A'+10;
259 return -1;
260 }
261
262 /* scan for the sequence $<data>#<checksum> */
263
getpacket(void)264 unsigned char *getpacket(void)
265 {
266 unsigned char *buffer = &remcomInBuffer[0];
267 unsigned char checksum;
268 unsigned char xmitcsum;
269 int count;
270 char ch;
271
272 while (1) {
273 /* wait around for the start character, ignore all other characters */
274 while ((ch = getDebugChar ()) != '$')
275 ;
276
277 retry:
278 checksum = 0;
279 xmitcsum = -1;
280 count = 0;
281
282 /* now, read until a # or end of buffer is found */
283 while (count < BUFMAX - 1) {
284 ch = getDebugChar ();
285 if (ch == '$')
286 goto retry;
287 if (ch == '#')
288 break;
289 checksum = checksum + ch;
290 buffer[count] = ch;
291 count = count + 1;
292 }
293 buffer[count] = 0;
294
295 if (ch == '#') {
296 ch = getDebugChar ();
297 xmitcsum = hex (ch) << 4;
298 ch = getDebugChar ();
299 xmitcsum += hex (ch);
300
301 if (checksum != xmitcsum) {
302 putDebugChar ('-'); /* failed checksum */
303 } else {
304 putDebugChar ('+'); /* successful transfer */
305
306 /* if a sequence char is present, reply the sequence ID */
307 if (buffer[2] == ':') {
308 putDebugChar (buffer[0]);
309 putDebugChar (buffer[1]);
310
311 return &buffer[3];
312 }
313
314 return &buffer[0];
315 }
316 }
317 }
318 }
319
320 /* send the packet in buffer. */
321
putpacket(uint8_t * buffer)322 static void putpacket(uint8_t *buffer)
323 {
324 unsigned char checksum;
325 int count;
326 unsigned char ch;
327
328 /* $<packet info>#<checksum>. */
329 do {
330 putDebugChar('$');
331 checksum = 0;
332 count = 0;
333
334 while ((ch = buffer[count]) != 0) {
335 putDebugChar(ch);
336 checksum += ch;
337 count += 1;
338 }
339
340 putDebugChar('#');
341 putDebugChar(hexchars[checksum >> 4]);
342 putDebugChar(hexchars[checksum & 0xf]);
343
344 } while (getDebugChar() != '+');
345 }
346
347 /* Indicate to caller of mem2hex or hex2mem that there has been an
348 error. */
349 volatile int mem_err = 0;
350
351 /* Convert the memory pointed to by mem into hex, placing result in buf.
352 * Return a pointer to the last char put in buf (null), in case of mem fault,
353 * return 0.
354 */
355
mem2hex(const void * mem_,uint8_t * buf,int count)356 static uint8_t * mem2hex(const void *mem_, uint8_t *buf, int count)
357 {
358 const unsigned char *mem = mem_;
359 unsigned char ch;
360
361 mem_err = 0;
362 while (count-- > 0) {
363 #ifdef __XTENSA__
364 unsigned long v;
365 unsigned long addr = (unsigned long)mem;
366 asm volatile ("_l32i %0, %1, 0\n"
367 : "=r"(v)
368 : "r"(addr & ~3)
369 : "memory");
370 ch = v >> (addr & 3) * 8;
371 #endif
372 mem++;
373 if (mem_err)
374 return NULL;
375 *buf++ = hexchars[ch >> 4];
376 *buf++ = hexchars[ch & 0xf];
377 }
378
379 *buf = 0;
380
381 return buf;
382 }
383
384 /* convert the hex array pointed to by buf into binary to be placed in mem
385 * return a pointer to the character AFTER the last byte written */
386
hex2mem(const uint8_t * buf,void * mem_,int count)387 static uint8_t * hex2mem(const uint8_t *buf, void *mem_, int count)
388 {
389 uint8_t *mem = mem_;
390 int i;
391 uint8_t ch;
392
393 if ((unsigned long)mem >= 0xece80000)
394 return NULL;
395
396 mem_err = 0;
397 for (i=0; i<count; i++) {
398 ch = hex(*buf++) << 4;
399 ch |= hex(*buf++);
400 #ifdef __XTENSA__
401 unsigned long tmp;
402 unsigned long addr = (unsigned long)mem;
403 asm volatile ("_l32i %0, %1, 0\n"
404 "and %0, %0, %2\n"
405 "or %0, %0, %3\n"
406 "_s32i %0, %1, 0\n"
407 "dhwb %1, 0\n"
408 "ihi %1, 0\n"
409 : "=r"(tmp)
410 : "r"(addr & ~3), "r"(0xffffffff ^ (0xff << (addr & 3) * 8)), "r"(ch << (addr & 3) * 8)
411 : "memory");
412 #endif
413 mem++;
414 if (mem_err)
415 return NULL;
416 }
417
418 return mem;
419 }
420
421 /*
422 * While we find nice hex chars, build an int.
423 * Return number of chars processed.
424 */
425
hexToInt(uint8_t ** ptr,int * intValue)426 static int hexToInt(uint8_t **ptr, int *intValue)
427 {
428 int numChars = 0;
429 int hexValue;
430
431 *intValue = 0;
432
433 while (**ptr) {
434 hexValue = hex(**ptr);
435 if (hexValue < 0)
436 break;
437
438 *intValue = (*intValue << 4) | hexValue;
439 numChars ++;
440
441 (*ptr)++;
442 }
443
444 return (numChars);
445 }
446
test_bit(const uint8_t * p,int bit)447 static inline int test_bit(const uint8_t *p, int bit)
448 {
449 return (p[bit / 8] >> (bit & 0x7)) & 1;
450 }
set_bit(uint8_t * p,int bit)451 static inline int set_bit(uint8_t *p, int bit)
452 {
453 return (p[bit / 8] |= 1u << (bit & 0x7));
454 }
455
mark_read(int sr)456 static inline void mark_read(int sr)
457 {
458 set_bit(sregs_read, sr);
459 }
is_read(int sr)460 static inline int is_read(int sr)
461 {
462 return test_bit(sregs_read, sr);
463 }
mark_mod(int sr)464 static inline void mark_mod(int sr)
465 {
466 set_bit(sregs_mod, sr);
467 }
is_mod(int sr)468 static inline int is_mod(int sr)
469 {
470 return test_bit(sregs_mod, sr);
471 }
mark_late(int sr)472 static inline void mark_late(int sr)
473 {
474 set_bit(sregs_late, sr);
475 }
is_late(int sr)476 static inline int is_late(int sr)
477 {
478 return test_bit(sregs_late, sr);
479 }
480
read_sr(int sr)481 static void read_sr(int sr)
482 {
483 if (!is_read(sr)) {
484 #ifdef __XTENSA__
485 uint32_t val;
486 asm volatile ("movi a3, 1f + 1\n"
487 "s8i %1, a3, 0\n"
488 "dhwb a3, 0\n"
489 "ihi a3, 0\n"
490 "isync\n"
491 "1:\n"
492 "rsr %0, lbeg\n"
493 : "=r"(val)
494 : "r"(sr)
495 : "a3", "memory");
496 sregs[sr] = val;
497 #endif
498 mark_read(sr);
499 }
500 }
501
write_sr(int sr)502 static void write_sr(int sr)
503 {
504 #ifdef __XTENSA__
505 asm volatile ("movi a3, 1f + 1\n"
506 "s8i %1, a3, 0\n"
507 "dhwb a3, 0\n"
508 "ihi a3, 0\n"
509 "isync\n"
510 "1:\n"
511 "wsr %0, lbeg\n"
512 :
513 : "r"(sregs[sr]), "r"(sr)
514 : "a3", "memory");
515 #endif
516 }
517
restore_sr(void)518 static void restore_sr(void)
519 {
520 int i;
521 for (i = 0; i < 256; ++i)
522 if (is_mod(i) && !is_late(i))
523 write_sr(i);
524 }
525
526 extern void *_xtos_exc_handler_table[];
527 void fault_handler(void);
528 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
529
handle_exception(void)530 void handle_exception(void)
531 {
532 int sigval = 0;
533 int addr;
534 int length;
535 uint8_t *ptr;
536 unsigned i;
537 const unsigned windowbase = 4 * sregs[WINDOWBASE];
538 uint8_t stop_status[4] = "Sxx";
539 #ifdef LIBC_LEVEL1_HANDLER
540 static const int cause[] = {
541 EXCCAUSE_LOAD_STORE_ERROR,
542 EXCCAUSE_LOAD_STORE_DATA_ERROR,
543 EXCCAUSE_LOAD_STORE_ADDR_ERROR,
544 EXCCAUSE_DTLB_MISS,
545 EXCCAUSE_DTLB_MULTIHIT,
546 EXCCAUSE_LOAD_PROHIBITED,
547 EXCCAUSE_STORE_PROHIBITED,
548 };
549 _xtos_handler handler[sizeof(cause) / sizeof(cause[0])];
550
551 for (i = 0; i < ARRAY_SIZE(cause); ++i) {
552 handler[i] = _xtos_exc_handler_table[cause[i]];
553 _xtos_exc_handler_table[cause[i]] = fault_handler;
554 }
555 #endif
556 memcpy(sregs_read, sregs_late, sizeof(sregs_read));
557 memset(sregs_mod, 0, sizeof(sregs_mod));
558
559 sigval = 5;
560 stop_status[1] = hexchars[sigval >> 4];
561 stop_status[2] = hexchars[sigval & 0xf];
562
563 if (sregs[DEBUGCAUSE] & DEBUGCAUSE_ICOUNT_MASK) {
564 sregs[ICOUNTLEVEL] = 0;
565 mark_mod(ICOUNTLEVEL);
566 }
567 putpacket(stop_status);
568
569 while (1) {
570 remcomOutBuffer[0] = 0;
571
572 ptr = getpacket();
573 switch (*ptr++) {
574 case '?':
575 memcpy(remcomOutBuffer, stop_status, sizeof(stop_status));
576 break;
577
578 case 'c': /* cAA..AA Continue at address AA..AA(optional) */
579 /* try to read optional parameter, pc unchanged if no parm */
580
581 if (hexToInt(&ptr, &addr))
582 sregs[DEBUG_PC] = addr;
583 goto out;
584
585 case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
586 /* Try to read %x,%x. */
587
588 if (hexToInt(&ptr, &addr) && *ptr++ == ',' &&
589 hexToInt(&ptr, &length)) {
590 if (mem2hex((void *)addr, remcomOutBuffer, length))
591 break;
592
593 strcpy((char *)remcomOutBuffer, "E03");
594 } else {
595 strcpy((char *)remcomOutBuffer, "E01");
596 }
597 break;
598
599 case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
600 /* Try to read '%x,%x:'. */
601
602 if (hexToInt(&ptr, &addr) && *ptr++ == ',' &&
603 hexToInt(&ptr, &length) && *ptr++ == ':') {
604 if (hex2mem(ptr, (void *)addr, length))
605 strcpy((char *)remcomOutBuffer, "OK");
606 else
607 strcpy((char *)remcomOutBuffer, "E03");
608 } else {
609 strcpy((char *)remcomOutBuffer, "E02");
610 }
611 break;
612
613 case 'p': /* pAA..AA read register number AA..AA */
614 if (hexToInt(&ptr, &addr)) {
615 if (addr < 0x10) { /* read address register in the current window */
616 mem2hex(aregs + addr, remcomOutBuffer, 4);
617 } else if (addr == 0x20) { /* read PC */
618 mem2hex(sregs + DEBUG_PC, remcomOutBuffer, 4);
619 } else if (addr >= 0x100 && addr < 0x100 + XCHAL_NUM_AREGS) { /* read address register by absolute index */
620 mem2hex(aregs + ((addr - windowbase) & 0xff), remcomOutBuffer, 4);
621 } else if (addr >= 0x200 && addr < 0x300) { /* read special register */
622 addr &= 0xff;
623 read_sr(addr);
624 mem2hex(sregs + addr, remcomOutBuffer, 4);
625 } else if (addr >= 0x300 && addr < 0x400) { /* TODO read user register */
626 strcpy((char *)remcomOutBuffer, "deadbabe");
627 } else { /* unexpected register number */
628 strcpy((char *)remcomOutBuffer, "E00");
629 }
630 }
631 break;
632
633 case 'P': /* PAA..AA=VV..VV Set register number AA..AA to a value VV..VV */
634 if (hexToInt(&ptr, &addr) && *(ptr++) == '=') {
635 int ok = 1;
636
637 if (addr < 0x10) {
638 hex2mem(ptr, aregs + addr, 4);
639 } else if (addr == 0x20) {
640 hex2mem(ptr, sregs + DEBUG_PC, 4);
641 } else if (addr >= 0x100 && addr < 0x100 + XCHAL_NUM_AREGS) {
642 hex2mem(ptr, aregs + ((addr - windowbase) & 0xff), 4);
643 } else if (addr >= 0x200 && addr < 0x300) {
644 addr &= 0xff;
645 hex2mem(ptr, sregs + addr, 4);
646 mark_read(addr);
647 mark_mod(addr);
648 } else {
649 ok = 0;
650 strcpy((char *)remcomOutBuffer, "E00");
651 }
652 if (ok)
653 strcpy((char *)remcomOutBuffer, "OK");
654 }
655 break;
656
657 case 'q': /* generic query */
658 if (strncmp((char *)ptr, "Supported", 9) == 0)
659 strcpy((char *)remcomOutBuffer, "PacketSize=100"); /* must match BUFMAX */
660 break;
661
662 case 's': /* s[AA..AA] Single step */
663 if (hexToInt(&ptr, &addr))
664 sregs[DEBUG_PC] = addr;
665 sregs[ICOUNT] = 0xfffffffe;
666 mark_mod(ICOUNT);
667 sregs[ICOUNTLEVEL] = XCHAL_DEBUGLEVEL;
668 mark_mod(ICOUNTLEVEL);
669 goto out;
670
671 case 'Z': /* insert HW breakpoint*/
672 switch (*ptr++) {
673 case '1':
674 read_sr(IBREAKENABLE);
675 if (*ptr++ == ',' && hexToInt(&ptr, &addr) &&
676 *ptr++ == ',' && hexToInt(&ptr, &length) &&
677 *ptr == 0) {
678 for (i = 0; i < XCHAL_NUM_IBREAK; ++i) {
679 if (!(sregs[IBREAKENABLE] & (1 << i)) ||
680 sregs[IBREAKA + i] == addr) {
681 sregs[IBREAKA + i] = addr;
682 mark_mod(IBREAKA + i);
683 sregs[IBREAKENABLE] |= (1 << i);
684 mark_mod(IBREAKENABLE);
685 break;
686 }
687 }
688 if (i == XCHAL_NUM_IBREAK)
689 strcpy((char *)remcomOutBuffer, "E02");
690 else
691 strcpy((char *)remcomOutBuffer, "OK");
692 } else {
693 strcpy((char *)remcomOutBuffer, "E01");
694 }
695 break;
696 }
697 break;
698
699 case 'z': /* remove HW breakpoint */
700 switch (*ptr++) {
701 case '1':
702 read_sr(IBREAKENABLE);
703 if (*ptr++ == ',' && hexToInt(&ptr, &addr) &&
704 *ptr++ == ',' && hexToInt(&ptr, &length)) {
705 for (i = 0; i < XCHAL_NUM_IBREAK; ++i) {
706 read_sr(IBREAKA + i);
707 if (sregs[IBREAKENABLE] & (1 << i) &&
708 sregs[IBREAKA + i] == addr) {
709 sregs[IBREAKENABLE] &= ~(1 << i);
710 mark_mod(IBREAKENABLE);
711 break;
712 }
713 }
714 if (i == XCHAL_NUM_IBREAK)
715 strcpy((char *)remcomOutBuffer, "E02");
716 else
717 strcpy((char *)remcomOutBuffer, "OK");
718 } else {
719 strcpy((char *)remcomOutBuffer, "E01");
720 }
721 break;
722 }
723 break;
724 }
725
726 /* reply to the request */
727 putpacket(remcomOutBuffer);
728 }
729 out:
730 #ifdef LIBC_LEVEL1_HANDLER
731 for (i = 0; i < ARRAY_SIZE(cause); ++i) {
732 _xtos_exc_handler_table[cause[i]] = handler[i];
733 }
734 #endif
735 restore_sr();
736 }
737
init_gdbstub(void)738 void init_gdbstub(void)
739 {
740 mark_late(LBEG);
741 mark_late(LEND);
742 mark_late(LCOUNT);
743 mark_late(SAR);
744 mark_late(WINDOWBASE);
745 mark_late(WINDOWSTART);
746 mark_late(DEBUG_PC);
747 mark_late(EXCSAVE_1);
748 mark_late(PS);
749 mark_late(EXCCAUSE);
750 mark_late(DEBUGCAUSE);
751 mark_late(EXCVADDR);
752 #ifdef __XTENSA__
753 init_debug_comm();
754 init_debug_entry();
755 #endif
756 }
757