home *** CD-ROM | disk | FTP | other *** search
- head 1.1;
- access;
- symbols
- version39-41:1.1;
- locks;
- comment @ * @;
-
-
- 1.1
- date 92.05.14.20.36.14; author mwild; state Exp;
- branches;
- next ;
-
-
- desc
- @trap handlers and glue code
- @
-
-
- 1.1
- log
- @Initial revision
- @
- text
- @/*
- * This file is part of ixemul.library for the Amiga.
- * Copyright (C) 1991, 1992 Markus M. Wild
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Id$
- *
- * $Log$
- */
-
- .globl _trap_00
- .globl _trap_20
- .globl _restore_00
- .globl _restore_20
- .globl _supervisor
- .globl _do_sigreturn
- .globl _sup00_do_sigreturn
- .globl _sup20_do_sigreturn
- .globl _sup00_do_sigreturn_ssp
- .globl _sup20_do_sigreturn_ssp
- .globl _launch_glue
- .globl _addupc
-
-
- #undef DEBUG
-
- |
- | ATTENTION:
- |
- | do_sigreturn() uses absolute offsets into struct user.
- | if you change struct user, be sure to check whether the current
- | offsets of p_sigmask and u_onstack are still valid !!!!
- |
-
-
- | This is the trap processing function for the mc68000.
- | Things are quite easy here, just save the general purpose registers
- | and the pc/sr combo, call trap(), then restore the previous
- | context and return
-
- _trap_00:
- movel a5,sp@@- | need a scratch register
- movel usp,a5 | get usp
- moveml d0-d7/a0-a6,a5@@-| store registers on usp
- movel sp@@+,a5@@(0x34) | insert the saved a5 into the saveset
- movel sp@@+,d2 | remember trapnumber
- movew sp@@+,a5@@- | copy SR
- movel sp@@+,a0 | remember and
- movel a0,a5@@- | copy offending PC
-
- |
- | pass return address and ssp-value on userstack
- | This happens for the same reason as we have a glue_launch entry.
- | trap cleans up these 8 bytes on the user stack itself
- movel sp,a5@@-
- movel #_restore_00,a5@@-
- movel a5,usp | and remember current value of usp (a5)
-
- | fine, now process this trap. This might (doesn't have to) push
- | additional frames. If not, we just return where the exception
- | took place (and probably will again...)
-
- movel a0,sp@@- | pass offending address (don't know more about it)
- addl d2,d2 | convert the passed trap number into a fake
- addl d2,d2 | 68020 frame format word
- movel d2,sp@@- | and pass it as argument
- jsr _trap | to the higher level C trap
- lea sp@@(8),sp | processor
-
- _restore_00:
- movel usp,a5 | get usp
- lea a5@@(0x42),a1 | skip over the now no longer needed frame
- movel a1,usp | -> 15 registers, one PC and one SR
-
- | set up the original supervisor stack frame
- movel a5@@+,sp@@- | PC
- movew a5@@+,sp@@- | SR
- moveml a5@@,d0-d7/a0-a6 | and the other cpu registers
- rte
-
-
-
- | This is the trap processor for the mc68020 and above, paired with
- | an fpu (don't *need* an fpu though).
- | What is done: start is same as with 68000, but then the complete
- | additional exception frame is saved on the usp, together with the
- | fpu state. Then trap() is called, and then the previous context
- | is restored (involves copying back the frame from the usp over to the ssp)
-
- _trap_20:
- movel a5,sp@@ | nuke the trap number, we use the frame format word
- movel usp,a5 | get usp
- moveml d0-d7/a0-a6,a5@@-| store registers on usp
- movel sp@@+,a5@@(0x34) | insert the saved a5 into the saveset
- movew sp@@+,a5@@- | copy SR
- movel sp@@+,d2 | remember and
- movel d2,a5@@- | copy (offending?) PC
-
- | find out more about the frame (according to the MC68030 user manual)
- clrl d1
- movew sp@@+,d1 | remember frame format word
- movew d1,d0
- andw #0xf000,d0
- beq Lfmt_S0 | S0
- cmpw #0x1000,d0
- beq Lfmt_S1 | S1 this (interrupt) frame shouldn't be here...
- cmpw #0x2000,d0
- beq Lfmt_S2 | CHK{2},cpTRAPcc,TRAPV,Trace,Div0,MMUcfg,cp post instr
- cmpw #0x9000,d0
- beq Lfmt_S9 | cp mid instr,main det prot viol,int during cp instr
- cmpw #0xa000,d0
- beq Lfmt_SA_SB | address or bus error, short and long frame
- cmpw #0xb000,d0
- bne Lfmt_S0 | ??? frame, this will probably not fully cleanup sp..
-
- Lfmt_SA_SB:
- | this part (upto Lbe10) inspired by locore.s in sys/hp300/ of BSD4.3-reno
- movew sp@@(2),d0 | grab SSW for fault processing
- btst #12,d0 | RB set?
- beq LbeX0 | no, test RC
- bset #14,d0 | yes, must set FB
- movew d0,sp@@(2) | for hardware too
- LbeX0:
- btst #13,d0 | RC set?
- beq LbeX1 | no, skip
- bset #15,d0 | yes, must set FC
- movew d0,sp@@(2) | for hardware too
- LbeX1:
- btst #8,d0 | data fault?
- beq Lbe0 | no, check for hard cases
- movel sp@@(8),d2 | fault address is as given in frame
- bra Lbe10 | thats it
- Lbe0:
- btst #12,d1 | long (type B) stack frame?
- bne Lbe4 | yes, go handle
- btst #14,d0 | no, can use saved PC. FB set?
- beq Lbe3 | no, try FC
- addql #4,d2 | yes, adjust address
- bra Lbe10 | done
- Lbe3:
- btst #15,d0 | FC set?
- beq Lbe10 | no, done
- addql #2,d2 | yes, adjust address
- bra Lbe10 | done
- Lbe4:
- movel sp@@(28),d2 | long format, use stage B address
- btst #15,d0 | FC set?
- beq Lbe10 | no, all done
- subql #2,d2 | yes, adjust address
- Lbe10:
-
- | now move the frame over to the usp (6/21 longwords remain)
-
- moveml sp@@+,d3-d7/a0 | may trash as many registers as I like, I saved
- moveml d3-d7/a0,a5@@- | them already ;-) First copy 6 longs
-
- btst #12,d1 | long (type B) stack frame?
- beq Lfmt_S0 | nope, done
-
- moveml sp@@+,d3-d7/a0-a2 | first copy 8 longs
- moveml d3-d7/a0-a2,a5@@-
- moveml sp@@+,d3-d7/a0-a1 | plus 7 gives 15, plus already stored 6 is 21
- moveml d3-d7/a0-a1,a5@@-
- bra Lfmt_S0 | finito
-
- Lfmt_S9:
- movel sp@@+,a5@@- | S9 is an S2 plus 4 internal (word length) registers
- movel sp@@+,a5@@- | so store those registers, and fall into S2
-
- Lfmt_S2:
- movel sp@@+,d2 | S2 contains the offending instruction address
- | and the frame format word
- movel d2,a5@@- | we have the offending instruction address here
-
- | fall into
-
- Lfmt_S0:
- Lfmt_S1:
- movew d1,a5@@- | and as the last thing store the frame format word
-
- |
- | now lets look at the fpu, if there is an fpu in the system
- |
-
- btst #4,(4)@@(0x129) | is AFB_68881 set in SysBase->AttnFlags ??
- beq Lno_fpu
-
- fsave a5@@- | dump the fpu state onto the usp
- moveb a5@@,d0 | and get the fpu state identifier
- beq Lno_fpu | null frame?
-
- clrl d0
- moveb a5@@(1),d0 | load state frame size
- bset #3,a5@@(d0) | set bit 27 of BIU
-
- fmovemx fp0-fp7,a5@@- | push the fpu data registers and
- fmoveml fpcr/fpsr/fpi,a5@@- | fpu control registers
-
- movew #-1,a5@@- | mark that there is fpu stuff on the stack
-
- Lno_fpu:
-
- |
- | pass return address and ssp-value on userstack
- | This happens for the same reason as we have a glue_launch entry.
- | trap cleans up these 8 bytes on the user stack itself
- movel sp,a5@@-
- movel #_restore_20,a5@@-
-
- movel a5,usp | set the new value of the usp
-
- | that's it, phew.. now process this frame, and perhaps throw some
- | frames on it as well to deal with the signal
-
- movel d2,sp@@- | pass offending PC
- movel d1,sp@@- | pass frame format word
- jsr _trap | do distribution in C ;-)
- lea sp@@(8),sp
-
- _restore_20:
- |
- | restore the saved stack frame from the usp, and copy the necessary
- | parts over to the ssp
- |
-
- movel usp,a5
-
- | first deal with fpu stuff, if there's an fpu
-
- btst #4,(4)@@(0x129) | is AFB_68881 set in SysBase->AttnFlags ??
- beq Lno_fpu2
-
- tstb a5@@
- beq Lrst_fpu_frame | there's only the null frame, go and restore it
-
- lea a5@@(2),a5 | skip fpu indicator
- fmoveml a5@@+,fpcr/fpsr/fpi | restore fpu control and
- fmovemx a5@@+,fp0-fp7 | fpu data registers
-
- Lrst_fpu_frame:
- frestore a5@@+ | and restore the internal fpu state
-
- Lno_fpu2:
- movew a5@@+,d1 | get frame format word
- movew d1,d0
- andw #0xf000,d0
- beq Lrfmt_S0 | S0
- cmpw #0x1000,d0
- beq Lrfmt_S1 | S1
- cmpw #0x2000,d0
- beq Lrfmt_S2 | S2
- cmpw #0x9000,d0
- beq Lrfmt_S9 | S9
- cmpw #0xa000,d0
- beq Lrfmt_SA | SA
- cmpw #0xb000,d0
- bne Lrfmt_S0 | ??? frame
-
- Lrfmt_SB:
- moveml a5@@+,d3-d7/a0-a2
- moveml d3-d7/a0-a2,sp@@-
- moveml a5@@+,d3-d7/a0-a1
- moveml d3-d7/a0-a1,sp@@- | copy 15 longs
-
- Lrfmt_SA:
- movel a5@@+,sp@@- | copy 3 longs
- movel a5@@+,sp@@-
- movel a5@@+,sp@@-
-
- Lrfmt_S9:
- movel a5@@+,sp@@- | copy 2 longs
- movel a5@@+,sp@@-
-
- Lrfmt_S2:
- movel a5@@+,sp@@- | copy 1 long
-
- Lrfmt_S1:
- Lrfmt_S0:
- movew d1,sp@@- | insert frame format word
- movel a5@@+,sp@@- | copy PC
- movew a5@@+,sp@@- | and SR
-
- lea a5@@(0x3c),a1 | skip the rest of the frame
- movel a1,usp | 0x3c -> 15 registers
-
- moveml a5@@,d0-d7/a0-a6 | restore the cpu registers
- rte | that's it (finally) ..
-
-
- |
- | jump to the given argument in supervisor mode
- | does NOT return
- |
-
- _supervisor:
- movel sp@@(4),a5 | where to go in supervisor
- movel sp@@(8),sp@@- | with this usp
- movel a6,sp@@-
- movel 4:w,a6
- jmp a6@@(-0x1e) | do it (Supervisor() system call)
-
-
- |
- | restore signal context
- | argument comes in usp
- |
-
- | mc68020 entry
- _sup20_do_sigreturn_ssp: | entry via jsr from supervisor mode
- movel sp@@(4),sp | set ssp
- _sup20_do_sigreturn:
- lea sp@@(-8),sp | make room for an exception frame
- movew #0x20,sp@@(6) | fake format word
- bra fromsup_sigreturn
-
- | mc68000 entry
- _sup00_do_sigreturn_ssp:
- movel sp@@(4),sp | set ssp
- _sup00_do_sigreturn:
- lea sp@@(-6),sp | make room for an exception frame
-
- fromsup_sigreturn:
- moveml d0/d1/a0/a1,sp@@-
-
- movel usp,a0 | get signal context
- bra resume_sigreturn
-
- | fall into _do_sigreturn
-
-
- | Supervisor() entry (already comes on exception frame)
- _do_sigreturn:
- | make the sigreturn() function preserve all registers
- moveml d0/d1/a0/a1,sp@@-
-
- movel usp,a0 | get signal context
- movel a0@@+,a6 | restore the trashed a6 register
- movel a0@@,a0
-
- resume_sigreturn:
-
- #if 0
- movel sp,a0@@-
- movel a0,sp
- pea dumpsc_msg
- jsr _kprintf
- movel sp@@(4),sp
- movel usp,a0
- #endif
-
- movel 4:w,a1 | SysBase
- movel a1,d1 | remember for later setting of sc_ap
- movel a1@@(0x114),a1 | ThisTask
- movel a1@@(0x2e),a1 | TrapData -> (struct user *)
-
- | ok, now a0:sc, a1:u
-
- | get those offsets in struct user with `print_user.c' !
- movel a0@@+,a1@@(0x11c) | u.u_onstack = sc->sc_onstack
- movel a0@@+,a1@@(0x134) | u.p_sigmask = sc->sc_mask
- movel a0@@+,a1 | usp = sc->sc_sp
- movel a1,usp
- movel a0@@+,a5 | fp = sc->sc_fp
-
-
- #if 0
- moveml d1/a0/a1,sp@@-
- movel a0@@,sp@@-
- pea before_foo
- jsr _kprintf
- lea sp@@(8),sp
- moveml sp@@+,d1/a0/a1
- #endif
-
- movel d1,a1 | get back SysBase
- movel a1@@(0x114),a1 | ThisTask
- movel a0@@,a1@@(0x0e) | store Flags,State,IDNestCnt,TDNestCnt
- movel d1,a1
- lea a0@@(2),a0 | skip unused part of sc_ap
- movew a0@@+,d1 | get IDNestCnt and TDNestCnt
- movew d1,a1@@(0x126) | store them in SysBase
- tstb a1@@(0x126)
- bmi Lenable
- Ldisabled:
- movew #0x4000,0xdff09a | disable interrupts
- bra Lint_twiddle
- Lenable:
- movew #0xc000,0xdff09a | enable interrupts
- Lint_twiddle:
-
- #if 0
- moveml d1/a0/a1,sp@@-
- pea after_foo
- jsr _kprintf
- lea sp@@(4),sp
- moveml sp@@+,d1/a0/a1
- #endif
-
- | set pc and sr in current exception frame
- movel a0@@+,sp@@(2+4*4) | set PC
- movew a0@@(2),sp@@(4*4) | and SR
-
- #ifdef DEBUG
- pea sp@@
- pea dumpframe_msg
- jsr _kprintf
- lea sp@@(8),sp
- #endif
-
- moveml sp@@+,d0/d1/a0/a1
- rte
-
- #ifdef DEBUG
- dumpsc_msg:
- .asciz "ssp = $%lx, onstack = %ld, mask = $%lx, sp = $%lx\nfp = $%lx, ap = $%lx, pc = $%lx, ps = $%lx\n"
- dumpframe_msg:
- .asciz "restore: ssp = $%lx, sr = $%x, pc = $%lx, fmt = $%x.\n"
- before_foo:
- .asciz "before foo ($%lx), "
- after_foo:
- .asciz "after foo.\n"
- .even
- #endif
-
-
- |
- | launch_glue is used to invoke the sig_launch handler. We have to care to
- | clean the supervisor stack, if we should call a signal handler from
- | the launch handler.
- | The bad thing is, that doing this right needs information on how
- | the tc_Launch entry is called from the OS. Thus I pass two parameters
- | on the user stack, the value of the `virgin' ssp and the value of
- | a4, which happens to contain the address of the context restore
- | function.
- | It is assumed, that tc_Launch is called via
- | ... jsr sub
- | ...
- | sub:jsr tc_Launch
- | Thus we have to backup the sp by two jsr's, which is 8.
-
- _launch_glue:
- movel 4:w,a0
- movel a0@@(0x114),a0 | tid = SysBase->ThisTask
- movel a0@@(0x36),a0 | usp isn't setup correctly, do it now from tc_SPReg
- movel sp,a0@@-
- addl #8,a0@@
- movel a4,a0@@-
- movel a0,usp
-
- jsr _sig_launch | sig_launch `(void *pc_ret, *ssp_ret)' (`' on usp)
-
- | sig_launch() already corrects the usp to pop those two arguments
- rts
-
-
-
- /*
- * update profiling information for the user
- * addupc(pc, &u.u_prof, ticks)
- */
- _addupc:
- movl a2,sp@@- | scratch register
- movl sp@@(12),a2 | get &u.u_prof
- movl sp@@(8),d0 | get user pc
- subl a2@@(8),d0 | pc -= pr->pr_off
- jlt Lauexit | less than 0, skip it
- movl a2@@(12),d1 | get pr->pr_scale
- lsrl #1,d0 | pc /= 2
- lsrl #1,d1 | scale /= 2
-
- | mulul d1,d0 | pc /= scale
- moveml d0/d1,sp@@-
- jbsr ___mulsi3
- lea sp@@(8),sp
-
- moveq #14,d1
- lsrl d1,d0 | pc >>= 14
- bclr #0,d0 | pc &= ~1
- cmpl a2@@(4),d0 | too big for buffer?
- jge Lauexit | yes, screw it
- addl a2@@,d0 | no, add base
-
- | movl d0,sp@@- | push address
- | jbsr _fusword | grab old value
- | movl sp@@+,a0 | grab address back
- | cmpl #-1,d0 | access ok
- | jeq Lauerror | no, skip out
-
- movel d0,a0
- movew a0@@,d0
-
- addw sp@@(18),d0 | add tick to current value
-
- movew d0,a0@@
-
- | movl d0,sp@@- | push value
- | movl a0,sp@@- | push address
- | jbsr _susword | write back new value
- | addql #8,sp | pop params
- | tstl d0 | fault?
- | jeq Lauexit | no, all done
- Lauerror:
- | clrl a2@@(12) | clear scale (turn off prof)
- Lauexit:
- movl sp@@+,a2 | restore scratch reg
- rts
- @
-