source: rtems/c/src/lib/libbsp/m68k/efi68k/startup/m68k-stub.c @ 98e4ebf5

4.104.114.84.95
Last change on this file since 98e4ebf5 was 486c329, checked in by Joel Sherrill <joel.sherrill@…>, on 09/20/95 at 15:05:19

Actually adding efi bsp's from John Gwynne after forgetting to
commit them.

  • Property mode set to 100644
File size: 22.8 KB
Line 
1/*  m68k-stub.c
2 *
3 *  $Id$
4 */
5
6#include <efi68k.h>
7#include <rtems.h>
8
9m68k_isr_entry set_vector(
10  rtems_isr_entry     handler,
11  rtems_vector_number vector,
12  int                 type
13);
14
15
16void (*exceptionHook)() = 0;
17
18void outbyte(char c);
19char putDebugChar( char c)
20{
21  outbyte(c);
22  return c;
23}
24
25char inbyte(void);
26char getDebugChar(void)
27{
28  return inbyte();
29}
30
31void flush_i_cache(void)
32{
33  return;
34}
35
36void *memset(void *p, int c, int n)
37{
38  register int i;
39  void *s=p;
40
41  for (i=0;i<n;i++) *((char *)p)++=(char)c;
42  return s;
43}
44
45char *db_strcpy(char *s, const char *t)
46{
47  char *save=s;
48  while((*s++ = *t++) != '\0');
49  return save;
50}
51
52int db_strlen(const char *s)
53{
54  int n;
55
56  for (n=0; *s!='\0'; s++) n++;
57  return n;
58}
59
60/************************************************************************
61 *
62 * external low-level support routines
63 */
64typedef void (*ExceptionHook)(int);   /* pointer to function with int parm */
65typedef void (*Function)();           /* pointer to a function */
66
67/* extern Function exceptionHandler(); */ /* assign an exception handler */
68extern ExceptionHook exceptionHook;  /* hook variable for errors/exceptions */
69/* extern void exceptionHandler(int vect, void (*function)()); */
70
71/************************/
72/* FORWARD DECLARATIONS */
73/************************/
74static void initializeRemcomErrorFrame();
75
76/************************************************************************/
77/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
78/* at least NUMREGBYTES*2 are needed for register packets */
79#define BUFMAX 400
80
81static char initialized;  /* boolean flag. != 0 means we've been initialized */
82
83int     remote_debug;
84/*  debug >  0 prints ill-formed commands in valid packets & checksum errors */
85
86static const char hexchars[]="0123456789abcdef";
87
88/* there are 180 bytes of registers on a 68020 w/68881      */
89/* many of the fpa registers are 12 byte (96 bit) registers */
90#define NUMREGBYTES 180
91enum regnames {D0,D1,D2,D3,D4,D5,D6,D7,
92               A0,A1,A2,A3,A4,A5,A6,A7,
93               PS,PC,
94               FP0,FP1,FP2,FP3,FP4,FP5,FP6,FP7,
95               FPCONTROL,FPSTATUS,FPIADDR
96              };
97
98
99
100typedef struct FrameStruct
101{
102    struct FrameStruct  *previous;
103    int       exceptionPC;      /* pc value when this frame created */
104    int       exceptionVector;  /* cpu vector causing exception     */
105    short     frameSize;        /* size of cpu frame in words       */
106    short     sr;               /* for 68000, this not always sr    */
107    int       pc;
108    short     format;
109    int       fsaveHeader;
110    int       morejunk[0];        /* exception frame, fp save... */
111} Frame;
112
113#define FRAMESIZE 10
114int   gdbFrameStack[FRAMESIZE];
115static Frame *lastFrame;
116
117/*
118 * these should not be static cuz they can be used outside this module
119 */
120int registers[NUMREGBYTES/4];
121int superStack;
122
123#define STACKSIZE 600
124int remcomStack[STACKSIZE/sizeof(int)];
125static int* stackPtr = &remcomStack[STACKSIZE/sizeof(int) - 1];
126
127static ExceptionHook oldExceptionHook;
128
129#define SAVE_FP_REGS()
130#define RESTORE_FP_REGS()
131
132void return_to_super();
133void return_to_user();
134
135asm("
136.text
137.align 2
138.globl return_to_super
139return_to_super:
140        oriw    #0x0700,%sr
141        movel   registers+60,%sp /* get new stack pointer */       
142        movel   lastFrame,%a0   /* get last frame info  */             
143        bra     return_to_any
144
145.globl return_to_user
146return_to_user:
147        oriw    #0x0700,%sr
148        movel   registers+60,%a0 /* get usp */                         
149        movel   %a0,%usp           /* set usp */
150        movel   superStack,%sp  /* get original stack pointer */       
151
152return_to_any:
153        movel   lastFrame,%a0   /* get last frame info  */             
154        movel   %a0@+,lastFrame /* link in previous frame     */       
155        addql   #8,%a0           /* skip over pc, vector#*/             
156        movew   %a0@+,%d0         /* get # of words in cpu frame */       
157        addw    %d0,%a0           /* point to end of data        */       
158        addw    %d0,%a0           /* point to end of data        */       
159        movel   %a0,%a1                                                   
160#                                                                       
161# copy the stack frame                                                 
162        subql   #1,%d0                                                   
163copyUserLoop:                                                               
164        movew   %a1@-,%sp@-                                               
165        dbf     %d0,copyUserLoop                                             
166");                                                                     
167        RESTORE_FP_REGS()                                             
168   asm("   moveml  registers,%d0-%d7/%a0-%a6");                         
169   asm("   rte");  /* pop and go! */                                   
170
171#define DISABLE_INTERRUPTS()   asm("         oriw   #0x0700,%sr");
172#define BREAKPOINT() asm("   trap #1");
173
174/* this function is called immediately when a level 7 interrupt occurs */
175/* if the previous interrupt level was 7 then we're already servicing  */
176/* this interrupt and an rte is in order to return to the debugger.    */
177/* For the 68000, the offset for sr is 6 due to the jsr return address */
178asm("
179.text
180.align 2
181.globl _debug_level7
182_debug_level7:
183        movew   %d0,%sp@-");
184asm("   movew   %sp@(6),%d0");
185
186asm("   andiw   #0x700,%d0
187        cmpiw   #0x700,%d0
188        beq     already7
189        movew   %sp@+,%d0       
190        bra     _catchException
191already7:
192        movew   %sp@+,%d0");
193asm("   lea     %sp@(4),%sp");     /* pull off 68000 return address */
194
195asm("   rte");
196
197extern void _catchException ();
198
199/* This function is called when an exception occurs.  It translates the
200 * return address found on the stack into an exception vector # which
201 * is then handled by either handle_exception or a system handler.
202 * _catchException provides a front end for both. 
203 *
204 * stack on entry:                       stack on exit:
205 *   Program counter MSWord              exception # MSWord
206 *   Program counter LSWord              exception # MSWord
207 *   Status Register                     
208 *   Return Address  MSWord             
209 *   Return Address  LSWord             
210 */
211
212asm("
213.text
214.align 2
215.globl _catchException
216_catchException:
217");
218DISABLE_INTERRUPTS();
219asm("
220        moveml %d0-%d7/%a0-%a6,registers  /* save registers               */
221        movel   lastFrame,%a0   /* last frame pointer */
222
223        move.b #64,(0x00600001)
224        move.b (0x00600007),%d0
225        andib #-64,%d0
226        move.b %d0,(0x00600007)
227
228");
229SAVE_FP_REGS();       
230asm("
231        lea     registers,%a5   /* get address of registers     */
232        movel   %sp@+,%d2         /* pop return address           */
233        addq.l  #6,%d2
234        sub.l   #0x200000,%d2
235        divs    #6,%d2
236/*      addl    #1530,%d2  */      /* convert return addr to    */
237/*      divs    #6,%d2     */   /*  exception number            */
238        extl    %d2   
239
240        moveql  #3,%d3           /* assume a three word frame     */
241
242        cmpiw   #3,%d2           /* bus error or address error ? */
243        bgt     normal          /* if >3 then normal error      */
244        movel   %sp@+,%a0@-       /* copy error info to frame buff*/
245        movel   %sp@+,%a0@-       /* these are never used         */
246        moveql  #7,%d3           /* this is a 7 word frame       */
247     
248normal:   
249        movew   %sp@+,%d1         /* pop status register          */
250        movel   %sp@+,%a4         /* pop program counter          */
251        movew   %d1,%a5@(66)      /* save sr                    */     
252        movel   %a4,%a5@(68)      /* save pc in _regisers[]             */
253        movel   %a4,%a0@-         /* copy pc to frame buffer      */
254        movew   %d1,%a0@-         /* copy sr to frame buffer      */
255
256        movel   %sp,superStack  /* save supervisor sp          */
257
258        andiw   #0x2000,%d1      /* were we in supervisor mode ? */
259        beq     userMode       
260        movel   %a7,%a5@(60)      /* save a7                  */
261        bra     saveDone             
262userMode:
263        movel   %usp,%a1        /* save user stack pointer      */
264        movel   %a1,%a5@(60)      /* save user stack pointer    */
265saveDone:
266
267        movew   %d3,%a0@-         /* push frame size in words     */
268        movel   %d2,%a0@-         /* push vector number           */
269        movel   %a4,%a0@-         /* push exception pc            */
270
271#
272# save old frame link and set the new value
273        movel   lastFrame,%a1   /* last frame pointer */
274        movel   %a1,%a0@-               /* save pointer to prev frame   */
275        movel   %a0,lastFrame
276
277        movel   %d2,%sp@-               /* push exception num           */
278        movel   exceptionHook,%a0  /* get address of handler */
279        jbsr    %a0@             /* and call it */
280        clrl    %sp@             /* replace exception num parm with frame ptr*/
281        jbsr     _returnFromException   /* jbsr, but never returns */
282");
283
284
285/*
286 * remcomHandler is a front end for handle_exception.  It moves the
287 * stack pointer into an area reserved for debugger use in case the
288 * breakpoint happened in supervisor mode.
289 */
290asm("remcomHandler:");
291asm("           addl    #4,%sp");        /* pop off return address     */
292asm("           movel   %sp@+,%d0");      /* get the exception number   */
293asm("           movel   stackPtr,%sp"); /* move to remcom stack area  */
294asm("           movel   %d0,%sp@-");    /* push exception onto stack  */
295asm("           andiw   #0xf8ff,%sr");
296asm("           jbsr    handle_exception");    /* this never returns */
297asm("           rts");                  /* return */
298
299void _returnFromException( Frame *frame )
300{
301    /* if no passed in frame, use the last one */
302    if (! frame)
303    {
304        frame = lastFrame;
305        frame->frameSize = 4;
306        frame->format = 0;
307        frame->fsaveHeader = -1; /* restore regs, but we dont have fsave info*/
308    }
309
310
311    /* a 68000 cannot use the internal info pushed onto a bus error
312     * or address error frame when doing an RTE so don't put this info
313     * onto the stack or the stack will creep every time this happens.
314     */
315    frame->frameSize=3;
316
317
318    /* throw away any frames in the list after this frame */
319    lastFrame = frame;
320
321    frame->sr = registers[(int) PS];
322    frame->pc = registers[(int) PC];
323
324    if (registers[(int) PS] & 0x2000)
325    {
326        /* return to supervisor mode... */
327        return_to_super();
328    }
329    else
330    { /* return to user mode */
331        return_to_user();
332    }
333}
334
335int hex(ch)
336char ch;
337{
338  if ((ch >= 'a') && (ch <= 'f')) return (ch-'a'+10);
339  if ((ch >= '0') && (ch <= '9')) return (ch-'0');
340  if ((ch >= 'A') && (ch <= 'F')) return (ch-'A'+10);
341  return (-1);
342}
343
344
345/* scan for the sequence $<data>#<checksum>     */
346void getpacket(buffer)
347char * buffer;
348{
349  unsigned char checksum;
350  unsigned char xmitcsum;
351  int  i;
352  int  count;
353  char ch;
354 
355  do {
356    /* wait around for the start character, ignore all other characters */
357    while ((ch = getDebugChar()) != '$');
358    checksum = 0;
359    xmitcsum = -1;
360   
361    count = 0;
362   
363    /* now, read until a # or end of buffer is found */
364    while (count < BUFMAX) {
365      ch = getDebugChar();
366      if (ch == '#') break;
367      checksum = checksum + ch;
368      buffer[count] = ch;
369      count = count + 1;
370      }
371    buffer[count] = 0;
372
373    if (ch == '#') {
374      xmitcsum = hex(getDebugChar()) << 4;
375      xmitcsum += hex(getDebugChar());
376     
377      if (checksum != xmitcsum) putDebugChar('-');  /* failed checksum */
378      else {
379         putDebugChar('+');  /* successful transfer */
380         /* if a sequence char is present, reply the sequence ID */
381         if (buffer[2] == ':') {
382            putDebugChar( buffer[0] );
383            putDebugChar( buffer[1] );
384            /* remove sequence chars from buffer */
385            count = db_strlen(buffer);
386            for (i=3; i <= count; i++) buffer[i-3] = buffer[i];
387         }
388      }
389    }
390  } while (checksum != xmitcsum);
391 
392}
393
394/* send the packet in buffer.  The host get's one chance to read it. 
395   This routine does not wait for a positive acknowledge.  */
396
397
398void putpacket(buffer)
399char * buffer;
400{
401  unsigned char checksum;
402  int  count;
403  char ch;
404 
405  /*  $<packet info>#<checksum>. */
406  do {
407  putDebugChar('$');
408  checksum = 0;
409  count    = 0;
410 
411  while ((ch=buffer[count])) {
412    if (! putDebugChar(ch)) return;
413    checksum += ch;
414    count += 1;
415  }
416 
417  putDebugChar('#');
418  putDebugChar(hexchars[checksum >> 4]);
419  putDebugChar(hexchars[checksum % 16]);
420
421  } while (1 == 0);  /* (getDebugChar() != '+'); */
422 
423}
424
425char  remcomInBuffer[BUFMAX];
426char  remcomOutBuffer[BUFMAX];
427static short error;
428
429
430void debug_error(format, parm)
431char * format;
432char * parm;
433{
434  return;
435}
436
437/* convert the memory pointed to by mem into hex, placing result in buf */
438/* return a pointer to the last char put in buf (null) */
439char* mem2hex(mem, buf, count)
440char* mem;
441char* buf;
442int   count;
443{
444      int i;
445      unsigned char ch;
446      for (i=0;i<count;i++) {
447          ch = *mem++;
448          *buf++ = hexchars[ch >> 4];
449          *buf++ = hexchars[ch % 16];
450      }
451      *buf = 0;
452      return(buf);
453}
454
455/* convert the hex array pointed to by buf into binary to be placed in mem */
456/* return a pointer to the character AFTER the last byte written */
457char* hex2mem(buf, mem, count)
458char* buf;
459char* mem;
460int   count;
461{
462      int i;
463      unsigned char ch;
464      for (i=0;i<count;i++) {
465          ch = hex(*buf++) << 4;
466          ch = ch + hex(*buf++);
467          *mem++ = ch;
468      }
469      return(mem);
470}
471
472/* this function takes the 68000 exception number and attempts to
473   translate this number into a unix compatible signal value */
474int computeSignal( exceptionVector )
475int exceptionVector;
476{
477  int sigval;
478  switch (exceptionVector) {
479    case 2 : sigval = 10; break; /* bus error           */
480    case 3 : sigval = 10; break; /* address error       */
481    case 4 : sigval = 4;  break; /* illegal instruction */
482    case 5 : sigval = 8;  break; /* zero divide         */
483    case 6 : sigval = 8; break; /* chk instruction     */
484    case 7 : sigval = 8; break; /* trapv instruction   */
485    case 8 : sigval = 11; break; /* privilege violation */
486    case 9 : sigval = 5;  break; /* trace trap          */
487    case 10: sigval = 4;  break; /* line 1010 emulator  */
488    case 11: sigval = 4;  break; /* line 1111 emulator  */
489
490      /* Coprocessor protocol violation.  Using a standard MMU or FPU
491         this cannot be triggered by software.  Call it a SIGBUS.  */
492    case 13: sigval = 10;  break;
493
494    case 31: sigval = 2;  break; /* interrupt           */
495    case 33: sigval = 5;  break; /* breakpoint          */
496
497      /* This is a trap #8 instruction.  Apparently it is someone's software
498         convention for some sort of SIGFPE condition.  Whose?  How many
499         people are being screwed by having this code the way it is?
500         Is there a clean solution?  */
501    case 40: sigval = 8;  break; /* floating point err  */
502
503    case 48: sigval = 8;  break; /* floating point err  */
504    case 49: sigval = 8;  break; /* floating point err  */
505    case 50: sigval = 8;  break; /* zero divide         */
506    case 51: sigval = 8;  break; /* underflow           */
507    case 52: sigval = 8;  break; /* operand error       */
508    case 53: sigval = 8;  break; /* overflow            */
509    case 54: sigval = 8;  break; /* NAN                 */
510    default:
511      sigval = 7;         /* "software generated"*/
512  }
513  return (sigval);
514}
515
516/**********************************************/
517/* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
518/* RETURN NUMBER OF CHARS PROCESSED           */
519/**********************************************/
520int hexToInt(char **ptr, int *intValue)
521{
522    int numChars = 0;
523    int hexValue;
524   
525    *intValue = 0;
526
527    while (**ptr)
528    {
529        hexValue = hex(**ptr);
530        if (hexValue >=0)
531        {
532            *intValue = (*intValue <<4) | hexValue;
533            numChars ++;
534        }
535        else
536            break;
537       
538        (*ptr)++;
539    }
540
541    return (numChars);
542}
543
544/*
545 * This function does all command procesing for interfacing to gdb.
546 */
547void handle_exception(int exceptionVector)
548{
549  int    sigval;
550  int    addr, length;
551  char * ptr;
552  int    newPC;
553  Frame  *frame;
554 
555  /* reply to host that an exception has occurred */
556  sigval = computeSignal( exceptionVector );
557  remcomOutBuffer[0] = 'S';
558  remcomOutBuffer[1] =  hexchars[sigval >> 4];
559  remcomOutBuffer[2] =  hexchars[sigval % 16];
560  remcomOutBuffer[3] = 0;
561
562  putpacket(remcomOutBuffer);
563
564  while (1==1) {
565    error = 0;
566    remcomOutBuffer[0] = 0;
567    getpacket(remcomInBuffer);
568    switch (remcomInBuffer[0]) {
569      case '?' :   remcomOutBuffer[0] = 'S';
570                   remcomOutBuffer[1] =  hexchars[sigval >> 4];
571                   remcomOutBuffer[2] =  hexchars[sigval % 16];
572                   remcomOutBuffer[3] = 0;
573                 break;
574      case 'd' : remote_debug = !(remote_debug);  /* toggle debug flag */
575                 break;
576      case 'g' : /* return the value of the CPU registers */
577                mem2hex((char*) registers, remcomOutBuffer, NUMREGBYTES);
578                break;
579      case 'G' : /* set the value of the CPU registers - return OK */
580                hex2mem(&remcomInBuffer[1], (char*) registers, NUMREGBYTES);
581                db_strcpy(remcomOutBuffer,"OK");
582                break;
583     
584      /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
585      case 'm' :
586        /* TRY TO READ %x,%x.  IF SUCCEED, SET PTR = 0 */
587        ptr = &remcomInBuffer[1];
588        if (hexToInt(&ptr,&addr))
589          if (*(ptr++) == ',')
590            if (hexToInt(&ptr,&length))
591              {
592                ptr = 0;
593                mem2hex((char*) addr, remcomOutBuffer, length);
594              }
595       
596        if (ptr)
597          {
598            db_strcpy(remcomOutBuffer,"E01");
599            debug_error("malformed read memory command: %s",remcomInBuffer);
600          }     
601        break;
602     
603      /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
604      case 'M' :
605        /* TRY TO READ '%x,%x:'.  IF SUCCEED, SET PTR = 0 */
606        ptr = &remcomInBuffer[1];
607        if (hexToInt(&ptr,&addr))
608          if (*(ptr++) == ',')
609            if (hexToInt(&ptr,&length))
610              if (*(ptr++) == ':')
611                {
612                  hex2mem(ptr, (char*) addr, length);
613                  ptr = 0;
614                  db_strcpy(remcomOutBuffer,"OK");
615                }
616        if (ptr)
617          {
618            db_strcpy(remcomOutBuffer,"E02");
619            debug_error("malformed write memory command: %s",remcomInBuffer);
620          }     
621        break;
622     
623     /* cAA..AA    Continue at address AA..AA(optional) */
624     /* sAA..AA   Step one instruction from AA..AA(optional) */
625     case 'c' :
626     case 's' :
627          /* try to read optional parameter, pc unchanged if no parm */
628         ptr = &remcomInBuffer[1];
629         if (hexToInt(&ptr,&addr))
630             registers[ PC ] = addr;
631             
632          newPC = registers[ PC];
633         
634          /* clear the trace bit */
635          registers[ PS ] &= 0x7fff;
636         
637          /* set the trace bit if we're stepping */
638          if (remcomInBuffer[0] == 's') registers[ PS ] |= 0x8000;
639         
640          /*
641           * look for newPC in the linked list of exception frames.
642           * if it is found, use the old frame it.  otherwise,
643           * fake up a dummy frame in returnFromException().
644           */
645          frame = lastFrame;
646          while (frame)
647          {
648              if (frame->exceptionPC == newPC) break;  /* bingo! a match */
649              /*
650               * for a breakpoint instruction, the saved pc may
651               * be off by two due to re-executing the instruction
652               * replaced by the trap instruction.  Check for this.
653               */
654              if ((frame->exceptionVector == 33) &&
655                  (frame->exceptionPC == (newPC+2))) break;
656              if (frame == frame->previous)
657              {
658                  frame = 0; /* no match found */
659                  break;
660              }
661              frame = frame->previous;
662          }
663         
664          /*
665           * If we found a match for the PC AND we are not returning
666           * as a result of a breakpoint (33),
667           * trace exception (9), nmi (31), jmp to
668           * the old exception handler as if this code never ran.
669           */
670          if (frame)
671          {
672              if ((frame->exceptionVector != 9)  &&
673                  (frame->exceptionVector != 31) &&
674                  (frame->exceptionVector != 33))
675              {
676                  /*
677                   * invoke the previous handler.
678                   */
679                  if (oldExceptionHook)
680                      (*oldExceptionHook) (frame->exceptionVector);
681                  newPC = registers[ PC ];    /* pc may have changed  */
682                  if (newPC != frame->exceptionPC)
683                  {
684                      /* re-use the last frame, we're skipping it (longjump?)*/
685                      frame = (Frame *) 0;
686                      _returnFromException( frame );  /* this is a jump */
687                  }
688              }
689          }         
690
691          /* if we couldn't find a frame, create one */
692          if (frame == 0)
693          {
694              frame = lastFrame -1 ;
695             
696              /* by using a bunch of print commands with breakpoints,
697                 it's possible for the frame stack to creep down.  If it creeps
698                 too far, give up and reset it to the top.  Normal use should
699                 not see this happen.
700              */
701              if ((unsigned int) (frame-2) < (unsigned int) &gdbFrameStack)
702              {
703                 initializeRemcomErrorFrame();
704                 frame = lastFrame;
705              }
706              frame->previous = lastFrame;
707              lastFrame = frame;
708              frame = 0;  /* null so _return... will properly initialize it */
709          }   
710         
711          _returnFromException( frame ); /* this is a jump */
712
713          break;
714         
715      /* kill the program */
716      case 'k' :  /* do nothing */
717                break;
718      } /* switch */
719   
720    /* reply to the request */
721    putpacket(remcomOutBuffer);
722    }
723}
724
725
726void
727initializeRemcomErrorFrame()
728{
729    lastFrame = ((Frame *) &gdbFrameStack[FRAMESIZE-1]) - 1;
730    lastFrame->previous = lastFrame;
731}
732
733/* this function is used to set up exception handlers for tracing and
734   breakpoints */
735void set_debug_traps()
736{
737  extern void _debug_level7();
738  extern void remcomHandler();
739  int exception;
740
741  initializeRemcomErrorFrame();
742  stackPtr  = &remcomStack[STACKSIZE/sizeof(int) - 1];
743
744  for (exception = 2; exception <= 23; exception++)
745      set_vector(_catchException,exception,0);   
746
747  /* level 7 interrupt              */
748  set_vector(_debug_level7,31,0);   
749 
750  /* breakpoint exception (trap #1) */
751  set_vector(_catchException,33,0);
752 
753  /* This is a trap #8 instruction.  Apparently it is someone's software
754     convention for some sort of SIGFPE condition.  Whose?  How many
755     people are being screwed by having this code the way it is?
756     Is there a clean solution?  */
757  set_vector(_catchException,40,0);
758 
759  /* 48 to 54 are floating point coprocessor errors */
760  for (exception = 48; exception <= 54; exception++)
761      set_vector(_catchException,exception,0);   
762
763  if (oldExceptionHook != remcomHandler)
764  {
765      oldExceptionHook = exceptionHook;
766      exceptionHook    = remcomHandler;
767  }
768 
769  initialized = 1;
770
771}
772
773/* This function will generate a breakpoint exception.  It is used at the
774   beginning of a program to sync up with a debugger and can be used
775   otherwise as a quick means to stop program execution and "break" into
776   the debugger. */
777   
778void breakpoint()
779{
780  if (initialized) BREAKPOINT();
781}
782
Note: See TracBrowser for help on using the repository browser.