1130812Smarcel/****************************************************************************
2130812Smarcel
3130812Smarcel		THIS SOFTWARE IS NOT COPYRIGHTED
4130812Smarcel
5130812Smarcel   HP offers the following for use in the public domain.  HP makes no
6130812Smarcel   warranty with regard to the software or it's performance and the
7130812Smarcel   user accepts the software "AS IS" with all faults.
8130812Smarcel
9130812Smarcel   HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
10130812Smarcel   TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
11130812Smarcel   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
12130812Smarcel
13130812Smarcel****************************************************************************/
14130812Smarcel
15130812Smarcel/****************************************************************************
16130812Smarcel *  Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
17130812Smarcel *
18130812Smarcel *  Module name: remcom.c $
19130812Smarcel *  Revision: 1.34 $
20130812Smarcel *  Date: 91/03/09 12:29:49 $
21130812Smarcel *  Contributor:     Lake Stevens Instrument Division$
22130812Smarcel *
23130812Smarcel *  Description:     low level support for gdb debugger. $
24130812Smarcel *
25130812Smarcel *  Considerations:  only works on target hardware $
26130812Smarcel *
27130812Smarcel *  Written by:      Glenn Engel $
28130812Smarcel *  ModuleState:     Experimental $
29130812Smarcel *
30130812Smarcel *  NOTES:           See Below $
31130812Smarcel *
32130812Smarcel *  Modified for 386 by Jim Kingdon, Cygnus Support.
33130812Smarcel *
34130812Smarcel *  To enable debugger support, two things need to happen.  One, a
35130812Smarcel *  call to set_debug_traps() is necessary in order to allow any breakpoints
36130812Smarcel *  or error conditions to be properly intercepted and reported to gdb.
37130812Smarcel *  Two, a breakpoint needs to be generated to begin communication.  This
38130812Smarcel *  is most easily accomplished by a call to breakpoint().  Breakpoint()
39130812Smarcel *  simulates a breakpoint by executing a trap #1.
40130812Smarcel *
41130812Smarcel *  The external function exceptionHandler() is
42130812Smarcel *  used to attach a specific handler to a specific 386 vector number.
43130812Smarcel *  It should use the same privilege level it runs at.  It should
44130812Smarcel *  install it as an interrupt gate so that interrupts are masked
45130812Smarcel *  while the handler runs.
46130812Smarcel *
47130812Smarcel *  Because gdb will sometimes write to the stack area to execute function
48130812Smarcel *  calls, this program cannot rely on using the supervisor stack so it
49130812Smarcel *  uses it's own stack area reserved in the int array remcomStack.
50130812Smarcel *
51130812Smarcel *************
52130812Smarcel *
53130812Smarcel *    The following gdb commands are supported:
54130812Smarcel *
55130812Smarcel * command          function                               Return value
56130812Smarcel *
57130812Smarcel *    g             return the value of the CPU registers  hex data or ENN
58130812Smarcel *    G             set the value of the CPU registers     OK or ENN
59130812Smarcel *
60130812Smarcel *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
61130812Smarcel *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
62130812Smarcel *
63130812Smarcel *    c             Resume at current address              SNN   ( signal NN)
64130812Smarcel *    cAA..AA       Continue at address AA..AA             SNN
65130812Smarcel *
66130812Smarcel *    s             Step one instruction                   SNN
67130812Smarcel *    sAA..AA       Step one instruction from AA..AA       SNN
68130812Smarcel *
69130812Smarcel *    k             kill
70130812Smarcel *
71130812Smarcel *    ?             What was the last sigval ?             SNN   (signal NN)
72130812Smarcel *
73130812Smarcel * All commands and responses are sent with a packet which includes a
74130812Smarcel * checksum.  A packet consists of
75130812Smarcel *
76130812Smarcel * $<packet info>#<checksum>.
77130812Smarcel *
78130812Smarcel * where
79130812Smarcel * <packet info> :: <characters representing the command or response>
80130812Smarcel * <checksum>    :: < two hex digits computed as modulo 256 sum of <packetinfo>>
81130812Smarcel *
82130812Smarcel * When a packet is received, it is first acknowledged with either '+' or '-'.
83130812Smarcel * '+' indicates a successful transfer.  '-' indicates a failed transfer.
84130812Smarcel *
85130812Smarcel * Example:
86130812Smarcel *
87130812Smarcel * Host:                  Reply:
88130812Smarcel * $m0,10#2a               +$00010203040506070809101112131415#42
89130812Smarcel *
90130812Smarcel ****************************************************************************/
91130812Smarcel
92130812Smarcel#include <stdio.h>
93130812Smarcel#include <string.h>
94130812Smarcel
95130812Smarcel/************************************************************************
96130812Smarcel *
97130812Smarcel * external low-level support routines
98130812Smarcel */
99130812Smarcel
100130812Smarcelextern void putDebugChar();	/* write a single character      */
101130812Smarcelextern int getDebugChar();	/* read and return a single char */
102130812Smarcelextern void exceptionHandler();	/* assign an exception handler   */
103130812Smarcel
104130812Smarcel/************************************************************************/
105130812Smarcel/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
106130812Smarcel/* at least NUMREGBYTES*2 are needed for register packets */
107130812Smarcel#define BUFMAX 400
108130812Smarcel
109130812Smarcelstatic char initialized;  /* boolean flag. != 0 means we've been initialized */
110130812Smarcel
111130812Smarcelint     remote_debug;
112130812Smarcel/*  debug >  0 prints ill-formed commands in valid packets & checksum errors */
113130812Smarcel
114130812Smarcelstatic const char hexchars[]="0123456789abcdef";
115130812Smarcel
116130812Smarcel/* Number of registers.  */
117130812Smarcel#define NUMREGS	16
118130812Smarcel
119130812Smarcel/* Number of bytes of registers.  */
120130812Smarcel#define NUMREGBYTES (NUMREGS * 4)
121130812Smarcel
122130812Smarcelenum regnames {EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI,
123130812Smarcel	       PC /* also known as eip */,
124130812Smarcel	       PS /* also known as eflags */,
125130812Smarcel	       CS, SS, DS, ES, FS, GS};
126130812Smarcel
127130812Smarcel/*
128130812Smarcel * these should not be static cuz they can be used outside this module
129130812Smarcel */
130130812Smarcelint registers[NUMREGS];
131130812Smarcel
132130812Smarcel#define STACKSIZE 10000
133130812Smarcelint remcomStack[STACKSIZE/sizeof(int)];
134130812Smarcelstatic int* stackPtr = &remcomStack[STACKSIZE/sizeof(int) - 1];
135130812Smarcel
136130812Smarcel/***************************  ASSEMBLY CODE MACROS *************************/
137130812Smarcel/* 									   */
138130812Smarcel
139130812Smarcelextern void
140130812Smarcelreturn_to_prog ();
141130812Smarcel
142130812Smarcel/* Restore the program's registers (including the stack pointer, which
143130812Smarcel   means we get the right stack and don't have to worry about popping our
144130812Smarcel   return address and any stack frames and so on) and return.  */
145130812Smarcelasm(".text");
146130812Smarcelasm(".globl _return_to_prog");
147130812Smarcelasm("_return_to_prog:");
148130812Smarcelasm("        movw _registers+44, %ss");
149130812Smarcelasm("        movl _registers+16, %esp");
150130812Smarcelasm("        movl _registers+4, %ecx");
151130812Smarcelasm("        movl _registers+8, %edx");
152130812Smarcelasm("        movl _registers+12, %ebx");
153130812Smarcelasm("        movl _registers+20, %ebp");
154130812Smarcelasm("        movl _registers+24, %esi");
155130812Smarcelasm("        movl _registers+28, %edi");
156130812Smarcelasm("        movw _registers+48, %ds");
157130812Smarcelasm("        movw _registers+52, %es");
158130812Smarcelasm("        movw _registers+56, %fs");
159130812Smarcelasm("        movw _registers+60, %gs");
160130812Smarcelasm("        movl _registers+36, %eax");
161130812Smarcelasm("        pushl %eax");  /* saved eflags */
162130812Smarcelasm("        movl _registers+40, %eax");
163130812Smarcelasm("        pushl %eax");  /* saved cs */
164130812Smarcelasm("        movl _registers+32, %eax");
165130812Smarcelasm("        pushl %eax");  /* saved eip */
166130812Smarcelasm("        movl _registers, %eax");
167130812Smarcel/* use iret to restore pc and flags together so
168130812Smarcel   that trace flag works right.  */
169130812Smarcelasm("        iret");
170130812Smarcel
171130812Smarcel#define BREAKPOINT() asm("   int $3");
172130812Smarcel
173130812Smarcel/* Put the error code here just in case the user cares.  */
174130812Smarcelint gdb_i386errcode;
175130812Smarcel/* Likewise, the vector number here (since GDB only gets the signal
176130812Smarcel   number through the usual means, and that's not very specific).  */
177130812Smarcelint gdb_i386vector = -1;
178130812Smarcel
179130812Smarcel/* GDB stores segment registers in 32-bit words (that's just the way
180130812Smarcel   m-i386v.h is written).  So zero the appropriate areas in registers.  */
181130812Smarcel#define SAVE_REGISTERS1() \
182130812Smarcel  asm ("movl %eax, _registers");                                   	  \
183130812Smarcel  asm ("movl %ecx, _registers+4");			  		     \
184130812Smarcel  asm ("movl %edx, _registers+8");			  		     \
185130812Smarcel  asm ("movl %ebx, _registers+12");			  		     \
186130812Smarcel  asm ("movl %ebp, _registers+20");			  		     \
187130812Smarcel  asm ("movl %esi, _registers+24");			  		     \
188130812Smarcel  asm ("movl %edi, _registers+28");			  		     \
189130812Smarcel  asm ("movw $0, %ax");							     \
190130812Smarcel  asm ("movw %ds, _registers+48");			  		     \
191130812Smarcel  asm ("movw %ax, _registers+50");					     \
192130812Smarcel  asm ("movw %es, _registers+52");			  		     \
193130812Smarcel  asm ("movw %ax, _registers+54");					     \
194130812Smarcel  asm ("movw %fs, _registers+56");			  		     \
195130812Smarcel  asm ("movw %ax, _registers+58");					     \
196130812Smarcel  asm ("movw %gs, _registers+60");			  		     \
197130812Smarcel  asm ("movw %ax, _registers+62");
198130812Smarcel#define SAVE_ERRCODE() \
199130812Smarcel  asm ("popl %ebx");                                  \
200130812Smarcel  asm ("movl %ebx, _gdb_i386errcode");
201130812Smarcel#define SAVE_REGISTERS2() \
202130812Smarcel  asm ("popl %ebx"); /* old eip */			  		     \
203130812Smarcel  asm ("movl %ebx, _registers+32");			  		     \
204130812Smarcel  asm ("popl %ebx");	 /* old cs */			  		     \
205130812Smarcel  asm ("movl %ebx, _registers+40");			  		     \
206130812Smarcel  asm ("movw %ax, _registers+42");                                           \
207130812Smarcel  asm ("popl %ebx");	 /* old eflags */		  		     \
208130812Smarcel  asm ("movl %ebx, _registers+36");			 		     \
209130812Smarcel  /* Now that we've done the pops, we can save the stack pointer.");  */   \
210130812Smarcel  asm ("movw %ss, _registers+44");					     \
211130812Smarcel  asm ("movw %ax, _registers+46");     	       	       	       	       	     \
212130812Smarcel  asm ("movl %esp, _registers+16");
213130812Smarcel
214130812Smarcel/* See if mem_fault_routine is set, if so just IRET to that address.  */
215130812Smarcel#define CHECK_FAULT() \
216130812Smarcel  asm ("cmpl $0, _mem_fault_routine");					   \
217130812Smarcel  asm ("jne mem_fault");
218130812Smarcel
219130812Smarcelasm (".text");
220130812Smarcelasm ("mem_fault:");
221130812Smarcel/* OK to clobber temp registers; we're just going to end up in set_mem_err.  */
222130812Smarcel/* Pop error code from the stack and save it.  */
223130812Smarcelasm ("     popl %eax");
224130812Smarcelasm ("     movl %eax, _gdb_i386errcode");
225130812Smarcel
226130812Smarcelasm ("     popl %eax"); /* eip */
227130812Smarcel/* We don't want to return there, we want to return to the function
228130812Smarcel   pointed to by mem_fault_routine instead.  */
229130812Smarcelasm ("     movl _mem_fault_routine, %eax");
230130812Smarcelasm ("     popl %ecx"); /* cs (low 16 bits; junk in hi 16 bits).  */
231130812Smarcelasm ("     popl %edx"); /* eflags */
232130812Smarcel
233130812Smarcel/* Remove this stack frame; when we do the iret, we will be going to
234130812Smarcel   the start of a function, so we want the stack to look just like it
235130812Smarcel   would after a "call" instruction.  */
236130812Smarcelasm ("     leave");
237130812Smarcel
238130812Smarcel/* Push the stuff that iret wants.  */
239130812Smarcelasm ("     pushl %edx"); /* eflags */
240130812Smarcelasm ("     pushl %ecx"); /* cs */
241130812Smarcelasm ("     pushl %eax"); /* eip */
242130812Smarcel
243130812Smarcel/* Zero mem_fault_routine.  */
244130812Smarcelasm ("     movl $0, %eax");
245130812Smarcelasm ("     movl %eax, _mem_fault_routine");
246130812Smarcel
247130812Smarcelasm ("iret");
248130812Smarcel
249130812Smarcel#define CALL_HOOK() asm("call _remcomHandler");
250130812Smarcel
251130812Smarcel/* This function is called when a i386 exception occurs.  It saves
252130812Smarcel * all the cpu regs in the _registers array, munges the stack a bit,
253130812Smarcel * and invokes an exception handler (remcom_handler).
254130812Smarcel *
255130812Smarcel * stack on entry:                       stack on exit:
256130812Smarcel *   old eflags                          vector number
257130812Smarcel *   old cs (zero-filled to 32 bits)
258130812Smarcel *   old eip
259130812Smarcel *
260130812Smarcel */
261130812Smarcelextern void _catchException3();
262130812Smarcelasm(".text");
263130812Smarcelasm(".globl __catchException3");
264130812Smarcelasm("__catchException3:");
265130812SmarcelSAVE_REGISTERS1();
266130812SmarcelSAVE_REGISTERS2();
267130812Smarcelasm ("pushl $3");
268130812SmarcelCALL_HOOK();
269130812Smarcel
270130812Smarcel/* Same thing for exception 1.  */
271130812Smarcelextern void _catchException1();
272130812Smarcelasm(".text");
273130812Smarcelasm(".globl __catchException1");
274130812Smarcelasm("__catchException1:");
275130812SmarcelSAVE_REGISTERS1();
276130812SmarcelSAVE_REGISTERS2();
277130812Smarcelasm ("pushl $1");
278130812SmarcelCALL_HOOK();
279130812Smarcel
280130812Smarcel/* Same thing for exception 0.  */
281130812Smarcelextern void _catchException0();
282130812Smarcelasm(".text");
283130812Smarcelasm(".globl __catchException0");
284130812Smarcelasm("__catchException0:");
285130812SmarcelSAVE_REGISTERS1();
286130812SmarcelSAVE_REGISTERS2();
287130812Smarcelasm ("pushl $0");
288130812SmarcelCALL_HOOK();
289130812Smarcel
290130812Smarcel/* Same thing for exception 4.  */
291130812Smarcelextern void _catchException4();
292130812Smarcelasm(".text");
293130812Smarcelasm(".globl __catchException4");
294130812Smarcelasm("__catchException4:");
295130812SmarcelSAVE_REGISTERS1();
296130812SmarcelSAVE_REGISTERS2();
297130812Smarcelasm ("pushl $4");
298130812SmarcelCALL_HOOK();
299130812Smarcel
300130812Smarcel/* Same thing for exception 5.  */
301130812Smarcelextern void _catchException5();
302130812Smarcelasm(".text");
303130812Smarcelasm(".globl __catchException5");
304130812Smarcelasm("__catchException5:");
305130812SmarcelSAVE_REGISTERS1();
306130812SmarcelSAVE_REGISTERS2();
307130812Smarcelasm ("pushl $5");
308130812SmarcelCALL_HOOK();
309130812Smarcel
310130812Smarcel/* Same thing for exception 6.  */
311130812Smarcelextern void _catchException6();
312130812Smarcelasm(".text");
313130812Smarcelasm(".globl __catchException6");
314130812Smarcelasm("__catchException6:");
315130812SmarcelSAVE_REGISTERS1();
316130812SmarcelSAVE_REGISTERS2();
317130812Smarcelasm ("pushl $6");
318130812SmarcelCALL_HOOK();
319130812Smarcel
320130812Smarcel/* Same thing for exception 7.  */
321130812Smarcelextern void _catchException7();
322130812Smarcelasm(".text");
323130812Smarcelasm(".globl __catchException7");
324130812Smarcelasm("__catchException7:");
325130812SmarcelSAVE_REGISTERS1();
326130812SmarcelSAVE_REGISTERS2();
327130812Smarcelasm ("pushl $7");
328130812SmarcelCALL_HOOK();
329130812Smarcel
330130812Smarcel/* Same thing for exception 8.  */
331130812Smarcelextern void _catchException8();
332130812Smarcelasm(".text");
333130812Smarcelasm(".globl __catchException8");
334130812Smarcelasm("__catchException8:");
335130812SmarcelSAVE_REGISTERS1();
336130812SmarcelSAVE_ERRCODE();
337130812SmarcelSAVE_REGISTERS2();
338130812Smarcelasm ("pushl $8");
339130812SmarcelCALL_HOOK();
340130812Smarcel
341130812Smarcel/* Same thing for exception 9.  */
342130812Smarcelextern void _catchException9();
343130812Smarcelasm(".text");
344130812Smarcelasm(".globl __catchException9");
345130812Smarcelasm("__catchException9:");
346130812SmarcelSAVE_REGISTERS1();
347130812SmarcelSAVE_REGISTERS2();
348130812Smarcelasm ("pushl $9");
349130812SmarcelCALL_HOOK();
350130812Smarcel
351130812Smarcel/* Same thing for exception 10.  */
352130812Smarcelextern void _catchException10();
353130812Smarcelasm(".text");
354130812Smarcelasm(".globl __catchException10");
355130812Smarcelasm("__catchException10:");
356130812SmarcelSAVE_REGISTERS1();
357130812SmarcelSAVE_ERRCODE();
358130812SmarcelSAVE_REGISTERS2();
359130812Smarcelasm ("pushl $10");
360130812SmarcelCALL_HOOK();
361130812Smarcel
362130812Smarcel/* Same thing for exception 12.  */
363130812Smarcelextern void _catchException12();
364130812Smarcelasm(".text");
365130812Smarcelasm(".globl __catchException12");
366130812Smarcelasm("__catchException12:");
367130812SmarcelSAVE_REGISTERS1();
368130812SmarcelSAVE_ERRCODE();
369130812SmarcelSAVE_REGISTERS2();
370130812Smarcelasm ("pushl $12");
371130812SmarcelCALL_HOOK();
372130812Smarcel
373130812Smarcel/* Same thing for exception 16.  */
374130812Smarcelextern void _catchException16();
375130812Smarcelasm(".text");
376130812Smarcelasm(".globl __catchException16");
377130812Smarcelasm("__catchException16:");
378130812SmarcelSAVE_REGISTERS1();
379130812SmarcelSAVE_REGISTERS2();
380130812Smarcelasm ("pushl $16");
381130812SmarcelCALL_HOOK();
382130812Smarcel
383130812Smarcel/* For 13, 11, and 14 we have to deal with the CHECK_FAULT stuff.  */
384130812Smarcel
385130812Smarcel/* Same thing for exception 13.  */
386130812Smarcelextern void _catchException13 ();
387130812Smarcelasm (".text");
388130812Smarcelasm (".globl __catchException13");
389130812Smarcelasm ("__catchException13:");
390130812SmarcelCHECK_FAULT();
391130812SmarcelSAVE_REGISTERS1();
392130812SmarcelSAVE_ERRCODE();
393130812SmarcelSAVE_REGISTERS2();
394130812Smarcelasm ("pushl $13");
395130812SmarcelCALL_HOOK();
396130812Smarcel
397130812Smarcel/* Same thing for exception 11.  */
398130812Smarcelextern void _catchException11 ();
399130812Smarcelasm (".text");
400130812Smarcelasm (".globl __catchException11");
401130812Smarcelasm ("__catchException11:");
402130812SmarcelCHECK_FAULT();
403130812SmarcelSAVE_REGISTERS1();
404130812SmarcelSAVE_ERRCODE();
405130812SmarcelSAVE_REGISTERS2();
406130812Smarcelasm ("pushl $11");
407130812SmarcelCALL_HOOK();
408130812Smarcel
409130812Smarcel/* Same thing for exception 14.  */
410130812Smarcelextern void _catchException14 ();
411130812Smarcelasm (".text");
412130812Smarcelasm (".globl __catchException14");
413130812Smarcelasm ("__catchException14:");
414130812SmarcelCHECK_FAULT();
415130812SmarcelSAVE_REGISTERS1();
416130812SmarcelSAVE_ERRCODE();
417130812SmarcelSAVE_REGISTERS2();
418130812Smarcelasm ("pushl $14");
419130812SmarcelCALL_HOOK();
420130812Smarcel
421130812Smarcel/*
422130812Smarcel * remcomHandler is a front end for handle_exception.  It moves the
423130812Smarcel * stack pointer into an area reserved for debugger use.
424130812Smarcel */
425130812Smarcelasm("_remcomHandler:");
426130812Smarcelasm("           popl %eax");        /* pop off return address     */
427130812Smarcelasm("           popl %eax");      /* get the exception number   */
428130812Smarcelasm("		movl _stackPtr, %esp"); /* move to remcom stack area  */
429130812Smarcelasm("		pushl %eax");	/* push exception onto stack  */
430130812Smarcelasm("		call  _handle_exception");    /* this never returns */
431130812Smarcel
432130812Smarcelvoid
433130812Smarcel_returnFromException ()
434130812Smarcel{
435130812Smarcel  return_to_prog ();
436130812Smarcel}
437130812Smarcel
438130812Smarcelint
439130812Smarcelhex (ch)
440130812Smarcel     char ch;
441130812Smarcel{
442130812Smarcel  if ((ch >= 'a') && (ch <= 'f'))
443130812Smarcel    return (ch - 'a' + 10);
444130812Smarcel  if ((ch >= '0') && (ch <= '9'))
445130812Smarcel    return (ch - '0');
446130812Smarcel  if ((ch >= 'A') && (ch <= 'F'))
447130812Smarcel    return (ch - 'A' + 10);
448130812Smarcel  return (-1);
449130812Smarcel}
450130812Smarcel
451130812Smarcelstatic char remcomInBuffer[BUFMAX];
452130812Smarcelstatic char remcomOutBuffer[BUFMAX];
453130812Smarcel
454130812Smarcel/* scan for the sequence $<data>#<checksum>     */
455130812Smarcel
456130812Smarcelunsigned char *
457130812Smarcelgetpacket (void)
458130812Smarcel{
459130812Smarcel  unsigned char *buffer = &remcomInBuffer[0];
460130812Smarcel  unsigned char checksum;
461130812Smarcel  unsigned char xmitcsum;
462130812Smarcel  int count;
463130812Smarcel  char ch;
464130812Smarcel
465130812Smarcel  while (1)
466130812Smarcel    {
467130812Smarcel      /* wait around for the start character, ignore all other characters */
468130812Smarcel      while ((ch = getDebugChar ()) != '$')
469130812Smarcel	;
470130812Smarcel
471130812Smarcel    retry:
472130812Smarcel      checksum = 0;
473130812Smarcel      xmitcsum = -1;
474130812Smarcel      count = 0;
475130812Smarcel
476130812Smarcel      /* now, read until a # or end of buffer is found */
477130812Smarcel      while (count < BUFMAX)
478130812Smarcel	{
479130812Smarcel	  ch = getDebugChar ();
480130812Smarcel	  if (ch == '$')
481130812Smarcel	    goto retry;
482130812Smarcel	  if (ch == '#')
483130812Smarcel	    break;
484130812Smarcel	  checksum = checksum + ch;
485130812Smarcel	  buffer[count] = ch;
486130812Smarcel	  count = count + 1;
487130812Smarcel	}
488130812Smarcel      buffer[count] = 0;
489130812Smarcel
490130812Smarcel      if (ch == '#')
491130812Smarcel	{
492130812Smarcel	  ch = getDebugChar ();
493130812Smarcel	  xmitcsum = hex (ch) << 4;
494130812Smarcel	  ch = getDebugChar ();
495130812Smarcel	  xmitcsum += hex (ch);
496130812Smarcel
497130812Smarcel	  if (checksum != xmitcsum)
498130812Smarcel	    {
499130812Smarcel	      if (remote_debug)
500130812Smarcel		{
501130812Smarcel		  fprintf (stderr,
502130812Smarcel			   "bad checksum.  My count = 0x%x, sent=0x%x. buf=%s\n",
503130812Smarcel			   checksum, xmitcsum, buffer);
504130812Smarcel		}
505130812Smarcel	      putDebugChar ('-');	/* failed checksum */
506130812Smarcel	    }
507130812Smarcel	  else
508130812Smarcel	    {
509130812Smarcel	      putDebugChar ('+');	/* successful transfer */
510130812Smarcel
511130812Smarcel	      /* if a sequence char is present, reply the sequence ID */
512130812Smarcel	      if (buffer[2] == ':')
513130812Smarcel		{
514130812Smarcel		  putDebugChar (buffer[0]);
515130812Smarcel		  putDebugChar (buffer[1]);
516130812Smarcel
517130812Smarcel		  return &buffer[3];
518130812Smarcel		}
519130812Smarcel
520130812Smarcel	      return &buffer[0];
521130812Smarcel	    }
522130812Smarcel	}
523130812Smarcel    }
524130812Smarcel}
525130812Smarcel
526130812Smarcel/* send the packet in buffer.  */
527130812Smarcel
528130812Smarcelvoid
529130812Smarcelputpacket (unsigned char *buffer)
530130812Smarcel{
531130812Smarcel  unsigned char checksum;
532130812Smarcel  int count;
533130812Smarcel  char ch;
534130812Smarcel
535130812Smarcel  /*  $<packet info>#<checksum>. */
536130812Smarcel  do
537130812Smarcel    {
538130812Smarcel      putDebugChar ('$');
539130812Smarcel      checksum = 0;
540130812Smarcel      count = 0;
541130812Smarcel
542130812Smarcel      while (ch = buffer[count])
543130812Smarcel	{
544130812Smarcel	  putDebugChar (ch);
545130812Smarcel	  checksum += ch;
546130812Smarcel	  count += 1;
547130812Smarcel	}
548130812Smarcel
549130812Smarcel      putDebugChar ('#');
550130812Smarcel      putDebugChar (hexchars[checksum >> 4]);
551130812Smarcel      putDebugChar (hexchars[checksum % 16]);
552130812Smarcel
553130812Smarcel    }
554130812Smarcel  while (getDebugChar () != '+');
555130812Smarcel}
556130812Smarcel
557130812Smarcelvoid
558130812Smarceldebug_error (format, parm)
559130812Smarcel     char *format;
560130812Smarcel     char *parm;
561130812Smarcel{
562130812Smarcel  if (remote_debug)
563130812Smarcel    fprintf (stderr, format, parm);
564130812Smarcel}
565130812Smarcel
566130812Smarcel/* Address of a routine to RTE to if we get a memory fault.  */
567130812Smarcelstatic void (*volatile mem_fault_routine) () = NULL;
568130812Smarcel
569130812Smarcel/* Indicate to caller of mem2hex or hex2mem that there has been an
570130812Smarcel   error.  */
571130812Smarcelstatic volatile int mem_err = 0;
572130812Smarcel
573130812Smarcelvoid
574130812Smarcelset_mem_err (void)
575130812Smarcel{
576130812Smarcel  mem_err = 1;
577130812Smarcel}
578130812Smarcel
579130812Smarcel/* These are separate functions so that they are so short and sweet
580130812Smarcel   that the compiler won't save any registers (if there is a fault
581130812Smarcel   to mem_fault, they won't get restored, so there better not be any
582130812Smarcel   saved).  */
583130812Smarcelint
584130812Smarcelget_char (char *addr)
585130812Smarcel{
586130812Smarcel  return *addr;
587130812Smarcel}
588130812Smarcel
589130812Smarcelvoid
590130812Smarcelset_char (char *addr, int val)
591130812Smarcel{
592130812Smarcel  *addr = val;
593130812Smarcel}
594130812Smarcel
595130812Smarcel/* convert the memory pointed to by mem into hex, placing result in buf */
596130812Smarcel/* return a pointer to the last char put in buf (null) */
597130812Smarcel/* If MAY_FAULT is non-zero, then we should set mem_err in response to
598130812Smarcel   a fault; if zero treat a fault like any other fault in the stub.  */
599130812Smarcelchar *
600130812Smarcelmem2hex (mem, buf, count, may_fault)
601130812Smarcel     char *mem;
602130812Smarcel     char *buf;
603130812Smarcel     int count;
604130812Smarcel     int may_fault;
605130812Smarcel{
606130812Smarcel  int i;
607130812Smarcel  unsigned char ch;
608130812Smarcel
609130812Smarcel  if (may_fault)
610130812Smarcel    mem_fault_routine = set_mem_err;
611130812Smarcel  for (i = 0; i < count; i++)
612130812Smarcel    {
613130812Smarcel      ch = get_char (mem++);
614130812Smarcel      if (may_fault && mem_err)
615130812Smarcel	return (buf);
616130812Smarcel      *buf++ = hexchars[ch >> 4];
617130812Smarcel      *buf++ = hexchars[ch % 16];
618130812Smarcel    }
619130812Smarcel  *buf = 0;
620130812Smarcel  if (may_fault)
621130812Smarcel    mem_fault_routine = NULL;
622130812Smarcel  return (buf);
623130812Smarcel}
624130812Smarcel
625130812Smarcel/* convert the hex array pointed to by buf into binary to be placed in mem */
626130812Smarcel/* return a pointer to the character AFTER the last byte written */
627130812Smarcelchar *
628130812Smarcelhex2mem (buf, mem, count, may_fault)
629130812Smarcel     char *buf;
630130812Smarcel     char *mem;
631130812Smarcel     int count;
632130812Smarcel     int may_fault;
633130812Smarcel{
634130812Smarcel  int i;
635130812Smarcel  unsigned char ch;
636130812Smarcel
637130812Smarcel  if (may_fault)
638130812Smarcel    mem_fault_routine = set_mem_err;
639130812Smarcel  for (i = 0; i < count; i++)
640130812Smarcel    {
641130812Smarcel      ch = hex (*buf++) << 4;
642130812Smarcel      ch = ch + hex (*buf++);
643130812Smarcel      set_char (mem++, ch);
644130812Smarcel      if (may_fault && mem_err)
645130812Smarcel	return (mem);
646130812Smarcel    }
647130812Smarcel  if (may_fault)
648130812Smarcel    mem_fault_routine = NULL;
649130812Smarcel  return (mem);
650130812Smarcel}
651130812Smarcel
652130812Smarcel/* this function takes the 386 exception vector and attempts to
653130812Smarcel   translate this number into a unix compatible signal value */
654130812Smarcelint
655130812SmarcelcomputeSignal (int exceptionVector)
656130812Smarcel{
657130812Smarcel  int sigval;
658130812Smarcel  switch (exceptionVector)
659130812Smarcel    {
660130812Smarcel    case 0:
661130812Smarcel      sigval = 8;
662130812Smarcel      break;			/* divide by zero */
663130812Smarcel    case 1:
664130812Smarcel      sigval = 5;
665130812Smarcel      break;			/* debug exception */
666130812Smarcel    case 3:
667130812Smarcel      sigval = 5;
668130812Smarcel      break;			/* breakpoint */
669130812Smarcel    case 4:
670130812Smarcel      sigval = 16;
671130812Smarcel      break;			/* into instruction (overflow) */
672130812Smarcel    case 5:
673130812Smarcel      sigval = 16;
674130812Smarcel      break;			/* bound instruction */
675130812Smarcel    case 6:
676130812Smarcel      sigval = 4;
677130812Smarcel      break;			/* Invalid opcode */
678130812Smarcel    case 7:
679130812Smarcel      sigval = 8;
680130812Smarcel      break;			/* coprocessor not available */
681130812Smarcel    case 8:
682130812Smarcel      sigval = 7;
683130812Smarcel      break;			/* double fault */
684130812Smarcel    case 9:
685130812Smarcel      sigval = 11;
686130812Smarcel      break;			/* coprocessor segment overrun */
687130812Smarcel    case 10:
688130812Smarcel      sigval = 11;
689130812Smarcel      break;			/* Invalid TSS */
690130812Smarcel    case 11:
691130812Smarcel      sigval = 11;
692130812Smarcel      break;			/* Segment not present */
693130812Smarcel    case 12:
694130812Smarcel      sigval = 11;
695130812Smarcel      break;			/* stack exception */
696130812Smarcel    case 13:
697130812Smarcel      sigval = 11;
698130812Smarcel      break;			/* general protection */
699130812Smarcel    case 14:
700130812Smarcel      sigval = 11;
701130812Smarcel      break;			/* page fault */
702130812Smarcel    case 16:
703130812Smarcel      sigval = 7;
704130812Smarcel      break;			/* coprocessor error */
705130812Smarcel    default:
706130812Smarcel      sigval = 7;		/* "software generated" */
707130812Smarcel    }
708130812Smarcel  return (sigval);
709130812Smarcel}
710130812Smarcel
711130812Smarcel/**********************************************/
712130812Smarcel/* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
713130812Smarcel/* RETURN NUMBER OF CHARS PROCESSED           */
714130812Smarcel/**********************************************/
715130812Smarcelint
716130812SmarcelhexToInt (char **ptr, int *intValue)
717130812Smarcel{
718130812Smarcel  int numChars = 0;
719130812Smarcel  int hexValue;
720130812Smarcel
721130812Smarcel  *intValue = 0;
722130812Smarcel
723130812Smarcel  while (**ptr)
724130812Smarcel    {
725130812Smarcel      hexValue = hex (**ptr);
726130812Smarcel      if (hexValue >= 0)
727130812Smarcel	{
728130812Smarcel	  *intValue = (*intValue << 4) | hexValue;
729130812Smarcel	  numChars++;
730130812Smarcel	}
731130812Smarcel      else
732130812Smarcel	break;
733130812Smarcel
734130812Smarcel      (*ptr)++;
735130812Smarcel    }
736130812Smarcel
737130812Smarcel  return (numChars);
738130812Smarcel}
739130812Smarcel
740130812Smarcel/*
741130812Smarcel * This function does all command procesing for interfacing to gdb.
742130812Smarcel */
743130812Smarcelvoid
744130812Smarcelhandle_exception (int exceptionVector)
745130812Smarcel{
746130812Smarcel  int sigval, stepping;
747130812Smarcel  int addr, length;
748130812Smarcel  char *ptr;
749130812Smarcel  int newPC;
750130812Smarcel
751130812Smarcel  gdb_i386vector = exceptionVector;
752130812Smarcel
753130812Smarcel  if (remote_debug)
754130812Smarcel    {
755130812Smarcel      printf ("vector=%d, sr=0x%x, pc=0x%x\n",
756130812Smarcel	      exceptionVector, registers[PS], registers[PC]);
757130812Smarcel    }
758130812Smarcel
759130812Smarcel  /* reply to host that an exception has occurred */
760130812Smarcel  sigval = computeSignal (exceptionVector);
761130812Smarcel
762130812Smarcel  ptr = remcomOutBuffer;
763130812Smarcel
764130812Smarcel  *ptr++ = 'T';			/* notify gdb with signo, PC, FP and SP */
765130812Smarcel  *ptr++ = hexchars[sigval >> 4];
766130812Smarcel  *ptr++ = hexchars[sigval & 0xf];
767130812Smarcel
768130812Smarcel  *ptr++ = hexchars[ESP];
769130812Smarcel  *ptr++ = ':';
770130812Smarcel  ptr = mem2hex((char *)&registers[ESP], ptr, 4, 0);	/* SP */
771130812Smarcel  *ptr++ = ';';
772130812Smarcel
773130812Smarcel  *ptr++ = hexchars[EBP];
774130812Smarcel  *ptr++ = ':';
775130812Smarcel  ptr = mem2hex((char *)&registers[EBP], ptr, 4, 0); 	/* FP */
776130812Smarcel  *ptr++ = ';';
777130812Smarcel
778130812Smarcel  *ptr++ = hexchars[PC];
779130812Smarcel  *ptr++ = ':';
780130812Smarcel  ptr = mem2hex((char *)&registers[PC], ptr, 4, 0); 	/* PC */
781130812Smarcel  *ptr++ = ';';
782130812Smarcel
783130812Smarcel  *ptr = '\0'
784130812Smarcel
785130812Smarcel  putpacket (remcomOutBuffer);
786130812Smarcel
787130812Smarcel  stepping = 0;
788130812Smarcel
789130812Smarcel  while (1 == 1)
790130812Smarcel    {
791130812Smarcel      remcomOutBuffer[0] = 0;
792130812Smarcel      ptr = getpacket ();
793130812Smarcel
794130812Smarcel      switch (*ptr++)
795130812Smarcel	{
796130812Smarcel	case '?':
797130812Smarcel	  remcomOutBuffer[0] = 'S';
798130812Smarcel	  remcomOutBuffer[1] = hexchars[sigval >> 4];
799130812Smarcel	  remcomOutBuffer[2] = hexchars[sigval % 16];
800130812Smarcel	  remcomOutBuffer[3] = 0;
801130812Smarcel	  break;
802130812Smarcel	case 'd':
803130812Smarcel	  remote_debug = !(remote_debug);	/* toggle debug flag */
804130812Smarcel	  break;
805130812Smarcel	case 'g':		/* return the value of the CPU registers */
806130812Smarcel	  mem2hex ((char *) registers, remcomOutBuffer, NUMREGBYTES, 0);
807130812Smarcel	  break;
808130812Smarcel	case 'G':		/* set the value of the CPU registers - return OK */
809130812Smarcel	  hex2mem (ptr, (char *) registers, NUMREGBYTES, 0);
810130812Smarcel	  strcpy (remcomOutBuffer, "OK");
811130812Smarcel	  break;
812130812Smarcel	case 'P':		/* set the value of a single CPU register - return OK */
813130812Smarcel	  {
814130812Smarcel	    int regno;
815130812Smarcel
816130812Smarcel	    if (hexToInt (&ptr, &regno) && *ptr++ == '=')
817130812Smarcel	      if (regno >= 0 && regno < NUMREGS)
818130812Smarcel		{
819130812Smarcel		  hex2mem (ptr, (char *) &registers[regno], 4, 0);
820130812Smarcel		  strcpy (remcomOutBuffer, "OK");
821130812Smarcel		  break;
822130812Smarcel		}
823130812Smarcel
824130812Smarcel	    strcpy (remcomOutBuffer, "E01");
825130812Smarcel	    break;
826130812Smarcel	  }
827130812Smarcel
828130812Smarcel	  /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
829130812Smarcel	case 'm':
830130812Smarcel	  /* TRY TO READ %x,%x.  IF SUCCEED, SET PTR = 0 */
831130812Smarcel	  if (hexToInt (&ptr, &addr))
832130812Smarcel	    if (*(ptr++) == ',')
833130812Smarcel	      if (hexToInt (&ptr, &length))
834130812Smarcel		{
835130812Smarcel		  ptr = 0;
836130812Smarcel		  mem_err = 0;
837130812Smarcel		  mem2hex ((char *) addr, remcomOutBuffer, length, 1);
838130812Smarcel		  if (mem_err)
839130812Smarcel		    {
840130812Smarcel		      strcpy (remcomOutBuffer, "E03");
841130812Smarcel		      debug_error ("memory fault");
842130812Smarcel		    }
843130812Smarcel		}
844130812Smarcel
845130812Smarcel	  if (ptr)
846130812Smarcel	    {
847130812Smarcel	      strcpy (remcomOutBuffer, "E01");
848130812Smarcel	    }
849130812Smarcel	  break;
850130812Smarcel
851130812Smarcel	  /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
852130812Smarcel	case 'M':
853130812Smarcel	  /* TRY TO READ '%x,%x:'.  IF SUCCEED, SET PTR = 0 */
854130812Smarcel	  if (hexToInt (&ptr, &addr))
855130812Smarcel	    if (*(ptr++) == ',')
856130812Smarcel	      if (hexToInt (&ptr, &length))
857130812Smarcel		if (*(ptr++) == ':')
858130812Smarcel		  {
859130812Smarcel		    mem_err = 0;
860130812Smarcel		    hex2mem (ptr, (char *) addr, length, 1);
861130812Smarcel
862130812Smarcel		    if (mem_err)
863130812Smarcel		      {
864130812Smarcel			strcpy (remcomOutBuffer, "E03");
865130812Smarcel			debug_error ("memory fault");
866130812Smarcel		      }
867130812Smarcel		    else
868130812Smarcel		      {
869130812Smarcel			strcpy (remcomOutBuffer, "OK");
870130812Smarcel		      }
871130812Smarcel
872130812Smarcel		    ptr = 0;
873130812Smarcel		  }
874130812Smarcel	  if (ptr)
875130812Smarcel	    {
876130812Smarcel	      strcpy (remcomOutBuffer, "E02");
877130812Smarcel	    }
878130812Smarcel	  break;
879130812Smarcel
880130812Smarcel	  /* cAA..AA    Continue at address AA..AA(optional) */
881130812Smarcel	  /* sAA..AA   Step one instruction from AA..AA(optional) */
882130812Smarcel	case 's':
883130812Smarcel	  stepping = 1;
884130812Smarcel	case 'c':
885130812Smarcel	  /* try to read optional parameter, pc unchanged if no parm */
886130812Smarcel	  if (hexToInt (&ptr, &addr))
887130812Smarcel	    registers[PC] = addr;
888130812Smarcel
889130812Smarcel	  newPC = registers[PC];
890130812Smarcel
891130812Smarcel	  /* clear the trace bit */
892130812Smarcel	  registers[PS] &= 0xfffffeff;
893130812Smarcel
894130812Smarcel	  /* set the trace bit if we're stepping */
895130812Smarcel	  if (stepping)
896130812Smarcel	    registers[PS] |= 0x100;
897130812Smarcel
898130812Smarcel	  _returnFromException ();	/* this is a jump */
899130812Smarcel	  break;
900130812Smarcel
901130812Smarcel	  /* kill the program */
902130812Smarcel	case 'k':		/* do nothing */
903130812Smarcel#if 0
904130812Smarcel	  /* Huh? This doesn't look like "nothing".
905130812Smarcel	     m68k-stub.c and sparc-stub.c don't have it.  */
906130812Smarcel	  BREAKPOINT ();
907130812Smarcel#endif
908130812Smarcel	  break;
909130812Smarcel	}			/* switch */
910130812Smarcel
911130812Smarcel      /* reply to the request */
912130812Smarcel      putpacket (remcomOutBuffer);
913130812Smarcel    }
914130812Smarcel}
915130812Smarcel
916130812Smarcel/* this function is used to set up exception handlers for tracing and
917130812Smarcel   breakpoints */
918130812Smarcelvoid
919130812Smarcelset_debug_traps (void)
920130812Smarcel{
921130812Smarcel  stackPtr = &remcomStack[STACKSIZE / sizeof (int) - 1];
922130812Smarcel
923130812Smarcel  exceptionHandler (0, _catchException0);
924130812Smarcel  exceptionHandler (1, _catchException1);
925130812Smarcel  exceptionHandler (3, _catchException3);
926130812Smarcel  exceptionHandler (4, _catchException4);
927130812Smarcel  exceptionHandler (5, _catchException5);
928130812Smarcel  exceptionHandler (6, _catchException6);
929130812Smarcel  exceptionHandler (7, _catchException7);
930130812Smarcel  exceptionHandler (8, _catchException8);
931130812Smarcel  exceptionHandler (9, _catchException9);
932130812Smarcel  exceptionHandler (10, _catchException10);
933130812Smarcel  exceptionHandler (11, _catchException11);
934130812Smarcel  exceptionHandler (12, _catchException12);
935130812Smarcel  exceptionHandler (13, _catchException13);
936130812Smarcel  exceptionHandler (14, _catchException14);
937130812Smarcel  exceptionHandler (16, _catchException16);
938130812Smarcel
939130812Smarcel  initialized = 1;
940130812Smarcel}
941130812Smarcel
942130812Smarcel/* This function will generate a breakpoint exception.  It is used at the
943130812Smarcel   beginning of a program to sync up with a debugger and can be used
944130812Smarcel   otherwise as a quick means to stop program execution and "break" into
945130812Smarcel   the debugger. */
946130812Smarcel
947130812Smarcelvoid
948130812Smarcelbreakpoint (void)
949130812Smarcel{
950130812Smarcel  if (initialized)
951130812Smarcel    BREAKPOINT ();
952130812Smarcel}
953