OSDN Git Service

2003-01-29 Joel Sherrill <joel@OARcorp.com>
[pf3gnuchains/gcc-fork.git] / gcc / ada / init.c
1 /****************************************************************************
2  *                                                                          *
3  *                         GNAT COMPILER COMPONENTS                         *
4  *                                                                          *
5  *                                 I N I T                                  *
6  *                                                                          *
7  *                                                                          *
8  *                          C Implementation File                           *
9  *                                                                          *
10  *          Copyright (C) 1992-2003 Free Software Foundation, Inc.          *
11  *                                                                          *
12  * GNAT is free software;  you can  redistribute it  and/or modify it under *
13  * terms of the  GNU General Public License as published  by the Free Soft- *
14  * ware  Foundation;  either version 2,  or (at your option) any later ver- *
15  * sion.  GNAT is distributed in the hope that it will be useful, but WITH- *
16  * OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY *
17  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License *
18  * for  more details.  You should have  received  a copy of the GNU General *
19  * Public License  distributed with GNAT;  see file COPYING.  If not, write *
20  * to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, *
21  * MA 02111-1307, USA.                                                      *
22  *                                                                          *
23  * As a  special  exception,  if you  link  this file  with other  files to *
24  * produce an executable,  this file does not by itself cause the resulting *
25  * executable to be covered by the GNU General Public License. This except- *
26  * ion does not  however invalidate  any other reasons  why the  executable *
27  * file might be covered by the  GNU Public License.                        *
28  *                                                                          *
29  * GNAT was originally developed  by the GNAT team at  New York University. *
30  * Extensive contributions were provided by Ada Core Technologies Inc.      *
31  *                                                                          *
32  ****************************************************************************/
33
34 /*  This unit contains initialization circuits that are system dependent. A
35     major part of the functionality involved involves stack overflow checking.
36     The GCC backend generates probe instructions to test for stack overflow.
37     For details on the exact approach used to generate these probes, see the
38     "Using and Porting GCC" manual, in particular the "Stack Checking" section
39     and the subsection "Specifying How Stack Checking is Done". The handlers
40     installed by this file are used to handle resulting signals that come
41     from these probes failing (i.e. touching protected pages) */
42
43 /* The following include is here to meet the published VxWorks requirement
44    that the __vxworks header appear before any other include. */
45 #ifdef __vxworks
46 #include "vxWorks.h"
47 #endif
48
49 #ifdef IN_RTS
50 #include "tconfig.h"
51 #include "tsystem.h"
52 #include <sys/stat.h>
53
54 /* We don't have libiberty, so us malloc.  */
55 #define xmalloc(S) malloc (S)
56 #else
57 #include "config.h"
58 #include "system.h"
59 #endif
60
61 #include "adaint.h"
62 #include "raise.h"
63
64 extern void __gnat_raise_program_error (const char *, int);
65
66 /* Addresses of exception data blocks for predefined exceptions. */
67 extern struct Exception_Data constraint_error;
68 extern struct Exception_Data numeric_error;
69 extern struct Exception_Data program_error;
70 extern struct Exception_Data storage_error;
71 extern struct Exception_Data tasking_error;
72 extern struct Exception_Data _abort_signal;
73
74 #define Lock_Task system__soft_links__lock_task
75 extern void (*Lock_Task) PARAMS ((void));
76
77 #define Unlock_Task system__soft_links__unlock_task
78 extern void (*Unlock_Task) PARAMS ((void));
79
80 #define Get_Machine_State_Addr \
81                       system__soft_links__get_machine_state_addr
82 extern struct Machine_State *(*Get_Machine_State_Addr) PARAMS ((void));
83
84 #define Check_Abort_Status     \
85                       system__soft_links__check_abort_status
86 extern int    (*Check_Abort_Status) PARAMS ((void));
87
88 #define Raise_From_Signal_Handler \
89                       ada__exceptions__raise_from_signal_handler
90 extern void   Raise_From_Signal_Handler PARAMS ((struct Exception_Data *,
91                                                 const char *));
92
93 #define Propagate_Signal_Exception \
94                       __gnat_propagate_sig_exc
95 extern void   Propagate_Signal_Exception
96         PARAMS ((struct Machine_State *, struct Exception_Data *, const char *));
97
98 /* Copies of global values computed by the binder */
99 int   __gl_main_priority            = -1;
100 int   __gl_time_slice_val           = -1;
101 char  __gl_wc_encoding              = 'n';
102 char  __gl_locking_policy           = ' ';
103 char  __gl_queuing_policy           = ' ';
104 char *__gl_restrictions             = 0;
105 char  __gl_task_dispatching_policy  = ' ';
106 int   __gl_unreserve_all_interrupts = 0;
107 int   __gl_exception_tracebacks     = 0;
108 int   __gl_zero_cost_exceptions     = 0;
109
110 /* Indication of whether synchronous signal handler has already been 
111    installed by a previous call to adainit */
112 int  __gnat_handler_installed      = 0;
113
114 /* HAVE_GNAT_INIT_FLOAT must be set on every targets where a __gnat_init_float
115    is defined. If this is not set them a void implementation will be defined
116    at the end of this unit. */
117 #undef HAVE_GNAT_INIT_FLOAT
118
119 /**********************/
120 /* __gnat_set_globals */
121 /**********************/
122
123 /* This routine is called from the binder generated main program.  It copies
124    the values for global quantities computed by the binder into the following
125    global locations. The reason that we go through this copy, rather than just
126    define the global locations in the binder generated file, is that they are
127    referenced from the runtime, which may be in a shared library, and the
128    binder file is not in the shared library. Global references across library
129    boundaries like this are not handled correctly in all systems.  */
130
131 void
132 __gnat_set_globals (main_priority, time_slice_val, wc_encoding, locking_policy,
133                     queuing_policy, task_dispatching_policy, restrictions,
134                     unreserve_all_interrupts, exception_tracebacks,
135                     zero_cost_exceptions)
136      int main_priority;
137      int time_slice_val;
138      char wc_encoding;
139      char locking_policy, queuing_policy, task_dispatching_policy;
140      char *restrictions;
141      int unreserve_all_interrupts, exception_tracebacks, zero_cost_exceptions;
142 {
143   static int already_called = 0;
144
145   /* If this procedure has been already called once, check that the
146      arguments in this call are consistent with the ones in the previous
147      calls. Otherwise, raise a Program_Error exception.
148
149      We do not check for consistency of the wide character encoding
150      method. This default affects only Wide_Text_IO where no explicit
151      coding method is given, and there is no particular reason to let
152      this default be affected by the source representation of a library
153      in any case. 
154
155      The value of main_priority is meaningful only when we are invoked
156      from the main program elaboration routine of an Ada application.
157      Checking the consistency of this parameter should therefore not be
158      done. Since it is assured that the main program elaboration will
159      always invoke this procedure before any library elaboration
160      routine, only the value of main_priority during the first call
161      should be taken into account and all the subsequent ones should be
162      ignored. Note that the case where the main program is not written
163      in Ada is also properly handled, since the default value will then
164      be used for this parameter.
165
166      For identical reasons, the consistency of time_slice_val should not
167      be checked. */
168
169   if (already_called)
170     {
171       if (__gl_locking_policy              != locking_policy
172           || __gl_queuing_policy           != queuing_policy
173           || __gl_task_dispatching_policy  != task_dispatching_policy
174           || __gl_unreserve_all_interrupts != unreserve_all_interrupts
175           || __gl_exception_tracebacks     != exception_tracebacks
176           || __gl_zero_cost_exceptions     != zero_cost_exceptions)
177         __gnat_raise_program_error (__FILE__, __LINE__);
178
179       return;
180     }
181   already_called = 1;
182
183   __gl_main_priority            = main_priority;
184   __gl_time_slice_val           = time_slice_val;
185   __gl_wc_encoding              = wc_encoding;
186   __gl_locking_policy           = locking_policy;
187   __gl_queuing_policy           = queuing_policy;
188   __gl_restrictions             = restrictions;
189   __gl_task_dispatching_policy  = task_dispatching_policy;
190   __gl_unreserve_all_interrupts = unreserve_all_interrupts;
191   __gl_exception_tracebacks     = exception_tracebacks;
192
193   /* ??? __gl_zero_cost_exceptions is new in 3.15 and is referenced from
194      a-except.adb, which is also part of the compiler sources. Since the
195      compiler is built with an older release of GNAT, the call generated by
196      the old binder to this function does not provide any value for the
197      corresponding argument, so the global has to be initialized in some
198      reasonable other way. This could be removed as soon as the next major
199      release is out.  */
200
201 #ifdef IN_RTS
202   __gl_zero_cost_exceptions = zero_cost_exceptions;
203 #else
204   __gl_zero_cost_exceptions = 0;
205   /* We never build the compiler to run in ZCX mode currently anyway.  */
206 #endif
207 }
208
209 /*********************/
210 /* __gnat_initialize */
211 /*********************/
212
213 /* __gnat_initialize is called at the start of execution of an Ada program
214    (the call is generated by the binder). The standard routine does nothing
215    at all; the intention is that this be replaced by system specific
216    code where initialization is required. */
217
218 /***********************************/
219 /* __gnat_initialize (AIX version) */
220 /***********************************/
221
222 #if defined (_AIX)
223
224 /* AiX doesn't have SA_NODEFER */
225
226 #define SA_NODEFER 0
227
228 #include <sys/time.h>
229
230 /* AiX doesn't have nanosleep, but provides nsleep instead */
231
232 extern int nanosleep PARAMS ((struct timestruc_t *, struct timestruc_t *));
233 static void __gnat_error_handler PARAMS ((int));
234
235 int
236 nanosleep (Rqtp, Rmtp)
237      struct timestruc_t *Rqtp, *Rmtp;
238 {
239   return nsleep (Rqtp, Rmtp);
240 }
241
242 #include <signal.h>
243
244 static void
245 __gnat_error_handler (sig)
246      int sig;
247 {
248   struct Exception_Data *exception;
249   const char *msg;
250
251   switch (sig)
252     {
253     case SIGSEGV:
254       /* FIXME: we need to detect the case of a *real* SIGSEGV */
255       exception = &storage_error;
256       msg = "stack overflow or erroneous memory access";
257       break;
258
259     case SIGBUS:
260       exception = &constraint_error;
261       msg = "SIGBUS";
262       break;
263
264     case SIGFPE:
265       exception = &constraint_error;
266       msg = "SIGFPE";
267       break;
268
269     default:
270       exception = &program_error;
271       msg = "unhandled signal";
272     }
273
274   Raise_From_Signal_Handler (exception, msg);
275 }
276
277 void
278 __gnat_install_handler ()
279 {
280   struct sigaction act;
281
282   /* Set up signal handler to map synchronous signals to appropriate
283      exceptions.  Make sure that the handler isn't interrupted by another
284      signal that might cause a scheduling event! */
285
286   act.sa_handler = __gnat_error_handler;
287   act.sa_flags = SA_NODEFER | SA_RESTART;
288   (void) sigemptyset (&act.sa_mask);
289
290   (void) sigaction (SIGABRT, &act, NULL);
291   (void) sigaction (SIGFPE,  &act, NULL);
292   (void) sigaction (SIGILL,  &act, NULL);
293   (void) sigaction (SIGSEGV, &act, NULL);
294   (void) sigaction (SIGBUS,  &act, NULL);
295   __gnat_handler_installed = 1;
296 }
297
298 void
299 __gnat_initialize ()
300 {
301 }
302
303 /****************************************/
304 /* __gnat_initialize (Dec Unix version) */
305 /****************************************/
306
307 #elif defined(__alpha__) && defined(__osf__) && ! defined(__alpha_vxworks)
308
309 /* Note: it seems that __osf__ is defined for the Alpha VXWorks case. Not
310    clear that this is reasonable, but in any case we have to be sure to
311    exclude this case in the above test.  */
312
313 #include <signal.h>
314 #include <sys/siginfo.h>
315
316 static void __gnat_error_handler PARAMS ((int, siginfo_t *,
317                                           struct sigcontext *));
318 extern char *__gnat_get_code_loc PARAMS ((struct sigcontext *));
319 extern void __gnat_enter_handler PARAMS ((struct sigcontext *, char *));
320 extern size_t __gnat_machine_state_length PARAMS ((void));
321
322 extern long exc_lookup_gp PARAMS ((char *));
323 extern void exc_resume PARAMS ((struct sigcontext *));
324
325 static void
326 __gnat_error_handler (sig, sip, context)
327      int sig;
328      siginfo_t *sip;
329      struct sigcontext *context;
330 {
331   struct Exception_Data *exception;
332   static int recurse = 0;
333   struct sigcontext *mstate;
334   const char *msg;
335
336   /* If this was an explicit signal from a "kill", just resignal it.  */
337   if (SI_FROMUSER (sip))
338     {
339       signal (sig, SIG_DFL);
340       kill (getpid(), sig);
341     }
342
343   /* Otherwise, treat it as something we handle.  */
344   switch (sig)
345     {
346     case SIGSEGV:
347       /* If the problem was permissions, this is a constraint error.
348          Likewise if the failing address isn't maximally aligned or if
349          we've recursed.
350
351          ??? Using a static variable here isn't task-safe, but it's
352          much too hard to do anything else and we're just determining
353          which exception to raise.  */
354       if (sip->si_code == SEGV_ACCERR
355           || (((long) sip->si_addr) & 3) != 0
356           || recurse)
357         {
358           exception = &constraint_error;
359           msg = "SIGSEGV";
360         }
361       else
362         {
363           /* See if the page before the faulting page is accessible.  Do that
364              by trying to access it.  We'd like to simply try to access
365              4096 + the faulting address, but it's not guaranteed to be
366              the actual address, just to be on the same page.  */
367           recurse++;
368           ((volatile char *)
369            ((long) sip->si_addr & - getpagesize ()))[getpagesize ()];
370           msg = "stack overflow (or erroneous memory access)";
371           exception = &storage_error;
372         }
373       break;
374
375     case SIGBUS:
376       exception = &program_error;
377       msg = "SIGBUS";
378       break;
379
380     case SIGFPE:
381       exception = &constraint_error;
382       msg = "SIGFPE";
383       break;
384
385     default:
386       exception = &program_error;
387       msg = "unhandled signal";
388     }
389
390   recurse = 0;
391   mstate = (struct sigcontext *) (*Get_Machine_State_Addr) ();
392   if (mstate != 0)
393     *mstate = *context;
394
395   Raise_From_Signal_Handler (exception, (char *) msg);
396 }
397
398 void
399 __gnat_install_handler ()
400 {
401   struct sigaction act;
402
403   /* Setup signal handler to map synchronous signals to appropriate
404      exceptions. Make sure that the handler isn't interrupted by another
405      signal that might cause a scheduling event! */
406
407   act.sa_handler = (void (*) PARAMS ((int))) __gnat_error_handler;
408   act.sa_flags = SA_ONSTACK | SA_RESTART | SA_NODEFER | SA_SIGINFO;
409   (void) sigemptyset (&act.sa_mask);
410
411   (void) sigaction (SIGABRT, &act, NULL);
412   (void) sigaction (SIGFPE,  &act, NULL);
413   (void) sigaction (SIGILL,  &act, NULL);
414   (void) sigaction (SIGSEGV, &act, NULL);
415   (void) sigaction (SIGBUS,  &act, NULL);
416
417   __gnat_handler_installed = 1;
418 }
419
420 void
421 __gnat_initialize ()
422 {
423 }
424
425 /* Routines called by 5amastop.adb.  */
426
427 #define SC_GP 29
428
429 char *
430 __gnat_get_code_loc (context)
431      struct sigcontext *context;
432 {
433   return (char *) context->sc_pc;
434 }
435
436 void
437 __gnat_enter_handler (context, pc)
438      struct sigcontext *context;
439      char *pc;
440 {
441   context->sc_pc = (long) pc;
442   context->sc_regs[SC_GP] = exc_lookup_gp (pc);
443   exc_resume (context);
444 }
445
446 size_t
447 __gnat_machine_state_length ()
448 {
449   return sizeof (struct sigcontext);
450 }
451
452 /***********************************/
453 /* __gnat_initialize (HPUX version) */
454 /***********************************/
455
456 #elif defined (hpux)
457
458 #include <signal.h>
459
460 static void __gnat_error_handler PARAMS ((int));
461
462 static void
463 __gnat_error_handler (sig)
464      int sig;
465 {
466   struct Exception_Data *exception;
467   char *msg;
468
469   switch (sig)
470     {
471     case SIGSEGV:
472       /* FIXME: we need to detect the case of a *real* SIGSEGV */
473       exception = &storage_error;
474       msg = "stack overflow or erroneous memory access";
475       break;
476
477     case SIGBUS:
478       exception = &constraint_error;
479       msg = "SIGBUS";
480       break;
481
482     case SIGFPE:
483       exception = &constraint_error;
484       msg = "SIGFPE";
485       break;
486
487     default:
488       exception = &program_error;
489       msg = "unhandled signal";
490     }
491
492   Raise_From_Signal_Handler (exception, msg);
493 }
494
495 void
496 __gnat_install_handler ()
497 {
498   struct sigaction act;
499
500   /* Set up signal handler to map synchronous signals to appropriate
501      exceptions.  Make sure that the handler isn't interrupted by another
502      signal that might cause a scheduling event! Also setup an alternate
503      stack region for the handler execution so that stack overflows can be
504      handled properly, avoiding a SEGV generation from stack usage by the
505      handler itself. */
506
507   static char handler_stack[SIGSTKSZ*2];
508   /* SIGSTKSZ appeared to be "short" for the needs in some contexts
509      (e.g. experiments with GCC ZCX exceptions).  */
510
511   stack_t stack;
512
513   stack.ss_sp    = handler_stack;
514   stack.ss_size  = sizeof (handler_stack);
515   stack.ss_flags = 0;
516
517   (void) sigaltstack (&stack, NULL);
518
519   act.sa_handler = __gnat_error_handler;
520   act.sa_flags = SA_NODEFER | SA_RESTART | SA_ONSTACK;
521   (void) sigemptyset (&act.sa_mask);
522
523   (void) sigaction (SIGABRT, &act, NULL);
524   (void) sigaction (SIGFPE,  &act, NULL);
525   (void) sigaction (SIGILL,  &act, NULL);
526   (void) sigaction (SIGSEGV, &act, NULL);
527   (void) sigaction (SIGBUS,  &act, NULL);
528
529   __gnat_handler_installed = 1;
530 }
531
532 void
533 __gnat_initialize ()
534 {
535 }
536
537 /*************************************/
538 /* __gnat_initialize (GNU/Linux version) */
539 /*************************************/
540
541 #elif defined (linux) && defined (i386) && !defined (__RT__)
542
543 #include <signal.h>
544 #include <asm/sigcontext.h>
545
546 /* GNU/Linux, which uses glibc, does not define NULL in included
547    header files */
548
549 #if !defined (NULL)
550 #define NULL ((void *) 0)
551 #endif
552
553 struct Machine_State
554 {
555   unsigned long eip;
556   unsigned long ebx;
557   unsigned long esp;
558   unsigned long ebp;
559   unsigned long esi;
560   unsigned long edi;
561 };
562
563 static void __gnat_error_handler PARAMS ((int));
564
565 static void
566 __gnat_error_handler (sig)
567      int sig;
568 {
569   struct Exception_Data *exception;
570   const char *msg;
571   static int recurse = 0;
572
573   struct sigcontext *info
574     = (struct sigcontext *) (((char *) &sig) + sizeof (int));
575
576   /* The Linux kernel does not document how to get the machine state in a
577      signal handler, but in fact the necessary data is in a sigcontext_struct
578      value that is on the stack immediately above the signal number
579      parameter, and the above messing accesses this value on the stack. */
580
581   struct Machine_State *mstate;
582
583   switch (sig)
584     {
585     case SIGSEGV:
586       /* If the problem was permissions, this is a constraint error.
587        Likewise if the failing address isn't maximally aligned or if
588        we've recursed.
589
590        ??? Using a static variable here isn't task-safe, but it's
591        much too hard to do anything else and we're just determining
592        which exception to raise.  */
593       if (recurse)
594       {
595         exception = &constraint_error;
596         msg = "SIGSEGV";
597       }
598       else
599       {
600         /* Here we would like a discrimination test to see whether the
601            page before the faulting address is accessible. Unfortunately
602            Linux seems to have no way of giving us the faulting address.
603
604            In versions of a-init.c before 1.95, we had a test of the page
605            before the stack pointer using:
606
607             recurse++;
608              ((volatile char *)
609               ((long) info->esp_at_signal & - getpagesize ()))[getpagesize ()];
610
611            but that's wrong, since it tests the stack pointer location, and
612            the current stack probe code does not move the stack pointer
613            until all probes succeed.
614
615            For now we simply do not attempt any discrimination at all. Note
616            that this is quite acceptable, since a "real" SIGSEGV can only
617            occur as the result of an erroneous program */
618
619         msg = "stack overflow (or erroneous memory access)";
620         exception = &storage_error;
621       }
622       break;
623
624     case SIGBUS:
625       exception = &constraint_error;
626       msg = "SIGBUS";
627       break;
628
629     case SIGFPE:
630       exception = &constraint_error;
631       msg = "SIGFPE";
632       break;
633
634     default:
635       exception = &program_error;
636       msg = "unhandled signal";
637     }
638
639   mstate = (*Get_Machine_State_Addr)();
640   if (mstate)
641     {
642       mstate->eip = info->eip;
643       mstate->ebx = info->ebx;
644       mstate->esp = info->esp_at_signal;
645       mstate->ebp = info->ebp;
646       mstate->esi = info->esi;
647       mstate->edi = info->edi;
648     }
649
650   recurse = 0;
651   Raise_From_Signal_Handler (exception, msg);
652 }
653
654 void
655 __gnat_install_handler ()
656 {
657   struct sigaction act;
658
659   /* Set up signal handler to map synchronous signals to appropriate
660      exceptions.  Make sure that the handler isn't interrupted by another
661      signal that might cause a scheduling event! */
662
663   act.sa_handler = __gnat_error_handler;
664   act.sa_flags = SA_NODEFER | SA_RESTART;
665   (void) sigemptyset (&act.sa_mask);
666
667   (void) sigaction (SIGABRT, &act, NULL);
668   (void) sigaction (SIGFPE,  &act, NULL);
669   (void) sigaction (SIGILL,  &act, NULL);
670   (void) sigaction (SIGSEGV, &act, NULL);
671   (void) sigaction (SIGBUS,  &act, NULL);
672
673   __gnat_handler_installed = 1;
674 }
675
676 void
677 __gnat_initialize ()
678 {
679 }
680
681 /******************************************/
682 /* __gnat_initialize (NT-mingw32 version) */
683 /******************************************/
684
685 #elif defined (__MINGW32__)
686 #include <windows.h>
687
688 static LONG __gnat_error_handler PARAMS ((PEXCEPTION_POINTERS));
689
690 /* __gnat_initialize (mingw32).  */
691
692 static LONG
693 __gnat_error_handler (info)
694      PEXCEPTION_POINTERS info;
695 {
696   static int recurse;
697   struct Exception_Data *exception;
698   char *msg;
699
700   switch (info->ExceptionRecord->ExceptionCode)
701     {
702     case EXCEPTION_ACCESS_VIOLATION:
703       /* If the failing address isn't maximally-aligned or if we've
704          recursed, this is a program error.  */
705       if ((info->ExceptionRecord->ExceptionInformation[1] & 3) != 0
706           || recurse)
707         {
708           exception = &program_error;
709           msg = "EXCEPTION_ACCESS_VIOLATION";
710         }
711       else
712         {
713           /* See if the page before the faulting page is accessible.  Do that
714              by trying to access it. */
715           recurse++;
716           * ((volatile char *) (info->ExceptionRecord->ExceptionInformation[1]
717                                 + 4096));
718           exception = &storage_error;
719           msg = "stack overflow (or erroneous memory access)";
720         }
721       break;
722
723     case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
724       exception = &constraint_error;
725       msg = "EXCEPTION_ARRAY_BOUNDS_EXCEEDED";
726       break;
727
728     case EXCEPTION_DATATYPE_MISALIGNMENT:
729       exception = &constraint_error;
730       msg = "EXCEPTION_DATATYPE_MISALIGNMENT";
731       break;
732
733     case EXCEPTION_FLT_DENORMAL_OPERAND:
734       exception = &constraint_error;
735       msg = "EXCEPTION_FLT_DENORMAL_OPERAND";
736       break;
737
738     case EXCEPTION_FLT_DIVIDE_BY_ZERO:
739       exception = &constraint_error;
740       msg = "EXCEPTION_FLT_DENORMAL_OPERAND";
741       break;
742
743     case EXCEPTION_FLT_INVALID_OPERATION:
744       exception = &constraint_error;
745       msg = "EXCEPTION_FLT_INVALID_OPERATION";
746       break;
747
748     case EXCEPTION_FLT_OVERFLOW:
749       exception = &constraint_error;
750       msg = "EXCEPTION_FLT_OVERFLOW";
751       break;
752
753     case EXCEPTION_FLT_STACK_CHECK:
754       exception = &program_error;
755       msg = "EXCEPTION_FLT_STACK_CHECK";
756       break;
757
758     case EXCEPTION_FLT_UNDERFLOW:
759       exception = &constraint_error;
760       msg = "EXCEPTION_FLT_UNDERFLOW";
761       break;
762
763     case EXCEPTION_INT_DIVIDE_BY_ZERO:
764       exception = &constraint_error;
765       msg = "EXCEPTION_INT_DIVIDE_BY_ZERO";
766       break;
767
768     case EXCEPTION_INT_OVERFLOW:
769       exception = &constraint_error;
770       msg = "EXCEPTION_INT_OVERFLOW";
771       break;
772
773     case EXCEPTION_INVALID_DISPOSITION:
774       exception = &program_error;
775       msg = "EXCEPTION_INVALID_DISPOSITION";
776       break;
777
778     case EXCEPTION_NONCONTINUABLE_EXCEPTION:
779       exception = &program_error;
780       msg = "EXCEPTION_NONCONTINUABLE_EXCEPTION";
781       break;
782
783     case EXCEPTION_PRIV_INSTRUCTION:
784       exception = &program_error;
785       msg = "EXCEPTION_PRIV_INSTRUCTION";
786       break;
787
788     case EXCEPTION_SINGLE_STEP:
789       exception = &program_error;
790       msg = "EXCEPTION_SINGLE_STEP";
791       break;
792
793     case EXCEPTION_STACK_OVERFLOW:
794       exception = &storage_error;
795       msg = "EXCEPTION_STACK_OVERFLOW";
796       break;
797
798    default:
799       exception = &program_error;
800       msg = "unhandled signal";
801     }
802
803   recurse = 0;
804   Raise_From_Signal_Handler (exception, msg);
805 }
806
807 void
808 __gnat_install_handler ()
809 {
810   SetUnhandledExceptionFilter (__gnat_error_handler);
811   __gnat_handler_installed = 1;
812 }
813
814 void
815 __gnat_initialize ()
816 {
817
818    /* Initialize floating-point coprocessor. This call is needed because
819       the MS libraries default to 64-bit precision instead of 80-bit
820       precision, and we require the full precision for proper operation,
821       given that we have set Max_Digits etc with this in mind */
822
823    __gnat_init_float ();
824
825    /* initialize a lock for a process handle list - see a-adaint.c for the
826       implementation of __gnat_portable_no_block_spawn, __gnat_portable_wait */
827    __gnat_plist_init();
828 }
829
830 /**************************************/
831 /* __gnat_initialize (Interix version) */
832 /**************************************/
833
834 #elif defined (__INTERIX)
835
836 #include <signal.h>
837
838 static void __gnat_error_handler PARAMS ((int));
839
840 static void
841 __gnat_error_handler (sig)
842      int sig;
843 {
844   struct Exception_Data *exception;
845   char *msg;
846
847   switch (sig)
848     {
849     case SIGSEGV:
850       exception = &storage_error;
851       msg = "stack overflow or erroneous memory access";
852       break;
853
854     case SIGBUS:
855       exception = &constraint_error;
856       msg = "SIGBUS";
857       break;
858
859     case SIGFPE:
860       exception = &constraint_error;
861       msg = "SIGFPE";
862       break;
863
864     default:
865       exception = &program_error;
866       msg = "unhandled signal";
867     }
868
869   Raise_From_Signal_Handler (exception, msg);
870 }
871
872 void
873 __gnat_install_handler ()
874 {
875   struct sigaction act;
876
877   /* Set up signal handler to map synchronous signals to appropriate
878      exceptions.  Make sure that the handler isn't interrupted by another
879      signal that might cause a scheduling event! */
880
881   act.sa_handler = __gnat_error_handler;
882   act.sa_flags = 0;
883   (void) sigemptyset (&act.sa_mask);
884
885   /* Handlers for signals besides SIGSEGV cause c974013 to hang */
886 /*  (void) sigaction (SIGILL,  &act, NULL); */
887 /*  (void) sigaction (SIGABRT, &act, NULL); */
888 /*  (void) sigaction (SIGFPE,  &act, NULL); */
889 /*  (void) sigaction (SIGBUS,  &act, NULL); */
890
891   (void) sigaction (SIGSEGV, &act, NULL);
892
893   __gnat_handler_installed = 1;
894 }
895
896 void
897 __gnat_initialize ()
898 {
899    __gnat_init_float ();
900 }
901
902 /**************************************/
903 /* __gnat_initialize (LynxOS version) */
904 /**************************************/
905
906 #elif defined (__Lynx__)
907
908 void
909 __gnat_initialize ()
910 {
911    __gnat_init_float ();
912 }
913
914 /*********************************/
915 /* __gnat_install_handler (Lynx) */
916 /*********************************/
917
918 void
919 __gnat_install_handler ()
920 {
921   __gnat_handler_installed = 1;
922 }
923
924 /****************************/
925 /* __gnat_initialize (OS/2) */
926 /****************************/
927
928 #elif defined (__EMX__) /* OS/2 dependent initialization */
929
930 void
931 __gnat_initialize ()
932 {
933 }
934
935 /*********************************/
936 /* __gnat_install_handler (OS/2) */
937 /*********************************/
938
939 void
940 __gnat_install_handler ()
941 {
942   __gnat_handler_installed = 1;
943 }
944
945 /***********************************/
946 /* __gnat_initialize (SGI version) */
947 /***********************************/
948
949 #elif defined (sgi)
950
951 #include <signal.h>
952 #include <siginfo.h>
953
954 #ifndef NULL
955 #define NULL 0
956 #endif
957
958 #define SIGADAABORT 48
959 #define SIGNAL_STACK_SIZE 4096
960 #define SIGNAL_STACK_ALIGNMENT 64
961
962 struct Machine_State
963 {
964   sigcontext_t context;
965 };
966
967 static void __gnat_error_handler PARAMS ((int, int, sigcontext_t *));
968
969 static void
970 __gnat_error_handler (sig, code, sc)
971      int sig;
972      int code;
973      sigcontext_t *sc;
974 {
975   struct Machine_State  *mstate;
976   struct Exception_Data *exception;
977   char *msg;
978
979   int i;
980
981   switch (sig)
982     {
983     case SIGSEGV:
984       if (code == EFAULT)
985         {
986           exception = &program_error;
987           msg = "SIGSEGV: (Invalid virtual address)";
988         }
989       else if (code == ENXIO)
990         {
991           exception = &program_error;
992           msg = "SIGSEGV: (Read beyond mapped object)";
993         }
994       else if (code == ENOSPC)
995         {
996           exception = &program_error; /* ??? storage_error ??? */
997           msg = "SIGSEGV: (Autogrow for file failed)";
998         }
999       else if (code == EACCES)
1000         {
1001           /* ??? Re-add smarts to further verify that we launched
1002                  the stack into a guard page, not an attempt to
1003                  write to .text or something */
1004           exception = &storage_error;
1005           msg = "SIGSEGV: (stack overflow or erroneous memory access)";
1006         }
1007       else
1008         {
1009           /* Just in case the OS guys did it to us again.  Sometimes
1010              they fail to document all of the valid codes that are
1011              passed to signal handlers, just in case someone depends
1012              on knowing all the codes */
1013           exception = &program_error;
1014           msg = "SIGSEGV: (Undocumented reason)";
1015         }
1016       break;
1017
1018     case SIGBUS:
1019       /* Map all bus errors to Program_Error.  */
1020       exception = &program_error;
1021       msg = "SIGBUS";
1022       break;
1023
1024     case SIGFPE:
1025       /* Map all fpe errors to Constraint_Error.  */
1026       exception = &constraint_error;
1027       msg = "SIGFPE";
1028       break;
1029
1030     case SIGADAABORT:
1031       if ((*Check_Abort_Status) ())
1032         {
1033           exception = &_abort_signal;
1034           msg = "";
1035         }
1036       else
1037         return;
1038
1039       break;
1040
1041     default:
1042       /* Everything else is a Program_Error. */
1043       exception = &program_error;
1044       msg = "unhandled signal";
1045     }
1046
1047   mstate = (*Get_Machine_State_Addr)();
1048   if (mstate != 0)
1049     memcpy ((void *) mstate, (const void *) sc, sizeof (sigcontext_t));
1050
1051   Raise_From_Signal_Handler (exception, msg);
1052
1053 }
1054
1055 void
1056 __gnat_install_handler ()
1057 {
1058   stack_t ss;
1059   struct sigaction act;
1060
1061   /* Setup signal handler to map synchronous signals to appropriate
1062      exceptions.  Make sure that the handler isn't interrupted by another
1063      signal that might cause a scheduling event! */
1064
1065   act.sa_handler = __gnat_error_handler;
1066   act.sa_flags = SA_NODEFER + SA_RESTART;
1067   (void) sigfillset (&act.sa_mask);
1068   (void) sigemptyset (&act.sa_mask);
1069
1070   (void) sigaction (SIGABRT, &act, NULL);
1071   (void) sigaction (SIGFPE,  &act, NULL);
1072   (void) sigaction (SIGILL,  &act, NULL);
1073   (void) sigaction (SIGSEGV, &act, NULL);
1074   (void) sigaction (SIGBUS,  &act, NULL);
1075   (void) sigaction (SIGADAABORT,  &act, NULL);
1076   __gnat_handler_installed = 1;
1077 }
1078
1079 void
1080 __gnat_initialize ()
1081 {
1082 }
1083
1084 /*************************************************/
1085 /* __gnat_initialize (Solaris and SunOS version) */
1086 /*************************************************/
1087
1088 #elif defined (sun) && defined (__SVR4) && !defined (__vxworks)
1089
1090 #include <signal.h>
1091 #include <siginfo.h>
1092
1093 static void __gnat_error_handler PARAMS ((int, siginfo_t *));
1094
1095 static void
1096 __gnat_error_handler (sig, sip)
1097      int sig;
1098      siginfo_t *sip;
1099 {
1100   struct Exception_Data *exception;
1101   static int recurse = 0;
1102   const char *msg;
1103
1104   /* If this was an explicit signal from a "kill", just resignal it.  */
1105   if (SI_FROMUSER (sip))
1106     {
1107       signal (sig, SIG_DFL);
1108       kill (getpid(), sig);
1109     }
1110
1111   /* Otherwise, treat it as something we handle.  */
1112   switch (sig)
1113     {
1114     case SIGSEGV:
1115       /* If the problem was permissions, this is a constraint error.
1116          Likewise if the failing address isn't maximally aligned or if
1117          we've recursed.
1118
1119          ??? Using a static variable here isn't task-safe, but it's
1120          much too hard to do anything else and we're just determining
1121          which exception to raise.  */
1122       if (sip->si_code == SEGV_ACCERR
1123           || (((long) sip->si_addr) & 3) != 0
1124           || recurse)
1125         {
1126           exception = &constraint_error;
1127           msg = "SIGSEGV";
1128         }
1129       else
1130         {
1131           /* See if the page before the faulting page is accessible.  Do that
1132              by trying to access it.  We'd like to simply try to access
1133              4096 + the faulting address, but it's not guaranteed to be
1134              the actual address, just to be on the same page.  */
1135           recurse++;
1136           ((volatile char *)
1137            ((long) sip->si_addr & - getpagesize ()))[getpagesize ()];
1138           exception = &storage_error;
1139           msg = "stack overflow (or erroneous memory access)";
1140         }
1141       break;
1142
1143     case SIGBUS:
1144       exception = &program_error;
1145       msg = "SIGBUS";
1146       break;
1147
1148     case SIGFPE:
1149       exception = &constraint_error;
1150       msg = "SIGFPE";
1151       break;
1152
1153     default:
1154       exception = &program_error;
1155       msg = "unhandled signal";
1156     }
1157
1158   recurse = 0;
1159
1160   Raise_From_Signal_Handler (exception, msg);
1161 }
1162
1163 void
1164 __gnat_install_handler ()
1165 {
1166   struct sigaction act;
1167
1168   /* Set up signal handler to map synchronous signals to appropriate
1169      exceptions.  Make sure that the handler isn't interrupted by another
1170      signal that might cause a scheduling event! */
1171
1172   act.sa_handler = __gnat_error_handler;
1173   act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
1174   (void) sigemptyset (&act.sa_mask);
1175
1176   (void) sigaction (SIGABRT, &act, NULL);
1177   (void) sigaction (SIGFPE,  &act, NULL);
1178   (void) sigaction (SIGSEGV, &act, NULL);
1179   (void) sigaction (SIGBUS,  &act, NULL);
1180
1181   __gnat_handler_installed = 1;
1182 }
1183
1184 void
1185 __gnat_initialize ()
1186 {
1187 }
1188
1189 /***********************************/
1190 /* __gnat_initialize (SNI version) */
1191 /***********************************/
1192
1193 #elif defined (__sni__)
1194
1195 /* SNI needs special defines and includes */
1196
1197 #define _XOPEN_SOURCE
1198 #define _POSIX_SOURCE
1199 #include <signal.h>
1200
1201 extern size_t __gnat_getpagesize PARAMS ((void));
1202 static void __gnat_error_handler PARAMS ((int));
1203
1204 /* The run time needs this function which is a #define in SNI */
1205
1206 size_t
1207 __gnat_getpagesize ()
1208 {
1209   return getpagesize ();
1210 }
1211
1212 static void
1213 __gnat_error_handler (sig)
1214      int sig;
1215 {
1216   struct Exception_Data *exception;
1217   char *msg;
1218
1219   switch (sig)
1220     {
1221     case SIGSEGV:
1222       /* FIXME: we need to detect the case of a *real* SIGSEGV */
1223       exception = &storage_error;
1224       msg = "stack overflow or erroneous memory access";
1225       break;
1226
1227     case SIGBUS:
1228       exception = &constraint_error;
1229       msg = "SIGBUS";
1230       break;
1231
1232     case SIGFPE:
1233       exception = &constraint_error;
1234       msg = "SIGFPE";
1235       break;
1236
1237     default:
1238       exception = &program_error;
1239       msg = "unhandled signal";
1240     }
1241
1242   Raise_From_Signal_Handler (exception, msg);
1243 }
1244
1245 void
1246 __gnat_install_handler ()
1247 {
1248   struct sigaction act;
1249
1250   /* Set up signal handler to map synchronous signals to appropriate
1251      exceptions.  Make sure that the handler isn't interrupted by another
1252      signal that might cause a scheduling event! */
1253
1254   act.sa_handler = __gnat_error_handler;
1255   act.sa_flags = SA_NODEFER | SA_RESTART;
1256   (void) sigemptyset (&act.sa_mask);
1257
1258   (void) sigaction (SIGABRT, &act, NULL);
1259   (void) sigaction (SIGFPE,  &act, NULL);
1260   (void) sigaction (SIGILL,  &act, NULL);
1261   (void) sigaction (SIGSEGV, &act, NULL);
1262   (void) sigaction (SIGBUS,  &act, NULL);
1263
1264   __gnat_handler_installed = 1;
1265 }
1266
1267 void
1268 __gnat_initialize ()
1269 {
1270 }
1271
1272 /***********************************/
1273 /* __gnat_initialize (VMS version) */
1274 /***********************************/
1275
1276 #elif defined (VMS)
1277
1278 /* The prehandler actually gets control first on a condition. It swaps the
1279    stack pointer and calls the handler (__gnat_error_handler). */
1280 extern long __gnat_error_prehandler ();
1281
1282 extern char *__gnat_error_prehandler_stack;   /* Alternate signal stack */
1283
1284 /* Conditions that don't have an Ada exception counterpart must raise
1285    Non_Ada_Error.  Since this is defined in s-auxdec, it should only be
1286    referenced by user programs, not the compiler or tools. Hence the
1287    #ifdef IN_RTS. */
1288
1289 #ifdef IN_RTS
1290 #define Non_Ada_Error system__aux_dec__non_ada_error
1291 extern struct Exception_Data Non_Ada_Error;
1292
1293 #define Coded_Exception system__vms_exception_table__coded_exception
1294 extern struct Exception_Data *Coded_Exception (int);
1295 #endif
1296
1297 /* Define macro symbols for the VMS conditions that become Ada exceptions.
1298    Most of these are also defined in the header file ssdef.h which has not
1299    yet been converted to be recoginized by Gnu C. Some, which couldn't be
1300    located, are assigned names based on the DEC test suite tests which
1301    raise them. */
1302
1303 #define SS$_ACCVIO            12
1304 #define SS$_DEBUG           1132
1305 #define SS$_INTDIV          1156
1306 #define SS$_HPARITH         1284
1307 #define SS$_STKOVF          1364
1308 #define SS$_RESIGNAL        2328
1309 #define MTH$_FLOOVEMAT   1475268       /* Some ACVC_21 CXA tests */
1310 #define SS$_CE24VRU      3253636       /* Write to unopened file */
1311 #define SS$_C980VTE      3246436       /* AST requests time slice */
1312 #define CMA$_EXIT_THREAD 4227492
1313 #define CMA$_EXCCOPLOS   4228108
1314 #define CMA$_ALERTED     4227460
1315
1316 struct descriptor_s {unsigned short len, mbz; char *adr; };
1317
1318 long __gnat_error_handler PARAMS ((int *, void *));
1319
1320 long
1321 __gnat_error_handler (sigargs, mechargs)
1322      int *sigargs;
1323      void *mechargs;
1324 {
1325   struct Exception_Data *exception = 0;
1326   char *msg = "";
1327   char message[256];
1328   long prvhnd;
1329   struct descriptor_s msgdesc;
1330   int msg_flag = 0x000f; /* 1 bit for each of the four message parts */
1331   unsigned short outlen;
1332   char curr_icb[544];
1333   long curr_invo_handle;
1334   long *mstate;
1335
1336   /* Resignaled conditions aren't effected by by pragma Import_Exception */
1337
1338   switch (sigargs[1])
1339   {
1340
1341     case CMA$_EXIT_THREAD:
1342       return SS$_RESIGNAL;
1343
1344     case SS$_DEBUG: /* Gdb attach, resignal to merge activate gdbstub. */
1345       return SS$_RESIGNAL;
1346
1347     case 1409786: /* Nickerson bug #33 ??? */
1348       return SS$_RESIGNAL;
1349
1350     case 1381050: /* Nickerson bug #33 ??? */
1351       return SS$_RESIGNAL;
1352
1353     case 11829410: /* Resignalled as Use_Error for CE10VRC */
1354       return SS$_RESIGNAL;
1355
1356   }
1357
1358 #ifdef IN_RTS
1359   /* See if it's an imported exception. Mask off severity bits. */
1360   exception = Coded_Exception (sigargs[1] & 0xfffffff8);
1361   if (exception)
1362     {
1363       msgdesc.len = 256;
1364       msgdesc.mbz = 0;
1365       msgdesc.adr = message;
1366       SYS$GETMSG (sigargs[1], &outlen, &msgdesc, msg_flag, 0);
1367       message[outlen] = 0;
1368       msg = message;
1369
1370       exception->Name_Length = 19;
1371       /* The full name really should be get sys$getmsg returns. ??? */
1372       exception->Full_Name = "IMPORTED_EXCEPTION";
1373       exception->Import_Code = sigargs[1] & 0xfffffff8;
1374     }
1375 #endif
1376
1377   if (exception == 0)
1378     switch (sigargs[1])
1379       {
1380       case SS$_ACCVIO:
1381         if (sigargs[3] == 0)
1382           {
1383             exception = &constraint_error;
1384             msg = "access zero";
1385           }
1386         else
1387           {
1388             exception = &storage_error;
1389             msg = "stack overflow (or erroneous memory access)";
1390           }
1391         break;
1392
1393       case SS$_STKOVF:
1394         exception = &storage_error;
1395         msg = "stack overflow";
1396         break;
1397
1398       case SS$_INTDIV:
1399         exception = &constraint_error;
1400         msg = "division by zero";
1401         break;
1402
1403       case SS$_HPARITH:
1404 #ifndef IN_RTS
1405         return SS$_RESIGNAL; /* toplev.c handles for compiler */
1406 #else
1407         {
1408           exception = &constraint_error;
1409           msg = "arithmetic error";
1410         }
1411 #endif
1412         break;
1413
1414       case MTH$_FLOOVEMAT:
1415         exception = &constraint_error;
1416         msg = "floating overflow in math library";
1417         break;
1418
1419       case SS$_CE24VRU:
1420         exception = &constraint_error;
1421         msg = "";
1422         break;
1423
1424       case SS$_C980VTE:
1425         exception = &program_error;
1426         msg = "";
1427         break;
1428
1429       default:
1430 #ifndef IN_RTS
1431         exception = &program_error;
1432 #else
1433         /* User programs expect Non_Ada_Error to be raised, reference
1434            DEC Ada test CXCONDHAN. */
1435         exception = &Non_Ada_Error;
1436 #endif
1437         msgdesc.len = 256;
1438         msgdesc.mbz = 0;
1439         msgdesc.adr = message;
1440         SYS$GETMSG (sigargs[1], &outlen, &msgdesc, msg_flag, 0);
1441         message[outlen] = 0;
1442         msg = message;
1443         break;
1444       }
1445
1446   mstate = (long *) (*Get_Machine_State_Addr) ();
1447   if (mstate != 0)
1448     {
1449       LIB$GET_CURR_INVO_CONTEXT (&curr_icb);
1450       LIB$GET_PREV_INVO_CONTEXT (&curr_icb);
1451       LIB$GET_PREV_INVO_CONTEXT (&curr_icb);
1452       curr_invo_handle = LIB$GET_INVO_HANDLE (&curr_icb);
1453       *mstate = curr_invo_handle;
1454     }
1455   Raise_From_Signal_Handler (exception, msg);
1456 }
1457
1458 void
1459 __gnat_install_handler ()
1460 {
1461   long prvhnd;
1462   char *c;
1463
1464   c = (char *) xmalloc (2049);
1465
1466   __gnat_error_prehandler_stack = &c[2048];
1467
1468   /* __gnat_error_prehandler is an assembly function.  */
1469   SYS$SETEXV (1, __gnat_error_prehandler, 3, &prvhnd);
1470   __gnat_handler_installed = 1;
1471 }
1472
1473 void
1474 __gnat_initialize()
1475 {
1476 }
1477
1478 /***************************************/
1479 /* __gnat_initialize (VXWorks version) */
1480 /***************************************/
1481
1482 #elif defined(__vxworks)
1483
1484 #include <signal.h>
1485 #include <taskLib.h>
1486 #include <intLib.h>
1487 #include <iv.h>
1488
1489 static void __gnat_init_handler PARAMS ((int));
1490 extern int __gnat_inum_to_ivec PARAMS ((int));
1491 static void __gnat_error_handler PARAMS ((int, int, struct sigcontext *));
1492
1493 static void
1494 __gnat_int_handler (interr)
1495       int interr;
1496 {
1497   /* Note that we should use something like Raise_From_Int_Handler here, but
1498      for now Raise_From_Signal_Handler will do the job. ??? */
1499
1500   Raise_From_Signal_Handler (&storage_error, "stack overflow");
1501 }
1502
1503 /* Used for stack-checking on VxWorks. Must be task-local in
1504    tasking programs */
1505
1506 void *__gnat_stack_limit = NULL;
1507
1508 #ifndef __alpha_vxworks
1509
1510 /* getpid is used by s-parint.adb, but is not defined by VxWorks, except
1511    on Alpha VxWorks */
1512
1513 extern long getpid PARAMS ((void));
1514
1515 long
1516 getpid ()
1517 {
1518   return taskIdSelf ();
1519 }
1520 #endif
1521
1522 /* This is needed by the GNAT run time to handle Vxworks interrupts */
1523 int
1524 __gnat_inum_to_ivec (num)
1525      int num;
1526 {
1527   return INUM_TO_IVEC (num);
1528 }
1529
1530 static void
1531 __gnat_error_handler (sig, code, sc)
1532      int sig;
1533      int code;
1534      struct sigcontext *sc;
1535 {
1536   struct Exception_Data *exception;
1537   sigset_t mask;
1538   int result;
1539   char *msg;
1540
1541   /* VxWorks will always mask out the signal during the signal handler and
1542      will reenable it on a longjmp.  GNAT does not generate a longjmp to
1543      return from a signal handler so the signal will still be masked unless
1544      we unmask it. */
1545   (void) sigprocmask (SIG_SETMASK, NULL, &mask);
1546   sigdelset (&mask, sig);
1547   (void) sigprocmask (SIG_SETMASK, &mask, NULL);
1548
1549   /* VxWorks will suspend the task when it gets a hardware exception.  We
1550      take the liberty of resuming the task for the application. */
1551   if (taskIsSuspended (taskIdSelf ()) != 0)
1552     (void) taskResume (taskIdSelf ());
1553
1554   switch (sig)
1555     {
1556     case SIGFPE:
1557       exception = &constraint_error;
1558       msg = "SIGFPE";
1559       break;
1560     case SIGILL:
1561       exception = &constraint_error;
1562       msg = "SIGILL";
1563       break;
1564     case SIGSEGV:
1565       exception = &program_error;
1566       msg = "SIGSEGV";
1567       break;
1568     case SIGBUS:
1569       exception = &program_error;
1570       msg = "SIGBUS";
1571       break;
1572     default:
1573       exception = &program_error;
1574       msg = "unhandled signal";
1575     }
1576
1577   Raise_From_Signal_Handler (exception, msg);
1578 }
1579
1580 void
1581 __gnat_install_handler ()
1582 {
1583   struct sigaction act;
1584
1585   /* Setup signal handler to map synchronous signals to appropriate
1586      exceptions.  Make sure that the handler isn't interrupted by another
1587      signal that might cause a scheduling event! */
1588
1589   act.sa_handler = __gnat_error_handler;
1590   act.sa_flags = SA_SIGINFO | SA_ONSTACK;
1591   (void) sigemptyset (&act.sa_mask);
1592
1593   (void) sigaction (SIGFPE,  &act, NULL);
1594   (void) sigaction (SIGILL,  &act, NULL);
1595   (void) sigaction (SIGSEGV, &act, NULL);
1596   (void) sigaction (SIGBUS,  &act, NULL);
1597
1598   __gnat_handler_installed = 1;
1599 }
1600
1601 #define HAVE_GNAT_INIT_FLOAT
1602
1603 void
1604 __gnat_init_float ()
1605 {
1606 #if defined (_ARCH_PPC) && !defined (_SOFT_FLOAT)
1607   /* Disable overflow/underflow exceptions on the PPC processor, this is needed
1608       to get correct Ada semantic */
1609   asm ("mtfsb0 25");
1610   asm ("mtfsb0 26");
1611 #endif
1612 }
1613
1614 void
1615 __gnat_initialize ()
1616 {
1617   TASK_DESC pTaskDesc;
1618
1619   if (taskInfoGet (taskIdSelf (), &pTaskDesc) != OK)
1620     printErr ("Cannot get task info");
1621
1622   __gnat_stack_limit = (void *) pTaskDesc.td_pStackLimit;
1623
1624   __gnat_init_float ();
1625
1626 #ifdef __mips_vxworks
1627 #if 0
1628   /* For now remove this handler, since it is causing interferences with gdb */
1629
1630   /* Connect the overflow trap directly to the __gnat_int_handler routine
1631    as it is not converted to a signal by VxWorks. */
1632
1633   intConnect (INUM_TO_IVEC (IV_TRAP_VEC), &__gnat_int_handler, IV_TRAP_VEC);
1634 #endif
1635 #endif
1636 }
1637
1638 /***************************************/
1639 /* __gnat_initialize (RTEMS version) */
1640 /***************************************/
1641
1642 #elif defined(__rtems__)
1643
1644 extern void __gnat_install_handler ();
1645
1646 /* For RTEMS, each bsp will provide a custom __gnat_install_handler (). */
1647
1648 void
1649 __gnat_initialize ()
1650 {
1651    __gnat_install_handler ();
1652 }
1653
1654 #else
1655
1656 /* For all other versions of GNAT, the initialize routine and handler
1657    installation do nothing */
1658
1659 /***************************************/
1660 /* __gnat_initialize (default version) */
1661 /***************************************/
1662
1663 void
1664 __gnat_initialize ()
1665 {
1666 }
1667
1668 /********************************************/
1669 /* __gnat_install_handler (default version) */
1670 /********************************************/
1671
1672 void
1673 __gnat_install_handler ()
1674 {
1675   __gnat_handler_installed = 1;
1676 }
1677
1678 #endif
1679
1680 /*********************/
1681 /* __gnat_init_float */
1682 /*********************/
1683
1684 /* This routine is called as each process thread is created, for possible
1685    initialization of the FP processor. This version is used under INTERIX,
1686    WIN32 and could be used under OS/2 */
1687
1688 #if defined (_WIN32) || defined (__INTERIX) || defined (__EMX__) \
1689   || defined (__Lynx__)
1690
1691 #define HAVE_GNAT_INIT_FLOAT
1692
1693 void
1694 __gnat_init_float ()
1695 {
1696 #if defined (__i386__) || defined (i386)
1697
1698   /* This is used to properly initialize the FPU on an x86 for each
1699      process thread. */
1700
1701   asm ("finit");
1702
1703 #endif  /* Defined __i386__ */
1704 }
1705 #endif
1706
1707 #ifndef HAVE_GNAT_INIT_FLOAT
1708
1709 /* All targets without a specific __gnat_init_float will use an empty one */
1710 void
1711 __gnat_init_float ()
1712 {
1713 }
1714 #endif