home *** CD-ROM | disk | FTP | other *** search
/ Aminet 18 / aminetcdnumber181997.iso / Aminet / dev / gcc / ixemulsrc.lha / ixemul / library / machdep.c < prev    next >
C/C++ Source or Header  |  1996-12-11  |  21KB  |  701 lines

  1. /*
  2.  *  This file is part of ixemul.library for the Amiga.
  3.  *  Copyright (C) 1991, 1992  Markus M. Wild
  4.  *
  5.  *  This library is free software; you can redistribute it and/or
  6.  *  modify it under the terms of the GNU Library General Public
  7.  *  License as published by the Free Software Foundation; either
  8.  *  version 2 of the License, or (at your option) any later version.
  9.  *
  10.  *  This library is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  *  Library General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU Library General Public
  16.  *  License along with this library; if not, write to the Free
  17.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  *  machdep.c,v 1.1.1.1 1994/04/04 04:30:40 amiga Exp
  20.  *
  21.  *  machdep.c,v
  22.  * Revision 1.1.1.1  1994/04/04  04:30:40  amiga
  23.  * Initial CVS check in.
  24.  *
  25.  *  Revision 1.5  1993/11/05  21:59:18  mwild
  26.  *  add code to deal with inet.library
  27.  *
  28.  *  Revision 1.4  1992/10/20  16:25:24  mwild
  29.  *  no nasty 'c' polling in DEF-signalhandler...
  30.  *
  31.  *  Revision 1.3  1992/08/09  20:57:59  amiga
  32.  *  add volatile to sysbase access, or the optimizer takes illegal shortcuts...
  33.  *
  34.  *  Revision 1.2  1992/07/04  19:20:20  mwild
  35.  *  add yet another state in which not to force a context switch.
  36.  *  Probably unnecessary paranoia...
  37.  *
  38.  * Revision 1.1  1992/05/14  19:55:40  mwild
  39.  * Initial revision
  40.  *
  41.  */
  42.  
  43. #define _KERNEL
  44. #include "ixemul.h"
  45. #include <sys/wait.h>
  46. #include "kprintf.h"
  47.  
  48. #include <string.h>
  49. #include <exec/execbase.h>
  50.  
  51. /* jump to pc in supervisor mode, usp is set to USP before */
  52. extern void volatile supervisor (u_int pc, u_int usp);
  53.  
  54. /* context restore functions for 68000 and 68020 rsp */
  55.  
  56. /* takes the sigcontext * from the usp and restores it 
  57.  * Assumes it's called by Supervisor(), ie. with an exception frame
  58.  */
  59. extern void volatile do_sigreturn (void);
  60.  
  61. /*
  62.  * These two are callable with jsr from supervisor mode, and then
  63.  * set up a fake exception frame and call do_sigreturn().
  64.  */
  65. extern void volatile sup00_do_sigreturn_ssp (u_int ssp);
  66. extern void volatile sup00_do_sigreturn (void);
  67. extern void volatile sup00_do_sigresume (void);
  68. extern void volatile restore_00 ();
  69. extern void volatile sup20_do_sigreturn_ssp (u_int ssp);
  70. extern void volatile sup20_do_sigreturn (void);
  71. extern void volatile sup20_do_sigresume (void);
  72. extern void volatile restore_20 ();
  73. /*
  74.  * Either one of sup{00,20}_do_sigreturn, set by configure_context_switch ();
  75.  */
  76. static void volatile (*sup_do_sigresume) (void);
  77. static void volatile (*sup_do_sigreturn) (void);
  78. static void volatile (*sup_do_sigreturn_ssp) (u_int ssp);
  79.  
  80. void setrun (struct Task *t);
  81. void sendsig(struct user *p, sig_t catcher, int sig, int mask, unsigned code, void *addr);
  82.  
  83. struct sigframe {
  84.   int            sf_signum;    /* signo for handler */
  85.   int            sf_code;    /* additional info for handler */
  86.   void            *sf_addr;    /* yet another info for handler ;-)) */
  87.   sig_t            sf_handler;    /* handler addr for u_sigc */
  88.   struct sigcontext     sf_sc;        /* actual context */
  89. };
  90.  
  91.  
  92. void
  93. configure_context_switch (void)
  94. {
  95.   if (betterthan68000())
  96.     {
  97.       sup_do_sigresume = sup20_do_sigresume;
  98.       sup_do_sigreturn = sup20_do_sigreturn;
  99.       sup_do_sigreturn_ssp = sup20_do_sigreturn_ssp;
  100.     }
  101.   else
  102.     {
  103.       sup_do_sigresume = sup00_do_sigresume;
  104.       sup_do_sigreturn = sup00_do_sigreturn;
  105.       sup_do_sigreturn_ssp = sup00_do_sigreturn_ssp;
  106.     }
  107. }
  108.  
  109. void volatile
  110. sigreturn (struct sigcontext *sc)
  111. {
  112.   supervisor ((u_int) do_sigreturn, (u_int) sc);
  113. }
  114.  
  115. void volatile
  116. sig_trampoline (struct sigframe sf)
  117. {
  118.   if (u.u_a4)
  119.     asm ("movel %0,a4" : : "g" (u.u_a4));
  120.   ((void (*)())sf.sf_handler) (sf.sf_signum, sf.sf_code, sf.sf_addr, & sf.sf_sc);
  121.  
  122.   sigreturn (& sf.sf_sc);
  123. }
  124.  
  125. /*
  126.  * This one is executed in Supervisor mode, just before dispatching this
  127.  * task, so be as quick as possible here !
  128.  */
  129. void
  130. sig_launch (void) 
  131. {
  132.   struct Task         *me         = SysBase->ThisTask;
  133.   /* precalculate struct user, so we don't have to go thru SysBase all the time */
  134.   struct user         *p         = getuser(me);
  135.   sigset_t         sigmsg         = sigmask (SIGMSG);
  136.   sigset_t        sigint         = sigmask (SIGINT);
  137.   sigset_t         newsigs;
  138.   int             i;
  139.   u_int            usp = 0, orig_usp;
  140.   struct sigcontext     *sc;
  141.   u_int            ret_pc, ret_ssp;
  142.  
  143.   /* GCC supports nested functions, and that's just what I need! */
  144.  
  145.   void setup_sigcontext(void)
  146.   {
  147.     usp = orig_usp = get_usp () + 8;     /* set up by our glue_launch() stub */
  148.     
  149.     /* the glue passes us the values of the pc and ssp to restore, if we should
  150.      * decide to sup_do_sigreturn_ssp() out of here, instead of leaving harmlessly..
  151.      */
  152.     ret_pc  = ((u_int *)usp)[-2];
  153.     ret_ssp = ((u_int *)usp)[-1];
  154.     
  155.     /* push a sigcontext that will get us back if no other signals
  156.      * were produced */
  157.     usp -= sizeof (struct sigcontext);
  158.     sc = (struct sigcontext *) usp;
  159.     set_usp (usp);
  160.     
  161.     sc->sc_onstack = p->u_onstack;
  162.     sc->sc_mask     = p->p_sigmask;
  163.     sc->sc_sp     = orig_usp;
  164.  
  165.     /* the OS context restore function expects a5 to contain the usp, so
  166.      * we have to obey.. */
  167.     sc->sc_fp     = orig_usp;
  168.     sc->sc_ap     = *(u_int *)&me->tc_Flags;
  169.     sc->sc_pc     = ret_pc;
  170.     sc->sc_ps     = get_sr();
  171.   
  172.     p->u_regs = NULL;
  173.     p->u_fpregs = NULL;
  174.   };
  175.  
  176.   if (p->u_mask_state) /* do not handle signals while the stop-handler is running */
  177.     return;
  178.  
  179.   /* if we're inside ix_sleep, no signal processing is done to break the
  180.      Wait there as soon as possible. Signals resume on return of ix_sleep */
  181.   /* Likewise if the process is stopped for debugging (SSTOP).  */
  182.   if (p->p_stat == SSLEEP || p->p_stat == SSTOP)
  183.     return;
  184.  
  185.   /* special processing for Wait()ing in Commodore inet.library. They
  186.      do reasonable interrupt checking, but only on SIGBREAKF_CTRL_C. So
  187.      whenever we have a signal to deliver, send ^C.. */
  188.   if (p->p_stat == SWAIT)
  189.     {
  190.       setup_sigcontext();
  191.       if (CURSIG (p))
  192.         Signal (me, SIGBREAKF_CTRL_C);
  193.       goto out;
  194.     }
  195.  
  196.   /* smells kludgy I know...... */
  197.   if (me->tc_TDNestCnt >= 0 || me->tc_IDNestCnt >= 0)
  198.     return;
  199.  
  200.   setup_sigcontext();
  201.  
  202.   /*
  203.    * first check AmigaOS signals. If SIGMSG is set to SIG_IGN or SIG_DFL, 
  204.    * we do our default mapping of SIGBREAKF_CTRL_C into SIGINT.
  205.    */
  206.   newsigs      = me->tc_SigRecvd & ~p->u_lastrcvsig;
  207.   p->u_lastrcvsig = me->tc_SigRecvd;
  208.  
  209.   if (p->u_ixnetbase)
  210.     netcall(NET__siglaunch, newsigs);
  211.  
  212.   if (((p->p_sigignore & sigmsg) || !(p->p_sigcatch & sigmsg)) 
  213.       && (newsigs & SIGBREAKF_CTRL_C))
  214.     {
  215.       /* in that case send us a SIGINT, if it's not ignored */
  216.       if (!(p->p_sigignore & sigint))
  217.         {
  218.       struct Process *proc = (struct Process *)(p->u_session ? p->u_session->pgrp : (int)me);
  219.           _psignalgrp(proc, SIGINT);
  220.         }
  221.         
  222.       /* in this mode we fully handle and use SIGBREAKF_CTRL_C, so remove it
  223.        * from the Exec signal mask */
  224.        
  225.       me->tc_SigRecvd &= ~SIGBREAKF_CTRL_C;
  226.       p->u_lastrcvsig &= ~SIGBREAKF_CTRL_C;
  227.     }
  228.   else if (newsigs && (p->p_sigcatch & sigmsg))
  229.     {
  230.       /* if possible, deliver the signal directly to get a code argument */
  231.       if (!(p->p_flag & STRC) && !(p->p_sigmask & sigmsg))
  232.         {
  233.           p->u_ru.ru_nsignals++;
  234.           sendsig(p, p->u_signal[SIGMSG], SIGMSG, p->p_sigmask, newsigs, 0);
  235.           p->p_sigmask |= p->u_sigmask[SIGMSG] | sigmsg;
  236.           setrun (me);
  237.         }
  238.       else
  239.         _psignal (me, SIGMSG);
  240.     }
  241.  
  242.   if ((i = CURSIG(p)))
  243.     {
  244.       psig (p, i);
  245.     }
  246.  
  247. out:
  248.   /* now try to optimize. We could always call sup_do_sigreturn here, but if no
  249.    * signals generated frames, we can just as well simply return, after having
  250.    * restored our usp */
  251.   if (usp == get_usp ())
  252.     {
  253.       /* this is probably not even necessary, since after processing sig_launch
  254.        * the OS reinstalls the usp as me->tc_SPReg, but I guess it's cleaner to
  255.        * do it explicitly here, to show that we reset usp to what it was before
  256.        */
  257.       set_usp (orig_usp);
  258.       return;
  259.     }
  260.   sup_do_sigreturn_ssp (ret_ssp);
  261. }
  262.  
  263.  
  264. void
  265. switch_glue (void)
  266. {
  267. }
  268.  
  269. /*
  270.  * Send an interrupt to process.
  271.  * Called from psig() which is called from sig_launch, thus we are in
  272.  * SUPERVISOR .
  273.  */
  274. void
  275. sendsig (struct user *p, sig_t catcher, int sig, int mask, unsigned code, void *addr)
  276. {
  277.   struct Task        *me        = SysBase->ThisTask;
  278.   u_int         usp, orig_usp;
  279.   struct sigframe     *sf;
  280.   struct sigcontext    *sc;
  281.   int            oonstack;
  282.   int            to_stopped_handler = (catcher == (sig_t)stopped_process_handler);
  283.   int             *dummy_frame;
  284.  
  285.   orig_usp = get_usp();    /* get value to restore later */
  286.  
  287.   oonstack = p->u_onstack;
  288.  
  289.   if (!p->u_onstack && (p->u_sigonstack & sigmask(sig)))
  290.     {
  291.       p->u_onstack = 1;
  292.       usp = (u_int) p->u_sigsp;
  293.     }
  294.   else
  295.     usp = orig_usp;
  296.   
  297.   /* make room for dummy stack frame (used by GDB) */
  298.   usp -= 8;
  299.   dummy_frame = (int *)usp;
  300.   /* push signal frame */
  301.   usp -= sizeof (struct sigframe);
  302.   sf = (struct sigframe *) usp;
  303.   
  304.   /* fill out the frame */
  305.   sf->sf_signum        = sig;
  306.   sf->sf_code          = code;
  307.   sf->sf_addr           = addr;
  308.   sf->sf_handler       = catcher;
  309.   sf->sf_sc.sc_onstack = oonstack;
  310.   sf->sf_sc.sc_mask    = mask;
  311.   sf->sf_sc.sc_sp      = (int) orig_usp;    /* previous sigcontext */
  312.   sf->sf_sc.sc_fp      = p->u_regs ? p->u_regs->r_regs[13] : 0;
  313.   sf->sf_sc.sc_ap      = *(u_int *)&me->tc_Flags;
  314.   sf->sf_sc.sc_ps      = get_sr() & ~0x8000;    /* we're in supervisor then */
  315.   /* this pc will restore it */
  316.   sf->sf_sc.sc_pc      = (int)(to_stopped_handler ? sup_do_sigresume : sup_do_sigreturn);
  317.  
  318.   /* push a signal context to call sig_trampoline */
  319.   usp -= sizeof (struct sigcontext);
  320.   sc = (struct sigcontext *) usp;
  321.  
  322.   /*
  323.    * NOTE: we set the default of a handler to Permit(), Enable(). I guess this
  324.    *       makes sense, since if either Forbid() or Disable() is active, it
  325.    *       shouldn't be possible to invoke a signal anyway, EXCEPT if the
  326.    *       task is Wait()ing, then the OS calls Switch() directly while
  327.    *       either Disable() or Forbid() is active (depends on OS version).
  328.    */
  329.  
  330.   sc->sc_onstack = p->u_onstack;
  331.   sc->sc_mask    = p->p_sigmask;
  332.   sc->sc_sp     = ((int) sf) - 4; /* so that sp@(4) is the argument */
  333.   dummy_frame[0] = (int)(p->u_regs ? p->u_regs->r_regs[13] : 0);
  334.   dummy_frame[1] = (int)(p->u_regs ? p->u_regs->r_pc : 0);
  335.   sc->sc_fp     = (int)dummy_frame;
  336.   sc->sc_ap     = (me->tc_Flags << 24) | (me->tc_State << 16) |
  337.              ((u_char)(-1) << 8) | (u_char)(-1);
  338.   sc->sc_ps     = ((to_stopped_handler || !p->u_regs) ? 0 : (p->u_regs->r_sr & ~0x2000));
  339.   sc->sc_pc     = (int) sig_trampoline;
  340.   
  341.   set_usp (usp);
  342. }
  343.  
  344.  
  345. /*
  346.  * called as the default action of a signal that terminates the process
  347.  */
  348. void
  349. sig_exit (unsigned int code)
  350. {
  351.   /* the whole purpose of this code inside is to
  352.    * prettyprint and identify the job that just terminates
  353.    * This stuff should be handled by a shell, but since there's (yet) no
  354.    * shell that knows how to interpret a signal-exit code I have to do it
  355.    * here myself...
  356.    */
  357.  
  358.   extern char *sys_siglist[NSIG];
  359.   extern void exit2(int);
  360.   struct Process *me = (struct Process *)(SysBase->ThisTask);
  361.   char err_buf[255];
  362.   struct CommandLineInterface *cli;
  363.   char process_name[255];
  364.   int is_fg;
  365.  
  366.   /* make sure we're not interrupted in this last step.. */
  367.   u.p_flag &= ~STRC;    /* disable tracing */
  368.   syscall (SYS_sigsetmask, ~0);
  369.   if ((ix.ix_flags & ix_create_enforcer_hit) && betterthan68010())
  370.     {
  371.       /* This piece of assembly will skip all the saved registers, signal
  372.      contexts, etc. on the stack and set the stack pointer accordingly.
  373.      The number 700 has been determined by experimenting. After setting
  374.      the SP it will put the exit code into the address 0xDEADDEAD. This
  375.      creates an Enforcer hit, and Enforcer will show a stack dump starting
  376.      with the new SP. If we didn't add 700 bytes to the SP, then you would
  377.      have to configure Enforcer to use a stacktrace of more than 24 lines
  378.      before you would get to the relevant parts of the trace. After that we
  379.      add a nop and restore the SP. The nop was needed because due to the
  380.      pipelining of a 68040 the SP was already updated before Enforcer could
  381.      read the value of the SP. More nops may be needed for the 68060 CPU. */
  382.  
  383.       asm ("movel %0,d0
  384.             addw  #700,sp
  385.             movel d0,0xdeaddead
  386.             nop
  387.             addqw #2,sp
  388.             movel d0,0xdeaddead
  389.             nop
  390.             addaw #-702,sp" : /* no output */ : "a" (code));
  391.     }
  392.   
  393.   /* output differs depending on
  394.    *  o  whether we're a CLI or a WB process (stderr or requester)
  395.    *  o  whether this is a foreground or background process
  396.    *  o  whether this is SIGINT or not
  397.    */
  398.  
  399.   if ((cli = BTOCPTR (me->pr_CLI)))
  400.     {
  401.       char *tmp = BTOCPTR (cli->cli_CommandName);
  402.       int   len = *tmp++;
  403.       
  404.       if (len > sizeof (process_name) - 1)
  405.         len = sizeof (process_name) - 1;
  406.       
  407.       bcopy (tmp, process_name, len);
  408.       process_name[len] = 0;
  409.       
  410.       is_fg = cli->cli_Interactive && !cli->cli_Background;
  411.  
  412.     }
  413.   else
  414.     {
  415.       process_name[0] = 0;
  416.       if (me->pr_Task.tc_Node.ln_Name)
  417.         strncpy (process_name, me->pr_Task.tc_Node.ln_Name, sizeof (process_name) - 1);
  418.         
  419.       /* no WB process is ever considered fg */
  420.       is_fg = 0;
  421.  
  422.     }
  423.  
  424.   /* if is_fg and SIGINT, simulate tty-driver and display ^C */
  425.   if (!(is_fg && (code == SIGINT)))
  426.     {
  427.       strcpy (err_buf, (code < NSIG) ? sys_siglist[code] : "Unknown signal");
  428.  
  429.       /* if is_fg, don't display the job */
  430.       if (! is_fg)
  431.         {
  432.           strcat (err_buf, " - ");
  433.       strcat (err_buf, process_name);
  434.           /* if we're a CLI we have an argument line saved, that we can print
  435.            * as well */
  436.       if (cli)
  437.               {
  438.           int line_len;
  439.           char *cp;
  440.           
  441.           /* we can display upto column 77, this should be save on all normal
  442.            * amiga CLI windows */
  443.           line_len = 77 - strlen (err_buf) - 1;
  444.           if (line_len > u.u_arglinelen)
  445.             line_len = u.u_arglinelen;
  446.  
  447.           if (line_len > 0 && u.u_argline)
  448.             {
  449.               strcat (err_buf, " ");
  450.           strncat (err_buf, u.u_argline, line_len);
  451.         }
  452.  
  453.           /* now get rid of possible terminating line feeds/cr's */
  454.           for (cp = err_buf; *cp && *cp != '\n' && *cp != '\r'; cp++) ;
  455.           *cp = 0;
  456.         }
  457.     }
  458.  
  459.       if (cli)
  460.         {
  461.           /* uniformly append ONE line feed */
  462.       strcat (err_buf, "\n");
  463.           syscall (SYS_write, 2, err_buf, strlen (err_buf));
  464.         }
  465.       else
  466.         ix_panic (err_buf);
  467.     }
  468.   else
  469.     syscall (SYS_write, 2, "^C\n", 3);
  470.  
  471.   exit2(W_EXITCODE(0, code));
  472.   /* not reached */
  473. }
  474.  
  475. /*
  476.  * This is used to awaken a possibly sleeping sigsuspend()
  477.  * and to force a context switch, if we send a signal to ourselves
  478.  */
  479. void
  480. setrun (struct Task *t)
  481. {
  482.   struct user *p = getuser(t);
  483.   u_int curr_disp;
  484.   u_int    sr;
  485.  
  486.   /* NOTE: the context switch is done to make sure sig_launch() is called as
  487.    *       soon as possible in the respective task. It's not nice if you can
  488.    *       return from a kill() to yourself, before the signal handler had a
  489.    *       chance to react accordingly to the signal..
  490.    */
  491.   asm volatile (" 
  492.     movel a5,a0
  493.     lea      L_get_sr,a5
  494.     movel 4:w,a6
  495.     jsr      a6@(-0x1e)
  496.     movel a1,%0
  497.     bra      L_skip
  498. L_get_sr:
  499.     movew sp@,a1    | get sr register from the calling function
  500.     rte
  501. L_skip:
  502.     movel a0,a5
  503.     " : "=g" (sr) : : "a0", "a1", "a6");
  504.  
  505.   /* Don't force context switch if:
  506.      o  running in Supervisor mode
  507.      o  we setrun() some other process
  508.      o  running under either Forbid() or Disable() */
  509.   if ((sr & 0x2000)
  510.       || SysBase->ThisTask != t
  511.       || p->p_stat == SSLEEP
  512.       || p->p_stat == SWAIT
  513.       || p->p_stat == SSTOP
  514.       || SysBase->TDNestCnt >= 0
  515.       || SysBase->IDNestCnt >= 0)
  516.     {
  517.       extern int select();
  518.  
  519.       /* make testing of p_stat and reaction atomic */
  520.       Forbid();
  521.  
  522.       if (p->p_stat == SWAIT)
  523.         Signal (t, SIGBREAKF_CTRL_C);
  524.       else if (p->p_stat == SSTOP)
  525.         {
  526.           p->p_stat = SRUN;
  527.       Signal (t, 1 << p->p_zombie_sig);
  528.         }
  529.       else if (p->p_wchan == (caddr_t) p)
  530.     {
  531.       KPRINTF (("setrun $%lx\n", p));
  532.           ix_wakeup ((u_int)p);
  533.         }
  534.       else if (p->p_wchan == (caddr_t) select)
  535.         Signal (t, 1<<p->u_sleep_sig);
  536.         
  537.       Permit();
  538.       return;
  539.     }
  540.   /* this quite brute-force method, but the only thing I could think of that
  541.    * really guarantees that there was a context switch.. */
  542.  
  543.   /* But I can think of something better: install a high-priority task when
  544.    * the library is opened. That task always Wait()s on signal 1 << 31. So
  545.    * when we want to make a context switch, we signal that task. Because of
  546.    * the high priority of that task, exec.library switches to that task.
  547.    * That task goes immediately back to Waiting for a signal, so
  548.    * exec.library will go back to another task.
  549.    *
  550.    * Just in case this task has also a high priority, we keep around the
  551.    * old method too. */
  552.   curr_disp = SysBase->DispCount;
  553.   Signal(ix.ix_task_switcher, 1 << 31);  /* signal the task switcher */
  554.   while (curr_disp == ((volatile struct ExecBase *)SysBase)->DispCount) ;
  555. }
  556.  
  557. /*
  558.  * Mapping from vector numbers into signals
  559.  */
  560. const static int hwtraptable[256] = {
  561.   SIGILL, /* Reset initial stack pointer */
  562.   SIGILL, /* Reset initial program counter */
  563.   SIGBUS, /* Bus Error */
  564.   SIGBUS, /* Address Error */
  565.   SIGILL, /* Illegal Instruction */
  566.   SIGFPE, /* Zero Divide */
  567.   SIGFPE, /* CHK, CHK2 Instruction */
  568.   SIGFPE, /* cpTRAPcc, TRAPcc, TRAPV Instruction */
  569.   SIGILL, /* Privilege Violation */
  570.   SIGTRAP,/* Trace */
  571.   SIGEMT, /* Line 1010 Emulator */
  572.   SIGEMT, /* Line 1111 Emulator */
  573.   SIGILL,
  574.   SIGILL, /* Coprocessor Protocol Violation */
  575.   SIGILL, /* Format Error */
  576.   SIGILL, /* Uninitialized Interrupt */
  577.   SIGILL, /* 16 */
  578.   SIGILL, /* 17 */
  579.   SIGILL, /* 18 */
  580.   SIGILL, /* 19 */        /* unimplemented, reserved */
  581.   SIGILL, /* 20 */
  582.   SIGILL, /* 21 */
  583.   SIGILL, /* 22 */
  584.   SIGILL, /* 23 */
  585.   SIGILL, /* spurious Interrupt */
  586.   SIGILL, /* Level 1 Interrupt Autovector */
  587.   SIGILL, /* Level 2 Interrupt Autovector */
  588.   SIGILL, /* Level 3 Interrupt Autovector */
  589.   SIGILL, /* Level 4 Interrupt Autovector */
  590.   SIGILL, /* Level 5 Interrupt Autovector */
  591.   SIGILL, /* Level 6 Interrupt Autovector */
  592.   SIGILL, /* Level 7 Interrupt Autovector */
  593.   SIGTRAP, /* Trap #0 (not available on Unix) */
  594.   SIGTRAP, /* Trap #1 */
  595.   SIGILL, /* Trap #2 */
  596.   SIGILL, /* Trap #3 */
  597.   SIGILL, /* Trap #4 */
  598.   SIGILL, /* Trap #5 */
  599.   SIGILL, /* Trap #6 */
  600.   SIGILL, /* Trap #7 */
  601.   SIGILL, /* Trap #8 */
  602.   SIGILL, /* Trap #9 */
  603.   SIGILL, /* Trap #10 */
  604.   SIGILL, /* Trap #11 */
  605.   SIGILL, /* Trap #12 */
  606.   SIGILL, /* Trap #13 */
  607.   SIGILL, /* Trap #14 */
  608.   SIGILL, /* Trap #15 (not available on Unix) */
  609.   SIGFPE, /* FPCP Branch or Set on Unordererd Condition */
  610.   SIGFPE, /* FPCP Inexact Result */
  611.   SIGFPE, /* FPCP Divide by Zero */
  612.   SIGFPE, /* FPCP Underflow */
  613.   SIGFPE, /* FPCP Operand Error */
  614.   SIGFPE, /* FPCP Overflow */
  615.   SIGFPE, /* FPCP Signaling NAN */
  616.   SIGILL,
  617.   SIGBUS, /* MMU Configuration Error */
  618.   SIGILL, /* MMU Illegal Operation (only 68851) */
  619.   SIGILL, /* MMU Privilege Violation (only 68851) */
  620.   /* rest undefined or free user-settable.. */
  621. };
  622.  
  623. /*
  624.  * handle traps handed over from the lowlevel trap handlers
  625.  */
  626. void
  627. trap (void)
  628. {
  629.   u_int            format;
  630.   void            *addr;
  631.   struct reg        *regs;
  632.   struct fpreg        *fpregs;
  633.   struct Task         *me         = SysBase->ThisTask;
  634.   /* precalculate struct user, so we don't have to go thru SysBase all the time */
  635.   struct user         *p         = getuser(me);
  636.   int             sig;
  637.   u_int            usp, orig_usp;
  638.   struct sigcontext     *sc;
  639.   u_int            ret_pc, ret_ssp;
  640.   extern long        vector_old_pc;
  641.   extern long        vector_nop;
  642.  
  643.   usp = orig_usp = get_usp () + 8;    /* skip argument parameters */
  644.   format = ((u_int *)usp)[0];
  645.   addr = (void *)((u_int *)usp)[1];
  646.   regs = (struct reg *)((u_int *)usp)[2];
  647.   fpregs = (struct fpreg *)((u_int *)usp)[3];
  648.  
  649.   ret_pc  = ((u_int *)usp)[-2];
  650.   ret_ssp = ((u_int *)usp)[-1];
  651.   
  652.   /* push a sigcontext that will get us back here if no other signals
  653.    * were produced */
  654.   usp -= sizeof (struct sigcontext);
  655.   sc = (struct sigcontext *) usp;
  656.   set_usp (usp);
  657.   sc->sc_onstack = p->u_onstack;
  658.   sc->sc_mask     = p->p_sigmask;
  659.   sc->sc_sp     = orig_usp;
  660.   sc->sc_fp     = regs->r_regs[13];
  661.   sc->sc_ap     = *(u_int *)&me->tc_Flags;
  662.   sc->sc_pc     = ret_pc;
  663.   sc->sc_ps     = get_sr() & ~0x8000;
  664.  
  665.   if (regs->r_pc == (void *)(&vector_nop) + 2)
  666.     {
  667.       regs->r_pc = (void *)vector_old_pc;
  668.       vector_old_pc = 0;
  669.     }
  670.   p->u_regs = regs;
  671.   p->u_fpregs = fpregs;
  672.   /* format contains the vector * 4, in the lower 12 bits */
  673.   sig = *(int *)((u_char *)hwtraptable + (format & 0x0fff));
  674.   
  675.   if (sig == SIGTRAP)
  676.     regs->r_sr &= ~0x8000;    /* turn off the trace flag */
  677.  
  678.   trapsignal (me, sig, format, addr);
  679.  
  680.   if ((sig = CURSIG(p)))
  681.     psig (p, sig);
  682.  
  683.   /* now try to optimize. We could always call sup_do_sigreturn here, but if no
  684.    * signals generated frames, we can just as well simply return, after having
  685.    * restored our usp */
  686.   if (usp == get_usp ())
  687.     {
  688.       set_usp (orig_usp);
  689.       return;
  690.     }
  691.   sup_do_sigreturn_ssp (ret_ssp);
  692. }
  693.  
  694. void resume_signal_check(void)
  695. {
  696.   int sig;
  697.  
  698.   if ((sig = issig(&u)))  /* always go through issig if we restart the process */
  699.     psig (&u, sig);
  700. }
  701.