root/arch/sparc/kernel/sparc-stub.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. get_sun4cpte
  2. get_sun4csegmap
  3. flush_cache_all_nop
  4. copy_ttentry
  5. eh_init
  6. exceptionHandler
  7. hex
  8. getpacket
  9. putpacket
  10. mem2hex
  11. hex2mem
  12. set_debug_traps
  13. computeSignal
  14. hexToInt
  15. handle_exception
  16. breakpoint

   1 /* $Id: sparc-stub.c,v 1.15 1996/04/04 12:41:35 davem Exp $
   2  * sparc-stub.c:  KGDB support for the Linux kernel.
   3  *
   4  * Modifications to run under Linux
   5  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
   6  *
   7  * This file originally came from the gdb sources, and the
   8  * copyright notices have been retained below.
   9  */
  10 
  11 /****************************************************************************
  12 
  13                 THIS SOFTWARE IS NOT COPYRIGHTED
  14 
  15    HP offers the following for use in the public domain.  HP makes no
  16    warranty with regard to the software or it's performance and the
  17    user accepts the software "AS IS" with all faults.
  18 
  19    HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
  20    TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  21    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  22 
  23 ****************************************************************************/
  24 
  25 /****************************************************************************
  26  *  Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
  27  *
  28  *  Module name: remcom.c $
  29  *  Revision: 1.34 $
  30  *  Date: 91/03/09 12:29:49 $
  31  *  Contributor:     Lake Stevens Instrument Division$
  32  *
  33  *  Description:     low level support for gdb debugger. $
  34  *
  35  *  Considerations:  only works on target hardware $
  36  *
  37  *  Written by:      Glenn Engel $
  38  *  ModuleState:     Experimental $
  39  *
  40  *  NOTES:           See Below $
  41  *
  42  *  Modified for SPARC by Stu Grossman, Cygnus Support.
  43  *
  44  *  This code has been extensively tested on the Fujitsu SPARClite demo board.
  45  *
  46  *  To enable debugger support, two things need to happen.  One, a
  47  *  call to set_debug_traps() is necessary in order to allow any breakpoints
  48  *  or error conditions to be properly intercepted and reported to gdb.
  49  *  Two, a breakpoint needs to be generated to begin communication.  This
  50  *  is most easily accomplished by a call to breakpoint().  Breakpoint()
  51  *  simulates a breakpoint by executing a trap #1.
  52  *
  53  *************
  54  *
  55  *    The following gdb commands are supported:
  56  *
  57  * command          function                               Return value
  58  *
  59  *    g             return the value of the CPU registers  hex data or ENN
  60  *    G             set the value of the CPU registers     OK or ENN
  61  *
  62  *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
  63  *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
  64  *
  65  *    c             Resume at current address              SNN   ( signal NN)
  66  *    cAA..AA       Continue at address AA..AA             SNN
  67  *
  68  *    s             Step one instruction                   SNN
  69  *    sAA..AA       Step one instruction from AA..AA       SNN
  70  *
  71  *    k             kill
  72  *
  73  *    ?             What was the last sigval ?             SNN   (signal NN)
  74  *
  75  *    bBB..BB       Set baud rate to BB..BB                OK or BNN, then sets
  76  *                                                         baud rate
  77  *
  78  * All commands and responses are sent with a packet which includes a
  79  * checksum.  A packet consists of
  80  *
  81  * $<packet info>#<checksum>.
  82  *
  83  * where
  84  * <packet info> :: <characters representing the command or response>
  85  * <checksum>    :: < two hex digits computed as modulo 256 sum of <packetinfo>>
  86  *
  87  * When a packet is received, it is first acknowledged with either '+' or '-'.
  88  * '+' indicates a successful transfer.  '-' indicates a failed transfer.
  89  *
  90  * Example:
  91  *
  92  * Host:                  Reply:
  93  * $m0,10#2a               +$00010203040506070809101112131415#42
  94  *
  95  ****************************************************************************/
  96 
  97 #include <linux/kernel.h>
  98 #include <linux/string.h>
  99 #include <linux/mm.h>
 100 
 101 #include <asm/system.h>
 102 #include <asm/signal.h>
 103 #include <asm/oplib.h>
 104 #include <asm/head.h>
 105 #include <asm/traps.h>
 106 #include <asm/system.h>
 107 #include <asm/vac-ops.h>
 108 #include <asm/kgdb.h>
 109 #include <asm/pgtable.h>
 110 /*
 111  *
 112  * external low-level support routines
 113  */
 114 
 115 extern void putDebugChar(char);   /* write a single character      */
 116 extern char getDebugChar(void);   /* read and return a single char */
 117 
 118 /*
 119  * BUFMAX defines the maximum number of characters in inbound/outbound buffers
 120  * at least NUMREGBYTES*2 are needed for register packets
 121  */
 122 #define BUFMAX 2048
 123 
 124 static int initialized = 0;     /* !0 means we've been initialized */
 125 
 126 static const char hexchars[]="0123456789abcdef";
 127 
 128 #define NUMREGS 72
 129 
 130 /* Number of bytes of registers.  */
 131 #define NUMREGBYTES (NUMREGS * 4)
 132 enum regnames {G0, G1, G2, G3, G4, G5, G6, G7,
 133                  O0, O1, O2, O3, O4, O5, SP, O7,
 134                  L0, L1, L2, L3, L4, L5, L6, L7,
 135                  I0, I1, I2, I3, I4, I5, FP, I7,
 136 
 137                  F0, F1, F2, F3, F4, F5, F6, F7,
 138                  F8, F9, F10, F11, F12, F13, F14, F15,
 139                  F16, F17, F18, F19, F20, F21, F22, F23,
 140                  F24, F25, F26, F27, F28, F29, F30, F31,
 141                  Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR };
 142 
 143 
 144 extern void trap_low(void);  /* In arch/sparc/kernel/entry.S */
 145 
 146 unsigned long get_sun4cpte(unsigned long addr)
     /* [previous][next][first][last][top][bottom][index][help] */
 147 {
 148         unsigned long entry;
 149 
 150         __asm__ __volatile__("\n\tlda [%1] %2, %0\n\t" : 
 151                              "=r" (entry) :
 152                              "r" (addr), "i" (ASI_PTE));
 153         return entry;
 154 }
 155 
 156 unsigned long get_sun4csegmap(unsigned long addr)
     /* [previous][next][first][last][top][bottom][index][help] */
 157 {
 158         unsigned long entry;
 159 
 160         __asm__ __volatile__("\n\tlduba [%1] %2, %0\n\t" : 
 161                              "=r" (entry) :
 162                              "r" (addr), "i" (ASI_SEGMAP));
 163         return entry;
 164 }
 165 
 166 static void flush_cache_all_nop(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 167 {
 168 }
 169 
 170 /* Place where we save old trap entries for restoration */
 171 struct tt_entry kgdb_savettable[256];
 172 typedef void (*trapfunc_t)(void);
 173 
 174 /* Helper routine for manipulation of kgdb_savettable */
 175 static inline void copy_ttentry(struct tt_entry *src, struct tt_entry *dest)
     /* [previous][next][first][last][top][bottom][index][help] */
 176 {
 177         dest->inst_one = src->inst_one;
 178         dest->inst_two = src->inst_two;
 179         dest->inst_three = src->inst_three;
 180         dest->inst_four = src->inst_four;
 181 }
 182 
 183 /* Initialize the kgdb_savettable so that debugging can commence */
 184 static void eh_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 185 {
 186         int i, flags;
 187 
 188         save_flags(flags); cli();
 189         for(i=0; i < 256; i++)
 190                 copy_ttentry(&sparc_ttable[i], &kgdb_savettable[i]);
 191         restore_flags(flags);
 192 }
 193 
 194 /* Install an exception handler for kgdb */
 195 static void exceptionHandler(int tnum, trapfunc_t trap_entry)
     /* [previous][next][first][last][top][bottom][index][help] */
 196 {
 197         unsigned long te_addr = (unsigned long) trap_entry;
 198         int flags;
 199 
 200         /* We are dorking with a live trap table, all irqs off */
 201         save_flags(flags); cli();
 202 
 203         /* Make new vector */
 204         sparc_ttable[tnum].inst_one =
 205                 SPARC_BRANCH((unsigned long) te_addr,
 206                              (unsigned long) &sparc_ttable[tnum].inst_one);
 207         sparc_ttable[tnum].inst_two = SPARC_RD_PSR_L0;
 208         sparc_ttable[tnum].inst_three = SPARC_NOP;
 209         sparc_ttable[tnum].inst_four = SPARC_NOP;
 210 
 211         restore_flags(flags);
 212 }
 213 
 214 /* Convert ch from a hex digit to an int */
 215 static int
 216 hex(unsigned char ch)
     /* [previous][next][first][last][top][bottom][index][help] */
 217 {
 218         if (ch >= 'a' && ch <= 'f')
 219                 return ch-'a'+10;
 220         if (ch >= '0' && ch <= '9')
 221                 return ch-'0';
 222         if (ch >= 'A' && ch <= 'F')
 223                 return ch-'A'+10;
 224         return -1;
 225 }
 226 
 227 /* scan for the sequence $<data>#<checksum>     */
 228 static void
 229 getpacket(char *buffer)
     /* [previous][next][first][last][top][bottom][index][help] */
 230 {
 231         unsigned char checksum;
 232         unsigned char xmitcsum;
 233         int i;
 234         int count;
 235         unsigned char ch;
 236 
 237         do {
 238                 /* wait around for the start character, ignore all other characters */
 239                 while ((ch = (getDebugChar() & 0x7f)) != '$') ;
 240 
 241                 checksum = 0;
 242                 xmitcsum = -1;
 243 
 244                 count = 0;
 245 
 246                 /* now, read until a # or end of buffer is found */
 247                 while (count < BUFMAX) {
 248                         ch = getDebugChar() & 0x7f;
 249                         if (ch == '#')
 250                                 break;
 251                         checksum = checksum + ch;
 252                         buffer[count] = ch;
 253                         count = count + 1;
 254                 }
 255 
 256                 if (count >= BUFMAX)
 257                         continue;
 258 
 259                 buffer[count] = 0;
 260 
 261                 if (ch == '#') {
 262                         xmitcsum = hex(getDebugChar() & 0x7f) << 4;
 263                         xmitcsum |= hex(getDebugChar() & 0x7f);
 264                         if (checksum != xmitcsum)
 265                                 putDebugChar('-');      /* failed checksum */
 266                         else {
 267                                 putDebugChar('+'); /* successful transfer */
 268                                 /* if a sequence char is present, reply the ID */
 269                                 if (buffer[2] == ':') {
 270                                         putDebugChar(buffer[0]);
 271                                         putDebugChar(buffer[1]);
 272                                         /* remove sequence chars from buffer */
 273                                         count = strlen(buffer);
 274                                         for (i=3; i <= count; i++)
 275                                                 buffer[i-3] = buffer[i];
 276                                 }
 277                         }
 278                 }
 279         } while (checksum != xmitcsum);
 280 }
 281 
 282 /* send the packet in buffer.  */
 283 
 284 static void
 285 putpacket(unsigned char *buffer)
     /* [previous][next][first][last][top][bottom][index][help] */
 286 {
 287         unsigned char checksum;
 288         int count;
 289         unsigned char ch, recv;
 290 
 291         /*  $<packet info>#<checksum>. */
 292         do {
 293                 putDebugChar('$');
 294                 checksum = 0;
 295                 count = 0;
 296 
 297                 while ((ch = buffer[count])) {
 298                         putDebugChar(ch);
 299                         checksum += ch;
 300                         count += 1;
 301                 }
 302 
 303                 putDebugChar('#');
 304                 putDebugChar(hexchars[checksum >> 4]);
 305                 putDebugChar(hexchars[checksum & 0xf]);
 306                 recv = getDebugChar();
 307         } while ((recv & 0x7f) != '+');
 308 }
 309 
 310 static char remcomInBuffer[BUFMAX];
 311 static char remcomOutBuffer[BUFMAX];
 312 
 313 /* Convert the memory pointed to by mem into hex, placing result in buf.
 314  * Return a pointer to the last char put in buf (null), in case of mem fault,
 315  * return 0.
 316  */
 317 
 318 static unsigned char *
 319 mem2hex(char *mem, char *buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 320 {
 321         unsigned char ch;
 322 
 323         while (count-- > 0) {
 324                 ch = *mem++;
 325                 *buf++ = hexchars[ch >> 4];
 326                 *buf++ = hexchars[ch & 0xf];
 327         }
 328 
 329         *buf = 0;
 330         return buf;
 331 }
 332 
 333 /* convert the hex array pointed to by buf into binary to be placed in mem
 334  * return a pointer to the character AFTER the last byte written.
 335 */
 336 static char *
 337 hex2mem(char *buf, char *mem, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 338 {
 339         int i;
 340         unsigned char ch;
 341 
 342         for (i=0; i<count; i++) {
 343 
 344                 ch = hex(*buf++) << 4;
 345                 ch |= hex(*buf++);
 346                 *mem++ = ch;
 347         }
 348         return mem;
 349 }
 350 
 351 /* This table contains the mapping between SPARC hardware trap types, and
 352    signals, which are primarily what GDB understands.  It also indicates
 353    which hardware traps we need to commandeer when initializing the stub. */
 354 
 355 static struct hard_trap_info
 356 {
 357   unsigned char tt;             /* Trap type code for SPARC */
 358   unsigned char signo;          /* Signal that we map this trap into */
 359 } hard_trap_info[] = {
 360   {SP_TRAP_SBPT, SIGTRAP},      /* ta 1 - Linux/KGDB software breakpoint */
 361   {0, 0}                        /* Must be last */
 362 };
 363 
 364 /* Set up exception handlers for tracing and breakpoints */
 365 
 366 void
 367 set_debug_traps(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 368 {
 369         struct hard_trap_info *ht;
 370         unsigned long flags;
 371         unsigned char c;
 372 
 373         save_flags(flags); cli();
 374         flush_cache_all = flush_cache_all_nop;
 375 
 376         /* Initialize our copy of the Linux Sparc trap table */
 377         eh_init();
 378 
 379         for (ht = hard_trap_info; ht->tt && ht->signo; ht++) {
 380                 /* Only if it doesn't destroy our fault handlers */
 381                 if((ht->tt != SP_TRAP_TFLT) && 
 382                    (ht->tt != SP_TRAP_DFLT))
 383                         exceptionHandler(ht->tt, trap_low);
 384         }
 385 
 386         /* In case GDB is started before us, ack any packets (presumably
 387          * "$?#xx") sitting there.
 388          */
 389 
 390         while((c = getDebugChar()) != '$');
 391         while((c = getDebugChar()) != '#');
 392         c = getDebugChar(); /* eat first csum byte */
 393         c = getDebugChar(); /* eat second csum byte */
 394         putDebugChar('+'); /* ack it */
 395 
 396         initialized = 1; /* connect! */
 397         restore_flags(flags);
 398 }
 399 
 400 /* Convert the SPARC hardware trap type code to a unix signal number. */
 401 
 402 static int
 403 computeSignal(int tt)
     /* [previous][next][first][last][top][bottom][index][help] */
 404 {
 405         struct hard_trap_info *ht;
 406 
 407         for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
 408                 if (ht->tt == tt)
 409                         return ht->signo;
 410 
 411         return SIGHUP;         /* default for things we don't know about */
 412 }
 413 
 414 /*
 415  * While we find nice hex chars, build an int.
 416  * Return number of chars processed.
 417  */
 418 
 419 static int
 420 hexToInt(char **ptr, int *intValue)
     /* [previous][next][first][last][top][bottom][index][help] */
 421 {
 422         int numChars = 0;
 423         int hexValue;
 424 
 425         *intValue = 0;
 426 
 427         while (**ptr) {
 428                 hexValue = hex(**ptr);
 429                 if (hexValue < 0)
 430                         break;
 431 
 432                 *intValue = (*intValue << 4) | hexValue;
 433                 numChars ++;
 434 
 435                 (*ptr)++;
 436         }
 437 
 438         return (numChars);
 439 }
 440 
 441 /*
 442  * This function does all command processing for interfacing to gdb.  It
 443  * returns 1 if you should skip the instruction at the trap address, 0
 444  * otherwise.
 445  */
 446 
 447 extern void breakinst(void);
 448 
 449 void
 450 handle_exception (unsigned long *registers)
     /* [previous][next][first][last][top][bottom][index][help] */
 451 {
 452         int tt;       /* Trap type */
 453         int sigval;
 454         int addr;
 455         int length;
 456         char *ptr;
 457         unsigned long *sp;
 458 
 459         /* First, we must force all of the windows to be spilled out */
 460 
 461         asm("save %sp, -64, %sp\n\t"
 462             "save %sp, -64, %sp\n\t"
 463             "save %sp, -64, %sp\n\t"
 464             "save %sp, -64, %sp\n\t"
 465             "save %sp, -64, %sp\n\t"
 466             "save %sp, -64, %sp\n\t"
 467             "save %sp, -64, %sp\n\t"
 468             "save %sp, -64, %sp\n\t"
 469             "restore\n\t"
 470             "restore\n\t"
 471             "restore\n\t"
 472             "restore\n\t"
 473             "restore\n\t"
 474             "restore\n\t"
 475             "restore\n\t"
 476             "restore\n\t");
 477 
 478         if (registers[PC] == (unsigned long)breakinst) {
 479                 /* Skip over breakpoint trap insn */
 480                 registers[PC] = registers[NPC];
 481                 registers[NPC] += 4;
 482         }
 483 
 484         sp = (unsigned long *)registers[SP];
 485 
 486         tt = (registers[TBR] >> 4) & 0xff;
 487 
 488         /* reply to host that an exception has occurred */
 489         sigval = computeSignal(tt);
 490         ptr = remcomOutBuffer;
 491 
 492         *ptr++ = 'T';
 493         *ptr++ = hexchars[sigval >> 4];
 494         *ptr++ = hexchars[sigval & 0xf];
 495 
 496         *ptr++ = hexchars[PC >> 4];
 497         *ptr++ = hexchars[PC & 0xf];
 498         *ptr++ = ':';
 499         ptr = mem2hex((char *)&registers[PC], ptr, 4);
 500         *ptr++ = ';';
 501 
 502         *ptr++ = hexchars[FP >> 4];
 503         *ptr++ = hexchars[FP & 0xf];
 504         *ptr++ = ':';
 505         ptr = mem2hex((char *) (sp + 8 + 6), ptr, 4); /* FP */
 506         *ptr++ = ';';
 507 
 508         *ptr++ = hexchars[SP >> 4];
 509         *ptr++ = hexchars[SP & 0xf];
 510         *ptr++ = ':';
 511         ptr = mem2hex((char *)&sp, ptr, 4);
 512         *ptr++ = ';';
 513 
 514         *ptr++ = hexchars[NPC >> 4];
 515         *ptr++ = hexchars[NPC & 0xf];
 516         *ptr++ = ':';
 517         ptr = mem2hex((char *)&registers[NPC], ptr, 4);
 518         *ptr++ = ';';
 519 
 520         *ptr++ = hexchars[O7 >> 4];
 521         *ptr++ = hexchars[O7 & 0xf];
 522         *ptr++ = ':';
 523         ptr = mem2hex((char *)&registers[O7], ptr, 4);
 524         *ptr++ = ';';
 525 
 526         *ptr++ = 0;
 527 
 528         putpacket(remcomOutBuffer);
 529 
 530         /* XXX We may want to add some features dealing with poking the
 531          * XXX page tables, the real ones on the srmmu, and what is currently
 532          * XXX loaded in the sun4/sun4c tlb at this point in time.  But this
 533          * XXX also required hacking to the gdb sources directly...
 534          */
 535 
 536         while (1) {
 537                 remcomOutBuffer[0] = 0;
 538 
 539                 getpacket(remcomInBuffer);
 540                 switch (remcomInBuffer[0]) {
 541                 case '?':
 542                         remcomOutBuffer[0] = 'S';
 543                         remcomOutBuffer[1] = hexchars[sigval >> 4];
 544                         remcomOutBuffer[2] = hexchars[sigval & 0xf];
 545                         remcomOutBuffer[3] = 0;
 546                         break;
 547 
 548                 case 'd':
 549                         /* toggle debug flag */
 550                         break;
 551 
 552                 case 'g':               /* return the value of the CPU registers */
 553                 {
 554                         ptr = remcomOutBuffer;
 555                         /* G & O regs */
 556                         ptr = mem2hex((char *)registers, ptr, 16 * 4);
 557                         /* L & I regs */
 558                         ptr = mem2hex((char *) (sp + 0), ptr, 16 * 4);
 559                         /* Floating point */
 560                         memset(ptr, '0', 32 * 8);
 561                         /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
 562                         mem2hex((char *)&registers[Y], (ptr + 32 * 4 * 2), (8 * 4));
 563                 }
 564                         break;
 565 
 566                 case 'G':          /* set the value of the CPU registers - return OK */
 567                 {
 568                         unsigned long *newsp, psr;
 569 
 570                         psr = registers[PSR];
 571 
 572                         ptr = &remcomInBuffer[1];
 573                         /* G & O regs */
 574                         hex2mem(ptr, (char *)registers, 16 * 4);
 575                         /* L & I regs */
 576                         hex2mem(ptr + 16 * 4 * 2, (char *) (sp + 0), 16 * 4);
 577                         /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
 578                         hex2mem(ptr + 64 * 4 * 2, (char *)&registers[Y], 8 * 4);
 579 
 580                         /* See if the stack pointer has moved.  If so,
 581                          * then copy the saved locals and ins to the
 582                          * new location.  This keeps the window
 583                          * overflow and underflow routines happy.
 584                          */
 585 
 586                         newsp = (unsigned long *)registers[SP];
 587                         if (sp != newsp)
 588                                 sp = memcpy(newsp, sp, 16 * 4);
 589 
 590                         /* Don't allow CWP to be modified. */
 591 
 592                         if (psr != registers[PSR])
 593                                 registers[PSR] = (psr & 0x1f) | (registers[PSR] & ~0x1f);
 594 
 595                         strcpy(remcomOutBuffer,"OK");
 596                 }
 597                         break;
 598 
 599                 case 'm':         /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
 600                         /* Try to read %x,%x.  */
 601 
 602                         ptr = &remcomInBuffer[1];
 603 
 604                         if (hexToInt(&ptr, &addr)
 605                             && *ptr++ == ','
 606                             && hexToInt(&ptr, &length)) {
 607                                 if (mem2hex((char *)addr, remcomOutBuffer, length))
 608                                         break;
 609 
 610                                 strcpy (remcomOutBuffer, "E03");
 611                         } else {
 612                                 strcpy(remcomOutBuffer,"E01");
 613                         }
 614                         break;
 615 
 616                 case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
 617                         /* Try to read '%x,%x:'.  */
 618 
 619                         ptr = &remcomInBuffer[1];
 620 
 621                         if (hexToInt(&ptr, &addr)
 622                             && *ptr++ == ','
 623                             && hexToInt(&ptr, &length)
 624                             && *ptr++ == ':') {
 625                                 if (hex2mem(ptr, (char *)addr, length)) {
 626                                         strcpy(remcomOutBuffer, "OK");
 627                                 } else {
 628                                         strcpy(remcomOutBuffer, "E03");
 629                                 }
 630                         } else {
 631                                 strcpy(remcomOutBuffer, "E02");
 632                         }
 633                         break;
 634 
 635                 case 'c':    /* cAA..AA    Continue at address AA..AA(optional) */
 636                         /* try to read optional parameter, pc unchanged if no parm */
 637 
 638                         ptr = &remcomInBuffer[1];
 639                         if (hexToInt(&ptr, &addr)) {
 640                                 registers[PC] = addr;
 641                                 registers[NPC] = addr + 4;
 642                         }
 643 
 644 /* Need to flush the instruction cache here, as we may have deposited a
 645  * breakpoint, and the icache probably has no way of knowing that a data ref to
 646  * some location may have changed something that is in the instruction cache.
 647  */
 648                         flush_cache_all();
 649                         return;
 650 
 651                         /* kill the program */
 652                 case 'k' :              /* do nothing */
 653                         break;
 654                 case 'r':               /* Reset */
 655                         asm ("call 0\n\t"
 656                              "nop\n\t");
 657                         break;
 658                 }                       /* switch */
 659 
 660                 /* reply to the request */
 661                 putpacket(remcomOutBuffer);
 662         } /* while(1) */
 663 }
 664 
 665 /* This function will generate a breakpoint exception.  It is used at the
 666    beginning of a program to sync up with a debugger and can be used
 667    otherwise as a quick means to stop program execution and "break" into
 668    the debugger. */
 669 
 670 void
 671 breakpoint(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 672 {
 673         if (!initialized)
 674                 return;
 675 
 676         /* Again, watch those c-prefixes for solaris/elf kernels */
 677 #ifndef __svr4__
 678         asm("   .globl _breakinst
 679 
 680              _breakinst: ta 1
 681             ");
 682 #else
 683         asm("   .globl breakinst
 684 
 685              breakinst: ta 1
 686             ");
 687 #endif
 688 }

/* [previous][next][first][last][top][bottom][index][help] */