home *** CD-ROM | disk | FTP | other *** search
/ The CDPD Public Domain Collection for CDTV 3 / CDPDIII.bin / pd / programming / gnuc / library / rcs / machdep.c,v < prev    next >
Encoding:
Text File  |  1992-08-09  |  18.9 KB  |  703 lines

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