home *** CD-ROM | disk | FTP | other *** search
/ The CDPD Public Domain Collection for CDTV 3 / CDPDIII.bin / pd / programming / gnuc / library / rcs / trap.s,v < prev    next >
Encoding:
Text File  |  1992-07-04  |  13.6 KB  |  545 lines

  1. head    1.1;
  2. access;
  3. symbols
  4.     version39-41:1.1;
  5. locks;
  6. comment    @ *  @;
  7.  
  8.  
  9. 1.1
  10. date    92.05.14.20.36.14;    author mwild;    state Exp;
  11. branches;
  12. next    ;
  13.  
  14.  
  15. desc
  16. @trap handlers and glue code
  17. @
  18.  
  19.  
  20. 1.1
  21. log
  22. @Initial revision
  23. @
  24. text
  25. @/*
  26.  *  This file is part of ixemul.library for the Amiga.
  27.  *  Copyright (C) 1991, 1992  Markus M. Wild
  28.  *
  29.  *  This library is free software; you can redistribute it and/or
  30.  *  modify it under the terms of the GNU Library General Public
  31.  *  License as published by the Free Software Foundation; either
  32.  *  version 2 of the License, or (at your option) any later version.
  33.  *
  34.  *  This library is distributed in the hope that it will be useful,
  35.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  36.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  37.  *  Library General Public License for more details.
  38.  *
  39.  *  You should have received a copy of the GNU Library General Public
  40.  *  License along with this library; if not, write to the Free
  41.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  42.  *
  43.  *  $Id$
  44.  *
  45.  *  $Log$
  46.  */
  47.  
  48.     .globl    _trap_00
  49.     .globl    _trap_20
  50.     .globl    _restore_00
  51.     .globl    _restore_20
  52.     .globl    _supervisor
  53.     .globl    _do_sigreturn
  54.     .globl    _sup00_do_sigreturn
  55.     .globl    _sup20_do_sigreturn
  56.     .globl    _sup00_do_sigreturn_ssp
  57.     .globl    _sup20_do_sigreturn_ssp
  58.     .globl    _launch_glue
  59.     .globl    _addupc
  60.  
  61.  
  62. #undef DEBUG
  63.  
  64.     |
  65.     | ATTENTION:
  66.     | 
  67.     | do_sigreturn() uses absolute offsets into struct user.
  68.     | if you change struct user, be sure to check whether the current
  69.     | offsets of p_sigmask and u_onstack are still valid !!!!
  70.     |
  71.  
  72.  
  73.     | This is the trap processing function for the mc68000.
  74.     | Things are quite easy here, just save the general purpose registers
  75.     | and the pc/sr combo, call trap(), then restore the previous
  76.     | context and return
  77.  
  78. _trap_00:
  79.     movel    a5,sp@@-        | need a scratch register
  80.     movel    usp,a5        | get usp
  81.     moveml    d0-d7/a0-a6,a5@@-| store registers on usp
  82.     movel    sp@@+,a5@@(0x34)    | insert the saved a5 into the saveset
  83.     movel    sp@@+,d2        | remember trapnumber
  84.     movew    sp@@+,a5@@-    | copy SR
  85.     movel    sp@@+,a0        | remember and
  86.     movel    a0,a5@@-        | copy offending PC
  87.  
  88.     |
  89.     | pass return address and ssp-value on userstack
  90.     | This happens for the same reason as we have a glue_launch entry.
  91.     | trap cleans up these 8 bytes on the user stack itself
  92.     movel    sp,a5@@-
  93.     movel    #_restore_00,a5@@-
  94.     movel    a5,usp        | and remember current value of usp (a5)
  95.  
  96.     | fine, now process this trap. This might (doesn't have to) push
  97.     | additional frames. If not, we just return where the exception 
  98.     | took place (and probably will again...)
  99.  
  100.     movel    a0,sp@@-        | pass offending address (don't know more about it)
  101.     addl    d2,d2        | convert the passed trap number into a fake
  102.     addl    d2,d2        | 68020 frame format word
  103.     movel    d2,sp@@-        | and pass it as argument
  104.     jsr    _trap        | to the higher level C trap 
  105.     lea    sp@@(8),sp    | processor
  106.  
  107. _restore_00:
  108.     movel    usp,a5        | get usp
  109.     lea    a5@@(0x42),a1    | skip over the now no longer needed frame
  110.     movel    a1,usp        | -> 15 registers, one PC and one SR
  111.     
  112.     | set up the original supervisor stack frame
  113.     movel    a5@@+,sp@@-    | PC
  114.     movew    a5@@+,sp@@-    | SR
  115.     moveml    a5@@,d0-d7/a0-a6    | and the other cpu registers
  116.     rte
  117.  
  118.  
  119.  
  120.     | This is the trap processor for the mc68020 and above, paired with
  121.     | an fpu (don't *need* an fpu though).
  122.     | What is done: start is same as with 68000, but then the complete
  123.     | additional exception frame is saved on the usp, together with the
  124.     | fpu state. Then trap() is called, and then the previous context
  125.     | is restored (involves copying back the frame from the usp over to the ssp)
  126.  
  127. _trap_20:
  128.     movel    a5,sp@@        | nuke the trap number, we use the frame format word
  129.     movel    usp,a5        | get usp
  130.     moveml    d0-d7/a0-a6,a5@@-| store registers on usp
  131.     movel    sp@@+,a5@@(0x34)    | insert the saved a5 into the saveset
  132.     movew    sp@@+,a5@@-    | copy SR
  133.     movel    sp@@+,d2        | remember and
  134.     movel    d2,a5@@-        | copy (offending?) PC
  135.  
  136.     | find out more about the frame (according to the MC68030 user manual)
  137.     clrl    d1
  138.     movew    sp@@+,d1        | remember frame format word
  139.     movew    d1,d0
  140.     andw    #0xf000,d0
  141.     beq    Lfmt_S0        | S0
  142.     cmpw    #0x1000,d0
  143.     beq    Lfmt_S1        | S1 this (interrupt) frame shouldn't be here...
  144.     cmpw    #0x2000,d0
  145.     beq    Lfmt_S2        | CHK{2},cpTRAPcc,TRAPV,Trace,Div0,MMUcfg,cp post instr
  146.     cmpw    #0x9000,d0
  147.     beq    Lfmt_S9        | cp mid instr,main det prot viol,int during cp instr
  148.     cmpw    #0xa000,d0
  149.     beq    Lfmt_SA_SB    | address or bus error, short and long frame
  150.     cmpw    #0xb000,d0
  151.     bne    Lfmt_S0        | ??? frame, this will probably not fully cleanup sp..
  152.  
  153. Lfmt_SA_SB:
  154.     | this part (upto Lbe10) inspired by locore.s in sys/hp300/ of BSD4.3-reno
  155.     movew    sp@@(2),d0    | grab SSW for fault processing
  156.     btst    #12,d0        | RB set?
  157.     beq    LbeX0        | no, test RC
  158.     bset    #14,d0        | yes, must set FB
  159.     movew    d0,sp@@(2)    | for hardware too
  160. LbeX0:
  161.     btst    #13,d0        | RC set?
  162.     beq    LbeX1        | no, skip
  163.     bset    #15,d0        | yes, must set FC
  164.     movew    d0,sp@@(2)    | for hardware too
  165. LbeX1:
  166.     btst    #8,d0        | data fault?
  167.     beq    Lbe0        | no, check for hard cases
  168.     movel    sp@@(8),d2    | fault address is as given in frame
  169.     bra    Lbe10        | thats it
  170. Lbe0:
  171.     btst    #12,d1        | long (type B) stack frame?
  172.     bne    Lbe4        | yes, go handle
  173.     btst    #14,d0        | no, can use saved PC. FB set?
  174.     beq    Lbe3        | no, try FC
  175.     addql    #4,d2        | yes, adjust address
  176.     bra    Lbe10        | done
  177. Lbe3:
  178.     btst    #15,d0        | FC set?
  179.     beq    Lbe10        | no, done
  180.     addql    #2,d2        | yes, adjust address
  181.     bra    Lbe10        | done
  182. Lbe4:
  183.     movel    sp@@(28),d2    | long format, use stage B address
  184.     btst    #15,d0        | FC set?
  185.     beq    Lbe10        | no, all done
  186.     subql    #2,d2        | yes, adjust address
  187. Lbe10:
  188.  
  189.     | now move the frame over to the usp (6/21 longwords remain)
  190.     
  191.     moveml    sp@@+,d3-d7/a0    | may trash as many registers as I like, I saved
  192.     moveml    d3-d7/a0,a5@@-    | them already ;-) First copy 6 longs
  193.  
  194.     btst    #12,d1        | long (type B) stack frame?
  195.     beq    Lfmt_S0        | nope, done
  196.  
  197.     moveml    sp@@+,d3-d7/a0-a2 | first copy 8 longs
  198.     moveml    d3-d7/a0-a2,a5@@-
  199.     moveml    sp@@+,d3-d7/a0-a1 | plus 7 gives 15, plus already stored 6 is 21
  200.     moveml    d3-d7/a0-a1,a5@@-
  201.     bra    Lfmt_S0        | finito
  202.  
  203. Lfmt_S9:
  204.     movel    sp@@+,a5@@-    | S9 is an S2 plus 4 internal (word length) registers
  205.     movel    sp@@+,a5@@-    | so store those registers, and fall into S2
  206.  
  207. Lfmt_S2:
  208.     movel    sp@@+,d2        | S2 contains the offending instruction address
  209.                 | and the frame format word
  210.     movel    d2,a5@@-        | we have the offending instruction address here
  211.  
  212.     | fall into
  213.  
  214. Lfmt_S0:
  215. Lfmt_S1:
  216.     movew    d1,a5@@-        | and as the last thing store the frame format word
  217.  
  218.     |
  219.     | now lets look at the fpu, if there is an fpu in the system
  220.     |
  221.     
  222.     btst    #4,(4)@@(0x129)    | is AFB_68881 set in SysBase->AttnFlags ??
  223.     beq    Lno_fpu
  224.     
  225.     fsave    a5@@-        | dump the fpu state onto the usp
  226.     moveb    a5@@,d0        | and get the fpu state identifier
  227.     beq    Lno_fpu        | null frame?
  228.  
  229.     clrl    d0
  230.     moveb    a5@@(1),d0    | load state frame size
  231.     bset    #3,a5@@(d0)    | set bit 27 of BIU
  232.  
  233.     fmovemx    fp0-fp7,a5@@-        | push the fpu data registers and
  234.     fmoveml    fpcr/fpsr/fpi,a5@@-    | fpu control registers
  235.  
  236.     movew    #-1,a5@@-    | mark that there is fpu stuff on the stack
  237.  
  238. Lno_fpu:
  239.  
  240.     |
  241.     | pass return address and ssp-value on userstack
  242.     | This happens for the same reason as we have a glue_launch entry.
  243.     | trap cleans up these 8 bytes on the user stack itself
  244.     movel    sp,a5@@-
  245.     movel    #_restore_20,a5@@-
  246.  
  247.     movel    a5,usp        | set the new value of the usp
  248.  
  249.     | that's it, phew.. now process this frame, and perhaps throw some
  250.     | frames on it as well to deal with the signal
  251.     
  252.     movel    d2,sp@@-        | pass offending PC
  253.     movel    d1,sp@@-        | pass frame format word
  254.     jsr    _trap        | do distribution in C ;-)
  255.     lea    sp@@(8),sp
  256.  
  257. _restore_20:
  258.     |
  259.     | restore the saved stack frame from the usp, and copy the necessary
  260.     | parts over to the ssp
  261.     |
  262.  
  263.     movel    usp,a5
  264.     
  265.     | first deal with fpu stuff, if there's an fpu
  266.  
  267.     btst    #4,(4)@@(0x129)    | is AFB_68881 set in SysBase->AttnFlags ??
  268.     beq    Lno_fpu2
  269.  
  270.     tstb    a5@@
  271.     beq    Lrst_fpu_frame    | there's only the null frame, go and restore it
  272.  
  273.     lea    a5@@(2),a5    | skip fpu indicator
  274.     fmoveml    a5@@+,fpcr/fpsr/fpi    | restore fpu control and
  275.     fmovemx    a5@@+,fp0-fp7        | fpu data registers
  276.     
  277. Lrst_fpu_frame:
  278.     frestore a5@@+        | and restore the internal fpu state
  279.  
  280. Lno_fpu2:
  281.     movew    a5@@+,d1        | get frame format word
  282.     movew    d1,d0
  283.     andw    #0xf000,d0
  284.     beq    Lrfmt_S0    | S0
  285.     cmpw    #0x1000,d0
  286.     beq    Lrfmt_S1    | S1
  287.     cmpw    #0x2000,d0
  288.     beq    Lrfmt_S2    | S2
  289.     cmpw    #0x9000,d0
  290.     beq    Lrfmt_S9    | S9
  291.     cmpw    #0xa000,d0
  292.     beq    Lrfmt_SA    | SA
  293.     cmpw    #0xb000,d0
  294.     bne    Lrfmt_S0    | ??? frame
  295.  
  296. Lrfmt_SB:
  297.     moveml    a5@@+,d3-d7/a0-a2
  298.     moveml    d3-d7/a0-a2,sp@@-
  299.     moveml    a5@@+,d3-d7/a0-a1
  300.     moveml    d3-d7/a0-a1,sp@@- | copy 15 longs
  301.  
  302. Lrfmt_SA:
  303.     movel    a5@@+,sp@@-    | copy  3 longs
  304.     movel    a5@@+,sp@@-
  305.     movel    a5@@+,sp@@-
  306.     
  307. Lrfmt_S9:
  308.     movel    a5@@+,sp@@-    | copy  2 longs
  309.     movel    a5@@+,sp@@-
  310.  
  311. Lrfmt_S2:
  312.     movel    a5@@+,sp@@-    | copy  1 long
  313.  
  314. Lrfmt_S1:
  315. Lrfmt_S0:
  316.     movew    d1,sp@@-        | insert frame format word
  317.     movel    a5@@+,sp@@-    | copy PC
  318.     movew    a5@@+,sp@@-    | and SR
  319.     
  320.     lea    a5@@(0x3c),a1    | skip the rest of the frame
  321.     movel    a1,usp        | 0x3c -> 15 registers
  322.     
  323.     moveml    a5@@,d0-d7/a0-a6    | restore the cpu registers
  324.     rte            | that's it (finally) .. 
  325.  
  326.  
  327.     |
  328.     | jump to the given argument in supervisor mode
  329.     | does NOT return
  330.     |
  331.  
  332. _supervisor:
  333.     movel    sp@@(4),a5    | where to go in supervisor
  334.     movel    sp@@(8),sp@@-    | with this usp
  335.     movel    a6,sp@@-
  336.     movel    4:w,a6
  337.     jmp    a6@@(-0x1e)    | do it (Supervisor() system call)
  338.  
  339.  
  340.     |
  341.     | restore signal context
  342.     | argument comes in usp
  343.     |
  344.  
  345.     | mc68020 entry
  346. _sup20_do_sigreturn_ssp:    | entry via jsr from supervisor mode
  347.     movel    sp@@(4),sp    | set ssp
  348. _sup20_do_sigreturn:
  349.     lea    sp@@(-8),sp    | make room for an exception frame
  350.     movew    #0x20,sp@@(6)    | fake format word
  351.     bra    fromsup_sigreturn
  352.  
  353.     | mc68000 entry
  354. _sup00_do_sigreturn_ssp:
  355.     movel    sp@@(4),sp    | set ssp
  356. _sup00_do_sigreturn:
  357.     lea    sp@@(-6),sp    | make room for an exception frame
  358.  
  359. fromsup_sigreturn:
  360.     moveml    d0/d1/a0/a1,sp@@-
  361.  
  362.     movel    usp,a0        | get signal context
  363.     bra    resume_sigreturn
  364.  
  365.     | fall into _do_sigreturn
  366.  
  367.  
  368.     | Supervisor() entry (already comes on exception frame)
  369. _do_sigreturn:
  370.     | make the sigreturn() function preserve all registers
  371.     moveml    d0/d1/a0/a1,sp@@-
  372.  
  373.     movel    usp,a0        | get signal context
  374.     movel    a0@@+,a6        | restore the trashed a6 register
  375.     movel    a0@@,a0
  376.  
  377. resume_sigreturn:
  378.  
  379. #if 0
  380.     movel    sp,a0@@-
  381.     movel    a0,sp
  382.     pea    dumpsc_msg
  383.     jsr    _kprintf
  384.     movel    sp@@(4),sp
  385.     movel    usp,a0
  386. #endif
  387.  
  388.     movel    4:w,a1        | SysBase
  389.     movel    a1,d1        | remember for later setting of sc_ap
  390.     movel    a1@@(0x114),a1    | ThisTask
  391.     movel    a1@@(0x2e),a1    | TrapData -> (struct user *)
  392.     
  393.     | ok, now a0:sc, a1:u
  394.  
  395.     | get those offsets in struct user with `print_user.c' !
  396.     movel    a0@@+,a1@@(0x11c)    | u.u_onstack = sc->sc_onstack
  397.     movel    a0@@+,a1@@(0x134)    | u.p_sigmask = sc->sc_mask
  398.     movel    a0@@+,a1        | usp = sc->sc_sp
  399.     movel    a1,usp
  400.     movel    a0@@+,a5        | fp  = sc->sc_fp
  401.  
  402.  
  403. #if 0
  404.     moveml    d1/a0/a1,sp@@-
  405.     movel    a0@@,sp@@-
  406.     pea    before_foo
  407.     jsr    _kprintf
  408.     lea    sp@@(8),sp
  409.     moveml    sp@@+,d1/a0/a1
  410. #endif
  411.  
  412.     movel    d1,a1        | get back SysBase
  413.     movel    a1@@(0x114),a1    | ThisTask
  414.     movel    a0@@,a1@@(0x0e)    | store Flags,State,IDNestCnt,TDNestCnt
  415.     movel    d1,a1
  416.     lea    a0@@(2),a0    | skip unused part of sc_ap
  417.     movew    a0@@+,d1        | get IDNestCnt and TDNestCnt
  418.     movew    d1,a1@@(0x126)    | store them in SysBase
  419.     tstb    a1@@(0x126)
  420.     bmi    Lenable
  421. Ldisabled:
  422.     movew    #0x4000,0xdff09a    | disable interrupts
  423.     bra    Lint_twiddle
  424. Lenable:
  425.     movew    #0xc000,0xdff09a    | enable interrupts
  426. Lint_twiddle:
  427.  
  428. #if 0
  429.     moveml    d1/a0/a1,sp@@-
  430.     pea    after_foo
  431.     jsr    _kprintf
  432.     lea    sp@@(4),sp
  433.     moveml    sp@@+,d1/a0/a1
  434. #endif
  435.  
  436.     | set pc and sr in current exception frame
  437.     movel    a0@@+,sp@@(2+4*4)    | set PC
  438.     movew    a0@@(2),sp@@(4*4)    | and SR
  439.  
  440. #ifdef DEBUG
  441.     pea    sp@@
  442.     pea    dumpframe_msg
  443.     jsr    _kprintf
  444.     lea    sp@@(8),sp
  445. #endif
  446.  
  447.     moveml    sp@@+,d0/d1/a0/a1
  448.     rte
  449.  
  450. #ifdef DEBUG
  451. dumpsc_msg:
  452.     .asciz    "ssp = $%lx, onstack = %ld, mask = $%lx, sp = $%lx\nfp = $%lx, ap = $%lx, pc = $%lx, ps = $%lx\n"
  453. dumpframe_msg:
  454.     .asciz    "restore: ssp = $%lx, sr = $%x, pc = $%lx, fmt = $%x.\n"
  455. before_foo:
  456.     .asciz    "before foo ($%lx), "
  457. after_foo:
  458.     .asciz    "after foo.\n"
  459.     .even
  460. #endif
  461.  
  462.  
  463.     |
  464.     | launch_glue is used to invoke the sig_launch handler. We have to care to
  465.     | clean the supervisor stack, if we should call a signal handler from
  466.     | the launch handler.
  467.     | The bad thing is, that doing this right needs information on how 
  468.     | the tc_Launch entry is called from the OS. Thus I pass two parameters
  469.     | on the user stack, the value of the `virgin' ssp and the value of
  470.     | a4, which happens to contain the address of the context restore
  471.     | function.
  472.     | It is assumed, that tc_Launch is called via 
  473.     | ... jsr sub
  474.     | ...
  475.     | sub:jsr tc_Launch
  476.     | Thus we have to backup the sp by two jsr's, which is 8.
  477.  
  478. _launch_glue:
  479.     movel    4:w,a0
  480.     movel    a0@@(0x114),a0    | tid = SysBase->ThisTask
  481.     movel    a0@@(0x36),a0    | usp isn't setup correctly, do it now from tc_SPReg
  482.     movel    sp,a0@@-
  483.     addl    #8,a0@@
  484.     movel    a4,a0@@-
  485.     movel    a0,usp
  486.     
  487.     jsr    _sig_launch    | sig_launch `(void *pc_ret, *ssp_ret)' (`' on usp)
  488.  
  489.     | sig_launch() already corrects the usp to pop those two arguments
  490.     rts
  491.  
  492.  
  493.  
  494. /*
  495.  * update profiling information for the user
  496.  * addupc(pc, &u.u_prof, ticks)
  497.  */
  498. _addupc:
  499.     movl    a2,sp@@-            | scratch register
  500.     movl    sp@@(12),a2        | get &u.u_prof
  501.     movl    sp@@(8),d0        | get user pc
  502.     subl    a2@@(8),d0        | pc -= pr->pr_off
  503.     jlt    Lauexit            | less than 0, skip it
  504.     movl    a2@@(12),d1        | get pr->pr_scale
  505.     lsrl    #1,d0            | pc /= 2
  506.     lsrl    #1,d1            | scale /= 2
  507.  
  508.     | mulul    d1,d0            | pc /= scale
  509.     moveml    d0/d1,sp@@-
  510.     jbsr    ___mulsi3
  511.     lea    sp@@(8),sp
  512.  
  513.     moveq    #14,d1
  514.     lsrl    d1,d0            | pc >>= 14
  515.     bclr    #0,d0            | pc &= ~1
  516.     cmpl    a2@@(4),d0        | too big for buffer?
  517.     jge    Lauexit            | yes, screw it
  518.     addl    a2@@,d0            | no, add base
  519.  
  520.     | movl    d0,sp@@-            | push address
  521.     | jbsr    _fusword        | grab old value
  522.     | movl    sp@@+,a0            | grab address back
  523.     | cmpl    #-1,d0            | access ok
  524.     | jeq    Lauerror        | no, skip out
  525.  
  526.     movel    d0,a0
  527.     movew    a0@@,d0
  528.  
  529.     addw    sp@@(18),d0        | add tick to current value
  530.  
  531.     movew    d0,a0@@
  532.  
  533.     | movl    d0,sp@@-            | push value
  534.     | movl    a0,sp@@-            | push address
  535.     | jbsr    _susword        | write back new value
  536.     | addql    #8,sp            | pop params
  537.     | tstl    d0            | fault?
  538.     | jeq    Lauexit            | no, all done
  539. Lauerror:
  540.     | clrl    a2@@(12)            | clear scale (turn off prof)
  541. Lauexit:
  542.     movl    sp@@+,a2            | restore scratch reg
  543.     rts
  544. @
  545.