MOXA linux-2.6.x / linux-2.6.19-uc1 from UC-7110-LX-BOOTLOADER-1.9_VERSION-4.2.tgz
[linux-2.6.19-moxart.git] / arch / nios2nommu / kernel / nios_gdb_stub.c
blob103925b69fd0e606e15aabaa0f685e45f1b5096c
1 // Modified for uClinux - Vic - Apr 2002
2 // From:
4 // File: nios_gdb_stub.c
5 // Date: 2000 June 20
6 // Author dvb \ Altera Santa Cruz
8 #ifndef __KERNEL__
9 #include "nios.h"
10 #else
11 #include <linux/kernel.h>
12 #include <linux/sched.h>
13 #include <asm/nios.h>
14 #endif
16 #include "nios_gdb_stub.h"
18 #define na_debug_peripheral_irq 8
20 enum
22 na_BreakpointTrap = 3,
23 na_SingleStepTrap = 4,
24 na_StartGDBTrap = 5
28 #ifdef __KERNEL__
30 extern int _etext;
32 static void puts( unsigned char *s )
34 while(*s) {
35 while (!(nasys_printf_uart->np_uartstatus & np_uartstatus_trdy_mask));
36 nasys_printf_uart->np_uarttxdata = *s++;
40 #endif // __KERNEL__
42 // --------------------------------
43 // Local Prototypes
45 #if GDB_DEBUG_PRINT
47 static void StringFit(char *s,int w);
49 // --------------------------------
50 // Debugging The Debugger
52 void GDB_RawMessage(char *s)
54 StringFit(s,32);
55 nr_pio_lcdwritescreen(s);
57 #else
58 #define GDB_RawMessage(a,b,c) // define away to nothing
59 #endif
61 #if GDB_DEBUG_PRINT
62 void GDB_Print2(char *s,int n1,int n2)
64 char st[1000];
66 sprintf(st,s,n1,n2);
67 GDB_RawMessage(st);
69 #else
70 #define GDB_Print2(a,b,c) // define away to nothing
71 #endif
73 // If string is longer than w, cut out the middle.
75 #if GDB_DEBUG_PRINT
76 int StringLen(char *s)
78 int l = 0;
80 while(*s++)
81 l++;
82 return l;
85 static void StringFit(char *s,int w)
87 if(StringLen(s) > w)
89 int i;
92 w = w / 2;
94 for(i = 0; i < w; i++)
96 s[i + w] = s[StringLen(s) - w + i];
98 s[w + w] = 0;
101 #endif
103 // ---------------------------------------------
104 // Generic routines for dealing with
105 // hex input, output, and parsing
106 // (Adapted from other stubs.)
108 NiosGDBGlobals gdb = {0}; // not static: the ISR uses it!
110 static char dHexChars[16] = "0123456789abcdef";
113 * HexCharToValue -- convert a characters
114 * to its hex value, or -1 if not.
116 char HexCharToValue(char c)
118 char result=0;
120 if(c >= '0' && c <= '9')
121 result = c - '0';
122 else if(c >= 'a' && c <= 'f')
123 result = c - 'a' + 10;
124 else if(c >= 'A' && c <= 'F')
125 result = c - 'A' + 10;
126 else
127 result = -1;
128 return result;
132 * HexStringToValue -- convert a 2*byte_width string of characters
133 * to its little endian hex value,
134 * or -1 if not.
135 * This routine is for strings of hex values
137 unsigned long HexStringToValue(char *c, int byte_width)
139 unsigned long result=0;
140 unsigned char a,b;
141 int i=0;
143 while (i < byte_width)
145 a = HexCharToValue(*c++);
146 if (a & 0x80) return a;
147 b = HexCharToValue(*c++);
148 if (b & 0x80) return b;
149 b = (a<<4) | (b&0x0f);
150 result |= b << (i*8);
151 i++;
153 return result;
157 * Hex2Value -- convert a non-hex char delimited string
158 * to its big endian hex value.
159 * This routine is for address and byte count values
162 char *Hex2Value(char *hexIn, int *valueOut)
164 char c;
165 int digitValue;
166 int value = 0;
168 while(1)
170 c = *hexIn;
171 digitValue = HexCharToValue(c);
172 if(digitValue < 0)
174 *valueOut = value;
175 return hexIn;
177 hexIn++;
178 value = (value << 4) + digitValue;
183 * HexToMem -- convert a string to a specified
184 * number of bytes in memory.
186 * JMB -- make this thing a bit smarter so
187 * that it selects the byte width to
188 * write based on the number of bytes
189 * and the destination address alignment.
190 * This is to support writes to non-byte enabled
191 * peripheral registers...I don't like it.
192 * Beware! there are cases where it wont work
194 char *HexToMem(char *hexIn, char *memOut, int memByteCount)
196 int i;
197 unsigned long x;
198 short *memOutS=0;
199 long *memOutL=0;
200 int byte_width;
202 //determine maximum byte width
203 if (((memByteCount%2) != 0) || (((unsigned int)memOut%2) != 0))
204 byte_width = 1;
205 else if (((memByteCount % 4) != 0) || (((unsigned int)memOut % 4) != 0))
207 byte_width = 2;
208 memOutS = (short *)memOut;
210 else
212 byte_width = 4;
213 memOutL = (long *)memOut;
215 for(i = 0; i < memByteCount; i+=byte_width)
217 x = HexStringToValue(hexIn,byte_width);
218 hexIn += byte_width*2;
219 switch (byte_width)
221 case 1:
222 *memOut++ = (unsigned char) 0x000000ff & x;
223 break;
224 case 2:
225 *memOutS++ = (unsigned short) 0x0000ffff & x;
226 break;
227 case 4:
228 *memOutL++ = x;
229 break;
230 default:
231 //How could this ever happen???
232 break;
236 return hexIn;
239 char *MemToHex(char *memIn, char *hexOut, int memByteCount)
241 int i,j;
242 int byte_width;
243 unsigned long x=0;
244 unsigned short *memInS=0;
245 unsigned long *memInL=0;
247 //determine maximum byte width
248 if (((memByteCount % 2) != 0) || (((unsigned int)memIn % 2) != 0))
249 byte_width = 1;
250 else if (((memByteCount % 4) != 0) || (((unsigned int)memIn % 4) != 0))
252 byte_width = 2;
253 memInS = (short *)memIn;
255 else
257 byte_width = 4;
258 memInL = (long *)memIn;
261 for(i = 0; i < memByteCount; i+=byte_width)
263 switch (byte_width)
265 case 1:
266 x = *memIn++;
267 break;
268 case 2:
269 x = *memInS++;
270 break;
271 case 4:
272 x = *memInL++;
273 break;
274 default:
275 //How would we get here?
276 break;
279 for (j=0; j<byte_width; j++)
281 *hexOut++ = dHexChars[(x&0x000000f0)>>4];
282 *hexOut++ = dHexChars[x&0x0000000f];
283 x = x>>8;
287 *hexOut = 0;
289 return hexOut;
292 //Send just the + or - to indicate
293 //ACK or NACK
294 void GDBPutAck (char ack)
296 if (gdb.comlink == ne_gdb_serial)
297 GDBPutChar (ack);
298 #ifdef ETHER_DEBUG
299 #ifdef ethernet_exists
300 else
302 if (gdb.host_ip_address != 0)
303 nr_plugs_send_to (gdb.gdb_eth_plug, &ack, 1, 0,
304 gdb.host_ip_address,
305 gdb.host_port_number);
307 #endif
308 #endif
312 * Once a $ comes in, use GetGDBPacket to
313 * retrieve a full gdb packet, and verify
314 * checksum, and reply + or -.
316 int GetGDBPacket(char *aBuffer)
318 int checksum=0;
319 int length=0;
320 char c;
321 int x=0;
323 if (gdb.comlink == ne_gdb_serial)
325 while ((c = GDBGetChar ()) != '$') ;
327 startPacket:
328 length = 0;
329 checksum = 0;
330 while(((c = GDBGetChar()) != '#') && (length < kTextBufferSize))
332 if(c == '$')
333 goto startPacket;
334 checksum += c;
335 aBuffer[length++] = c;
336 aBuffer[length] = 0;
339 c = GDBGetChar();
340 x = HexCharToValue(c) << 4;
341 c = GDBGetChar();
342 x += HexCharToValue(c);
345 checksum &= 0xff;
347 GDB_Print2("GetPacket %d",length,0);
349 #ifdef ETHER_DEBUG
350 #ifdef ethernet_exists
351 else
353 int srcidx;
354 // wait till beginning of packet
355 while (gdb.textBuffer[0] != '$') nr_plugs_idle();
356 startEPacket:
357 length = 0;
358 checksum = 0;
359 srcidx = 1;
361 //loop until packet terminator
362 //leave enough room for the checksum at the end
363 while (((c = gdb.textBuffer[srcidx++]) != '#') && (srcidx < kTextBufferSize-2))
365 if (c == '$')
366 goto startEPacket;
368 checksum += c;
369 aBuffer[length++] = c;
372 c = gdb.textBuffer[srcidx++];
373 x = HexCharToValue(c) << 4;
374 c = gdb.textBuffer[srcidx++];
375 x += HexCharToValue (c);
377 aBuffer[length++] = 0;
379 checksum &= 0xff;
381 GDB_Print2("GetPacket %d",length,0);
383 #endif
384 #endif
386 if(checksum != x)
388 GDBPutAck('-');
389 length = 0;
391 else
393 GDBPutAck('+');
395 return length;
398 //Wait for acknowledgement
399 //Should we have some way of timing out???
400 //return TRUE if ACK
401 //return FALSE if NACK
402 int GDBGetACK (void)
404 char c;
405 if (gdb.comlink == ne_gdb_serial)
407 while (1)
409 c = GDBGetChar ();
410 if (c == '+') return (1);
411 else if (c == '-') return (0);
415 #ifdef ETHER_DEBUG
416 #ifdef ethernet_exists
417 else
419 gdb.ACKstatus = ne_gdb_ack_waiting;
420 while (1)
422 nr_plugs_idle ();
423 if (gdb.ACKstatus == ne_gdb_ack_acked)
425 gdb.ACKstatus = ne_gdb_ack_notwaiting;
426 return (1);
428 else if (gdb.ACKstatus == ne_gdb_ack_nacked)
430 gdb.ACKstatus = ne_gdb_ack_notwaiting;
431 return (0);
435 #endif
436 #endif
437 return(0);
441 * Send a packet, preceded by $,
442 * and followed by #checksum.
444 void PutGDBPacket(char *aBuffer)
446 int checksum;
447 char c;
448 char *origPtr;
449 int cnt=0;
451 origPtr = aBuffer; // Remember in case we get a NACK
452 if (gdb.comlink == ne_gdb_serial)
454 startPutSerial:
455 GDBPutChar('$');
456 checksum = 0;
457 while((c = *aBuffer++) != 0)
459 checksum += c;
460 GDBPutChar(c);
462 GDBPutChar('#');
463 GDBPutChar(dHexChars[(checksum >> 4) & 15]);
464 GDBPutChar(dHexChars[checksum & 15]);
466 if (!GDBGetACK ())
468 aBuffer = origPtr;
469 if (++cnt < GDB_RETRY_CNT) goto startPutSerial;
472 #ifdef ETHER_DEBUG
473 #ifdef ethernet_exists
474 else
476 if (gdb.host_ip_address != 0)
478 int i;
479 int result;
480 char c1;
482 i = 0;
483 c = aBuffer[i];
484 if (c==0) return; //there is no data in packet, so why bother sending
485 aBuffer[i++] = '$';
486 checksum = 0;
489 checksum += c;
490 c1 = aBuffer[i];
491 aBuffer[i++] = c;
492 c = c1;
493 } while (c != 0);
495 aBuffer[i++] = '#';
496 aBuffer[i++] = dHexChars[(checksum >> 4) & 15];
497 aBuffer[i++] = dHexChars[checksum & 15];
498 aBuffer[i++] = 0;
499 startPutEth:
500 result = nr_plugs_send_to (gdb.gdb_eth_plug, aBuffer, i, 0,
501 gdb.host_ip_address,
502 gdb.host_port_number);
504 if (!GDBGetACK ())
506 if (++cnt < GDB_RETRY_CNT) goto startPutEth;
508 aBuffer[0] = 0; //clear packet to
511 #endif
512 #endif
515 int PutTracePacket(char *aBuffer, int size)
517 int checksum;
518 #ifdef ethernet_exists
519 char c;
520 #endif
521 int i;
522 int cnt=0;
524 if (gdb.comlink == ne_gdb_serial)
526 startPutSerial:
527 GDBPutChar('$');
528 checksum = 0;
529 for (i=0; i<size; i++)
531 checksum += aBuffer[i];
532 GDBPutChar (aBuffer[i]);
534 GDBPutChar('#');
535 GDBPutChar(dHexChars[(checksum >> 4) & 15]);
536 GDBPutChar(dHexChars[checksum & 15]);
538 if (!GDBGetACK ())
540 if (++cnt < GDB_RETRY_CNT) goto startPutSerial;
543 #ifdef ETHER_DEBUG
544 #ifdef ethernet_exists
545 else
547 int result;
548 char c1;
550 checksum = 0;
551 c = '$';
552 for (i=0; i<size; i++)
554 checksum += aBuffer[i];
555 c1 = aBuffer[i];
556 aBuffer[i] = c;
557 c = c1;
559 aBuffer[i++] = c;
561 aBuffer[i++] = '#';
562 aBuffer[i++] = dHexChars[(checksum >> 4) & 15];
563 aBuffer[i++] = dHexChars[checksum & 15];
564 aBuffer[i++] = 0;
565 ethResend:
566 if (gdb.host_ip_address != 0)
568 result = nr_plugs_send_to (gdb.gdb_eth_plug, aBuffer, i, 0,
569 gdb.host_ip_address,
570 gdb.host_port_number);
572 if (!GDBGetACK ())
574 if (++cnt < GDB_RETRY_CNT) goto ethResend;
576 aBuffer[0]=0;
578 #endif
579 #endif
580 if (cnt < GDB_RETRY_CNT) return 1;
581 else return 0;
584 void PutGDBOKPacket(char *aBuffer)
586 aBuffer[0] = 'O';
587 aBuffer[1] = 'K';
588 aBuffer[2] = 0;
589 PutGDBPacket(aBuffer);
592 #if nasys_debug_core
594 //some defines used exclusively for TRACE data xfer
595 //stepsize is the ascii hex step value i.e. twice the binary length
596 #define stepsize (2*(2*sizeof(int) + sizeof (char)))
597 #define MAX_TRACE_BYTES (((int)((2*MAX_DATA_SIZE-2)/stepsize))*stepsize)
599 int Trace_Read_Intercept (char *aBuffer)
601 int cnt=0;
602 unsigned int data;
603 unsigned char code;
604 int byteCount;
605 unsigned char *w;
606 unsigned short dataAccumulate;
607 int status;
609 w = aBuffer;
610 w++; //skip past the m
611 if (*w++ == 't') //see if this is a special "memory trace" packet
613 w = Hex2Value(w,&byteCount); //get the number of bytes to transfer
615 //turn byteCount to a multiple of stepsize
616 byteCount = ((int)(byteCount/stepsize))*stepsize;
618 //wait until fifo empties
619 nm_debug_get_reg(status, np_debug_write_status);
620 while (status&np_debug_write_status_writing_mask) nm_debug_get_reg(status,np_debug_write_status);
622 // loop through total size
623 while (byteCount > 0)
625 w=aBuffer; //reset w to beginning of buffer
627 //calculate the number of bytes in this packet
628 if (byteCount > MAX_TRACE_BYTES) dataAccumulate = MAX_TRACE_BYTES;
629 else dataAccumulate = byteCount;
631 //insert data size at beginning of packet
632 w = MemToHex((char *)&dataAccumulate, w, sizeof (dataAccumulate));
634 byteCount -= dataAccumulate; //decrement byteCount
636 // accumulate a full buffer
637 for (cnt=0; cnt<dataAccumulate; cnt+=stepsize)
639 int valid;
640 nm_debug_set_reg (1, np_debug_read_sample); //begin transaction
642 //wait until data is ready
643 nm_debug_get_reg (valid, np_debug_data_valid);
644 while (!valid) nm_debug_get_reg(valid,np_debug_data_valid) ;
646 nm_debug_get_reg (data, np_debug_trace_address);
647 w = MemToHex ((char *)&data, w, sizeof (int));
649 nm_debug_get_reg (data, np_debug_trace_data);
650 w = MemToHex ((char *)&data, w, sizeof (int));
652 nm_debug_get_reg (data, np_debug_trace_code);
653 w = MemToHex ((char *)&data, w, sizeof (char));
656 //if one of our data packets doesn't make it, stop sending them
657 //if (PutTracePacket (aBuffer,dataAccumulate+4) != 1) //+4 for size filed
658 // byteCount = 0;
659 /* kenw - My module can't handle the incoming data fast enough. So
660 * send this one packet, and wait for another mt command.
662 PutTracePacket (aBuffer,dataAccumulate+4);
663 byteCount = 0;
665 return 1;
667 return 0;
671 #undef stepsize
672 #undef MAX_TRACE_BYTES
675 #endif
677 void DoGDBCommand_m(char *aBuffer)
679 char *w;
680 int startAddr,byteCount;
682 #if nasys_debug_core
683 /* intercept some access to the dbg peripheral */
684 if (Trace_Read_Intercept (aBuffer)) return;
685 #endif
687 w = aBuffer;
688 w++; // past 'm'
689 w = Hex2Value(w,&startAddr);
690 w++; // past ','
691 w = Hex2Value(w,&byteCount);
693 if (byteCount > MAX_DATA_SIZE) byteCount = MAX_DATA_SIZE;
695 // mA,L -- request memory
696 w = aBuffer;
697 w = MemToHex((char *)startAddr,w,byteCount);
698 PutGDBPacket(aBuffer);
701 void DoGDBCommand_M(char *aBuffer)
703 char *w;
704 int startAddr,byteCount;
706 w = aBuffer;
707 w++; // past 'M'
708 w = Hex2Value(w,&startAddr);
709 w++; // past ','
710 w = Hex2Value(w,&byteCount);
711 w++; // past ':'
713 GDB_Print2("M from %x to %x",startAddr,byteCount);
715 // MA,L:values -- write to memory
717 w = HexToMem(w,(char *)startAddr,byteCount);
719 // Send "OK"
720 PutGDBOKPacket(aBuffer);
723 int Debug_Read_Intercept (char *aBuffer)
725 unsigned int data;
726 int index;
727 unsigned char *w;
729 w = aBuffer;
730 w++; //skip past the g
731 if (*w++ == 'g') //see if this is a special "register read" packet
733 w = Hex2Value(w,&index); //get the index of the register to be read
735 nm_debug_get_reg (data, index);
737 //assemble the output packet
738 w=aBuffer; //reset w to beginning of buffer
739 w = MemToHex((char *)&data, w, sizeof (data));
740 *w++ = 0;
742 //now send it
743 PutTracePacket (aBuffer,sizeof (data) * 2);
745 return 1;
747 return 0;
750 // Return the values of all the registers
751 void DoGDBCommand_g(NiosGDBGlobals *g)
753 char *w;
755 if (Debug_Read_Intercept (g->textBuffer)) return;
757 w = g->textBuffer;
759 w = MemToHex((char *)(&g->registers),w,sizeof(g->registers));
760 PutGDBPacket(g->textBuffer);
761 GDB_Print2("Sent Registers",0,0);
764 int Debug_Write_Intercept (char *aBuffer)
766 unsigned int data;
767 int index;
768 unsigned char *w;
770 w = aBuffer;
771 w++; //skip past the g
772 if (*w++ == 'g') //see if this is a special "register read" packet
774 w = Hex2Value(w,&index); //get the index of the register to be written
775 w++; // past ','
776 w = Hex2Value(w,&data);
778 nm_debug_set_reg (data, index);
780 //now send it
781 // Send "OK"
782 PutGDBOKPacket(aBuffer);
784 return 1;
786 return 0;
789 void DoGDBCommand_G(NiosGDBGlobals *g)
791 char *w;
793 if (Debug_Write_Intercept (g->textBuffer)) return;
795 w = g->textBuffer;
796 w++; // skip past 'G'
797 w = HexToMem(w,(char *)(&g->registers), sizeof(g->registers) );
799 // Send "OK"
800 PutGDBOKPacket(g->textBuffer);
802 GDB_Print2("Received Registers",0,0);
805 // Return last signal value
806 void DoGDBCommand_qm(NiosGDBGlobals *g)
808 char *w;
810 w = g->textBuffer;
812 *w++ = 'S';
813 *w++ = '2';
814 *w++ = '3'; // make up a signal for now...
815 *w++ = 0;
816 PutGDBPacket(g->textBuffer);
819 void DoGDBCommand_q(NiosGDBGlobals *g)
821 #ifdef na_ssram_detect_in
822 short int* ssram_exists;
823 #endif
824 char *w;
825 w = g->textBuffer;
827 w++; /* skip past the q */
828 switch (*w) {
829 case ('A'):
830 w = g->textBuffer;
832 /* handle intialization information */
833 /* is nios_ocd available? */
834 #ifdef nasys_debug_core
835 *w++ = nasys_debug_core + '0';
836 #else
837 *w++ = '0';
838 #endif
839 *w++ = ',';
841 /* determine if the SSRAM debugger board is
842 * physically present */
843 #ifdef na_ssram_detect_in
844 ssram_exists = (short int*) na_ssram_detect_in;
845 *w++ = !(*ssram_exists) + '0';
846 #else
847 *w++ = '0';
848 #endif
849 *w++ = ',';
851 /* print out the max size of a trace packet */
852 #if nasys_debug_core
853 sprintf (w, "%04x", MAX_TRACE_BYTES);
854 #else
855 sprintf (w, "0000");
856 #endif
858 break;
859 case ('B'):
860 w = g->textBuffer;
862 /* returns 1 if it was an OCD interrupt
863 * returns 0 if it was software breakpoint */
864 if (gdb.trapNumber == nasys_debug_core_irq) {
865 *w++ = '1';
866 } else {
867 *w++ = '0';
870 *w++ = 0;
871 break;
872 default:
873 w = g->textBuffer;
875 *w = 0;
876 break;
879 PutGDBPacket(g->textBuffer);
883 void GDBInsertBreakpoint(NiosGDBGlobals *g,short *address)
885 NiosGDBBreakpoint *b;
887 GDB_Print2("breakpoint 0x%x",(int)address,0);
888 if(g->breakpointCount < kMaximumBreakpoints)
890 b = &g->breakpoint[g->breakpointCount++];
891 b->address = address;
892 b->oldContents = *b->address;
893 *b->address = 0x7904;
897 void GDBRemoveBreakpoints(NiosGDBGlobals *g)
899 NiosGDBBreakpoint *b;
900 int i;
902 for(i = 0; i < g->breakpointCount; i++)
904 b = &g->breakpoint[i];
905 *b->address = b->oldContents;
906 b->address = 0;
909 g->breakpointCount = 0;
912 int NiosInstructionIsTrap5(unsigned short instruction)
914 return instruction == 0x7905;
917 int NiosInstructionIsPrefix(unsigned short instruction)
919 return (instruction >> 11) == 0x13;
922 int NiosInstructionIsSkip(unsigned short instruction)
924 int op6;
925 int op11;
927 op6 = (instruction >> 10);
928 op11 = (instruction >> 5);
930 return (op6 == 0x14 // SKP0
931 || op6 == 0x15 // SKP1
932 || op11 == 0x3f6 // SKPRz
933 || op11 == 0x3f7 // SKPS
934 || op11 == 0x3fa); // SKPRnz
937 int NiosInstructionIsBranch(unsigned short instruction,short *pc,short **branchTargetOut)
939 int op4;
940 int op7;
941 int op10;
942 short *branchTarget = 0;
943 int result = 0;
945 op4 = (instruction >> 12);
946 op7 = (instruction >> 9);
947 op10 = (instruction >> 6);
949 if(op4 == 0x08) // BR, BSR
951 int offset;
953 result = 1;
954 offset = instruction & 0x07ff;
955 if(offset & 0x400) // sign extend
956 offset |= 0xffffF800;
957 branchTarget = pc + offset + 1; // short * gets x2 scaling automatically
959 else if(op10 == 0x1ff) // JMP, CALL
961 result = 1;
962 branchTarget = (short *)(gdb.registers.r[instruction & 31] * 2);
964 else if(op7 == 0x3d) // JMPC, CALLC
966 result = 1;
967 branchTarget = pc + 1 + (instruction & 0x0ffff);
968 #ifdef __nios32__
969 branchTarget = (short *)((int)branchTarget & 0xffffFFFc); // align 32...
970 #else
971 branchTarget = (short *)((int)branchTarget & 0xFFFe); // align 16...
972 #endif
973 branchTarget = (short *)(*(int *)branchTarget);
976 if(branchTargetOut)
977 *branchTargetOut = branchTarget;
979 return result;
982 // -------------------------
983 // Step at address
985 // "stepping" involves inserting a
986 // breakpoint at some reasonable
987 // spot later than the current program
988 // counter
990 // On the Nios processor, this is
991 // nontrivial. For example, we should
992 // not break up a PFX instruction.
994 void DoGDBCommand_s(NiosGDBGlobals *g)
996 char *w;
997 int x;
998 short *pc;
999 short *branchTarget;
1000 unsigned short instruction;
1001 int stepType;
1004 * First, if there's an argument to the packet,
1005 * set the new program-counter value
1008 w = g->textBuffer;
1009 w++;
1010 if(HexCharToValue(*w) >= 0)
1012 w = Hex2Value(w,&x);
1013 g->registers.pc = x;
1017 * Scan forward to see what the
1018 * most appropriate location(s) for
1019 * a breakpoint will be.
1021 * The rules are:
1022 * 1. If *pc == PFX, break after modified instruction.
1023 * 2. If *pc == BR,BSR,JMP,CALL, break at destination
1024 * 3. If *pc == SKIP, break right after SKIP AND after optional instruction,
1025 which might, of course, be prefixed.
1026 * 4. Anything else, just drop in the breakpoint.
1029 pc = (short *)(int)g->registers.pc;
1031 instruction = *pc;
1032 stepType = 0;
1034 if(NiosInstructionIsPrefix(instruction))
1037 * PFX instruction: skip til after it
1039 while(NiosInstructionIsPrefix(instruction))
1041 pc++;
1042 instruction = *pc;
1045 GDBInsertBreakpoint(g,pc + 1);
1046 stepType = 1;
1048 else if(NiosInstructionIsBranch(instruction,pc,&branchTarget))
1050 GDBInsertBreakpoint(g,branchTarget);
1051 stepType = 2;
1053 else if(NiosInstructionIsSkip(instruction))
1055 short *pc2;
1056 stepType = 3;
1059 * Skip gets to breaks: one after the skippable instruction,
1060 * and the skippable instruction itself.
1062 * Since Skips know how to skip over PFX's, we have to, too.
1064 pc2 = pc; // the Skip instruction
1067 pc2++;
1068 } while(NiosInstructionIsPrefix(*pc2));
1069 // pc2 now points to first non-PFX after Skip
1070 GDBInsertBreakpoint(g,pc2+1);
1071 GDBInsertBreakpoint(g,pc+1);
1073 else
1074 GDBInsertBreakpoint(g,pc+1); // the genericest case
1076 GDB_Print2("Program Steppingat 0x%x (%d)",g->registers.pc,stepType);
1079 // -----------------------------
1080 // Continue at address
1082 void DoGDBCommand_c(NiosGDBGlobals *g)
1084 char *w;
1085 int x;
1086 w = g->textBuffer;
1088 w++; // past command
1090 // Anything in the packet? if so,
1091 // use it to set the PC value
1093 if(HexCharToValue(*w) >= 0)
1095 w = Hex2Value(w,&x);
1096 g->registers.pc = x;
1099 GDB_Print2("Program Running at 0x%x",g->registers.pc,0);
1102 // ----------------------
1103 // Kill
1105 void DoGDBCommand_k(NiosGDBGlobals *g)
1107 return;
1112 * If we've somehow skidded
1113 * to a stop just after a PFX instruction
1114 * back up the program counter by one.
1116 * That way, we can't end up with an accidentally-unprefixed
1117 * instruction.
1119 * We do this just before we begin running
1120 * again, so that when the host queries our
1121 * registers, we report the place we actually
1122 * stopped.
1125 void MaybeAdjustProgramCounter(NiosGDBGlobals *g)
1127 short instruction;
1128 if(g->registers.pc)
1130 instruction = *(short *)(int)(g->registers.pc - 2);
1131 if(NiosInstructionIsPrefix(instruction))
1132 g->registers.pc -= 2;
1133 else
1135 // If the *current* instruction is Trap5, we must skip it!
1136 instruction = *(short *)(int)(g->registers.pc);
1137 if(NiosInstructionIsTrap5(instruction))
1138 g->registers.pc += 2;
1144 * GDBMainLoop - this is the main processing loop
1145 * for the GDB stub.
1147 void GDBMainLoop (void)
1149 while(1)
1151 if (GetGDBPacket(gdb.textBuffer) > 0)
1154 GDB_Print2(gdb.textBuffer,0,0);
1155 switch(gdb.textBuffer[0])
1157 case 's':
1158 DoGDBCommand_s(&gdb);
1159 goto startRunning;
1160 break;
1162 case 'c': // continue
1163 DoGDBCommand_c(&gdb);
1165 // if the PC is something other than 0, it's
1166 // probably ok to exit and go there
1168 startRunning:
1169 if(gdb.registers.pc)
1171 MaybeAdjustProgramCounter(&gdb);
1172 return;
1174 break;
1176 case 'm': // memory read
1177 DoGDBCommand_m(gdb.textBuffer);
1178 break;
1180 case 'M': // memory set
1181 DoGDBCommand_M(gdb.textBuffer);
1182 break;
1184 case 'g': // registers read
1185 DoGDBCommand_g(&gdb);
1186 break;
1188 case 'G': //registers set
1189 DoGDBCommand_G(&gdb);
1190 break;
1192 case 'k': //kill process
1193 DoGDBCommand_k(&gdb);
1194 break;
1196 case '?': // last exception value
1197 DoGDBCommand_qm(&gdb);
1198 break;
1200 case 'q':
1201 DoGDBCommand_q(&gdb);
1202 break;
1204 default: // return empty packet, means "yeah yeah".
1205 gdb.textBuffer[0] = 0;
1206 PutGDBPacket(gdb.textBuffer);
1207 break;
1214 // ----------main------------
1215 void GDBMain(void)
1217 int i;
1219 for(i = 0; i < kTextBufferSize; i++)
1220 gdb.textBuffer[i] = i;
1222 GDBRemoveBreakpoints(&gdb);
1224 #ifdef __KERNEL__
1226 * Inform the user that they need to add the symbol file for the application
1227 * that is just starting up. Display the .text .data .bss regions.
1229 if (gdb.trapNumber == 5) {
1230 extern struct task_struct *_current_task;
1231 sprintf(gdb.textBuffer,
1232 "\r\n\nGDB: trap 5 at 0x%08lX", gdb.registers.pc);
1233 puts(gdb.textBuffer);
1234 if (_current_task) {
1235 if ( _current_task->mm->start_code > _etext )
1236 sprintf(gdb.textBuffer,
1237 "\r\nGDB: Enter the following command in the nios-elf-gdb Console Window:"
1238 "\r\nGDB: add-symbol-file %s.abself 0x%08lX 0x%08lX 0x%08lX\r\n\n",
1239 _current_task->comm,
1240 (unsigned long)_current_task->mm->start_code,
1241 (unsigned long)_current_task->mm->start_data,
1242 (unsigned long)_current_task->mm->end_data );
1243 else
1244 sprintf(gdb.textBuffer,
1245 ", kernel process: %s\r\n", _current_task->comm );
1246 } else
1247 sprintf(gdb.textBuffer,
1248 ", kernel process unknown\r\n" );
1249 puts(gdb.textBuffer);
1251 #endif
1253 // Send trapnumber for breakpoint encountered. No other signals.
1255 gdb.textBuffer[0] = 'S';
1256 gdb.textBuffer[1] = '0';
1258 #if nasys_debug_core
1259 if (gdb.trapNumber == nasys_debug_core_irq)
1261 /* gdb.textBuffer[2] = '8'; */
1262 gdb.textBuffer[2] = '5';
1264 else
1266 gdb.textBuffer[2] = '5';
1268 #else
1269 gdb.textBuffer[2] = '5';
1270 #endif
1271 gdb.textBuffer[3] = 0;
1272 PutGDBPacket(gdb.textBuffer);
1274 GDB_Print2("Trap %2d At 0x%x",
1275 gdb.trapNumber,gdb.registers.pc);
1276 // printf ("Trap %d at 0x%x\n",gdb.trapNumber,gdb.registers.pc);
1277 // for (i=0;i<32;i++) printf (" register[%d] = 0x%x\n",i,gdb.registers.r[i]);
1279 GDBMainLoop ();
1282 // +----------------------------------
1283 // | gdb_eth_proc -- gets called for udp packets
1284 // | from the host bound for gdb stub
1285 #ifdef ETHER_DEBUG
1286 #ifdef ethernet_exists
1287 int gdb_eth_proc(int plug_handle,
1288 void *context,
1289 ns_plugs_packet *p,
1290 void *payload,
1291 int payload_length)
1293 int i;
1294 char *buf = (char *)payload;
1295 // if this is a stop request, set a flag to stop after nr_plugs_idle
1296 // leave it up to the host to prevent stops from being sent while stub is running???
1298 if (*buf == 3) gdb.stop = 1;
1300 // if we're waiting for an ack, check that here
1301 if (gdb.ACKstatus == ne_gdb_ack_waiting)
1303 if (buf[0] == '+')
1305 gdb.ACKstatus = ne_gdb_ack_acked;
1306 return 0;
1308 else if (buf[0] == '-')
1310 gdb.ACKstatus = ne_gdb_ack_nacked;
1311 return 0;
1314 strcpy (gdb.textBuffer, buf); //all commands should be zero terminated strings
1316 gdb.textBuffer[payload_length] = 0; //terminate string
1318 gdb.host_ip_address=((ns_plugs_ip_packet *)(p[ne_plugs_ip].header))->source_ip_address;
1319 gdb.host_port_number=((ns_plugs_udp_packet *)(p[ne_plugs_udp].header))->source_port;
1321 return 0;
1324 int nr_dbg_plugs_idle (void)
1326 int result;
1328 result = nr_plugs_idle ();
1329 if (gdb.stop)
1331 gdb.stop = 0;
1332 //;dgt2;tmp; asm ("TRAP #5");
1334 return result;
1336 #endif
1337 #endif
1341 * int main(void)
1343 * All we really do here is install our trap # 3,
1344 * and call it once, so that we're living down in
1345 * the GDBMain, trap handler.
1348 extern int StubBreakpointHandler;
1349 extern int StubHarmlessHandler;
1350 #if nasys_debug_core
1351 extern int StubHWBreakpointHandler;
1352 #endif
1353 #ifdef nasys_debug_uart
1354 extern int StubUartHandler;
1355 #endif
1357 void gdb_local_install(int active)
1359 unsigned int *vectorTable;
1360 unsigned int stubBreakpointHandler;
1361 unsigned int stubHarmlessHandler;
1362 #if nasys_debug_core
1363 unsigned int stubHWBreakpointHandler;
1364 #endif
1366 gdb.breakpointCount = 0;
1367 gdb.textBuffer[0] = 0;
1369 vectorTable = (int *)nasys_vector_table;
1370 stubBreakpointHandler = ( (unsigned int)(&StubBreakpointHandler) ) >> 1;
1371 stubHarmlessHandler = ( (unsigned int)(&StubHarmlessHandler) ) >> 1;
1372 #if nasys_debug_core
1373 stubHWBreakpointHandler = ( (unsigned int)(&StubHWBreakpointHandler) ) >> 1;
1374 #endif
1377 * Breakpoint & single step both go here
1379 vectorTable[na_BreakpointTrap] = stubBreakpointHandler;
1380 vectorTable[na_SingleStepTrap] = stubBreakpointHandler;
1381 vectorTable[na_StartGDBTrap] = active ? stubBreakpointHandler : stubHarmlessHandler;
1383 * If it exists, Hardware Breakpoint has a different entry point
1385 #if nasys_debug_core
1386 vectorTable[na_debug_peripheral_irq] = stubHWBreakpointHandler;
1387 #endif
1389 #ifndef __KERNEL__
1390 #ifdef nasys_debug_uart
1391 if (gdb.comlink == ne_gdb_serial)
1393 np_uart *uart = (np_uart *)nasys_debug_uart;
1394 unsigned int stubUartHandler = ((unsigned int)(&StubUartHandler)) >> 1;
1396 vectorTable[nasys_debug_uart_irq] = stubUartHandler; //set Uart int vector
1397 uart->np_uartcontrol = np_uartcontrol_irrdy_mask; //enable Rx intr
1399 #endif
1400 #endif
1403 void nios_gdb_install(int active)
1405 gdb.comlink = ne_gdb_serial;
1406 gdb_local_install (active);
1409 #ifdef ETHER_DEBUG
1410 #ifdef ethernet_exists
1411 void nios_gdb_install_ethernet (int active)
1413 int result;
1414 host_16 host_port = GDB_ETH_PORT;
1416 gdb.comlink = ne_gdb_ethernet;
1417 gdb_local_install (active);
1419 result = nr_plugs_create (&gdb.gdb_eth_plug, ne_plugs_udp, host_port, gdb_eth_proc, 0, 0);
1420 //if unabled to open ethernet plug, switch back to default serial interface
1421 if (result)
1423 printf ("nr_plugs_create failed %d\n",result);
1424 gdb.comlink = ne_gdb_serial;
1425 return;
1427 result = nr_plugs_connect (gdb.gdb_eth_plug, 0, -1, -1);
1428 if (result)
1430 printf ("nr_plugs_connect fialed %d\n",result);
1431 gdb.comlink = ne_gdb_serial;
1432 return;
1435 #endif
1436 #endif
1438 #ifdef nios_gdb_breakpoint
1439 #undef nios_gdb_breakpoint
1440 #endif
1442 void nios_gdb_breakpoint(void)
1445 * If you arrived here, you didn't include
1446 * the file "nios_peripherals.h", which
1447 * defines nios_gdb_breakpoint as a
1448 * macro that expands to TRAP 5.
1450 * (No problem, you can step out
1451 * of this routine.)
1453 //;dgt2;tmp; asm("TRAP 5");
1456 // end of file