home *** CD-ROM | disk | FTP | other *** search
/ Atari FTP / ATARI_FTP_0693.zip / ATARI_FTP_0693 / Mint / mint104s.zoo / mint.src / context.spp < prev    next >
Text File  |  1993-03-08  |  11KB  |  312 lines

  1. ;
  2. ; Copyright 1992 Eric R. Smith
  3. ; Copyright 1992 Atari Corporation
  4. ; All rights reserved.
  5.  
  6. %include "magic.i"
  7. ;
  8. ; routines for saving/restoring user contexts
  9. ;
  10. ; long build_context(struct context *sav, short fmt):
  11. ;    Called from an interrupt handler (such as the trap #1 routine
  12. ;    for system calls) saves the context of the interrupted
  13. ;    routine. Assumes that no user registers have been changed
  14. ;    since the interrupt, and that the PC and status register
  15. ;    are still on the stack. Returns the stack pointer being used
  16. ;    at the time of the interrupt **in register a1**.
  17. ;    The fmt parameter is used on the 68000 to communicate the exception
  18. ;    vector number; on >=68010 we use the vector offset from the frame.
  19. ;
  20. ; long save_context(struct context *sav):
  21. ;    Saves the context of the calling routine in the area pointed
  22. ;    to by sav. Save_context always returns 0 when initially called;
  23. ;    this is so processes can (by suitably manipulating the
  24. ;    saved registers) tell when the return from save_context is
  25. ;    actually caused by restoring the context, e.g.:
  26. ;        if (save_context(sav) == 0) {        <<-- L1
  27. ;            /* do some stuff */
  28. ;            sav.regs[D0] = 1;    /* for restore context */
  29. ;            restore_context(sav);    /* goes back to L1 */
  30. ;        }
  31. ;        else /* this is the second time through */
  32. ;
  33. ; void restore_context(struct context *sav):
  34. ;    Restores a context previously saved by build_context or save_context.
  35. ;    Since the program counter is part of the context, this function
  36. ;    will never return (it's like longjmp()). NOTE: this function should
  37. ;    be used only to change contexts _within_ the same program, since
  38. ;    it does NOT flush the ATC. See change_context
  39. ;
  40. ; void change_context(struct context *sav):
  41. ;    Restores a context previously saved by build_context or save_context
  42. ;    for a different process. Unlike restore_context, this one *does*
  43. ;    flush the ATC.
  44.  
  45.     TEXT
  46.     
  47.     XDEF    _build_context
  48.     XDEF     _save_context
  49.     XDEF    _restore_context
  50.     XDEF    _change_context
  51.     XDEF    _set_mmu
  52.  
  53.     XREF    _fpu
  54.     XREF    _framesizes
  55.     XREF    _new_trace    ; from intr.s
  56.     XREF    _no_mem_prot    
  57. ;
  58. ; set_mmu(crp,tc): called once, the first time a page table is built, to 
  59. ; switch away from the MMU setup that came from the ROM and into the setup 
  60. ; that we just built.  The CRP is actually on the stack, and it's 8 bytes.
  61. ; The TC is four bytes at sp@(0xc).  "Nulls" is here because we need to
  62. ; shove zeros into a few places.
  63. ;
  64. ; nulltc is in the data segment because otherwise GAS assembles PC-relative
  65. ; and that's not legal on 68030.
  66. ;
  67.     DATA
  68. nulltc:    dc.l    0
  69.  
  70.     TEXT
  71. _set_mmu:
  72.     pmove    nulltc,tc        ; turn off mmu
  73.     dc.l    $f0390800,nulltc    ; pmove nulltc,tt0
  74.     dc.l    $f0390c00,nulltc    ; pmove nulltc,tt1
  75.     pmove    4(sp),crp        ; caution: crp is 8 bytes
  76.     pmove    $c(sp),tc
  77.     rts
  78.  
  79. _build_context:
  80.     move.l    a0,-(sp)    ; save a0; we'll use it for scratch
  81.     move.l    8(sp),a0    ; get address of save area
  82.  
  83.     tst.w    _no_mem_prot    ; is there memory protection?
  84.     bne.s    noprot1
  85.     pmove    crp,C_CRP(a0)    ; save CRP from MMU
  86.     pmove    tc,C_TC(a0)    ; save TC from MMU
  87. noprot1:
  88.     movem.l    d0-d7/a0-a6,(a0)    ; save registers D0-D7/A0-A6
  89.     clr.b    C_PTRACE(a0)    ; no pending traces, thanks!
  90.     lea    12(sp),a1    ; start of the interesting stack area
  91.     move.w    (a1)+,d0    ; 68000 fake frame format
  92.  
  93. %ifndef ONLY030
  94.     move.w    ($59e).w,d7    ; get process frame flag
  95.     bne.s    nojunk        ; we have some junk on the stack
  96.     move.w    d0,C_SFMT(a0)    ; save fake frame format
  97.     cmp.w    #$8,d0        ; if bus error
  98.     beq.s    group0
  99.     cmp.w    #$c,d0        ; or address error
  100.     bne.s    nojunk
  101. group0:    move.l    (a1)+,C_INTERNAL(a0)    ; stash it in the internal area
  102.     move.l    (a1)+,C_INTERNAL+4(a0)    ; if a debugger's interested
  103. nojunk:
  104. %endif
  105.     move.w    (a1)+,d0    ; get SR of context
  106.     move.w    d0,C_SR(a0)    ; save it
  107.     move.l    (a1)+,C_PC(a0)    ; save PC of context
  108. %ifndef ONLY030
  109.     tst.w    d7        ; test longframe (AKP)
  110.     beq.s    short1        ; short
  111. %endif
  112.     tst.w    _fpu        ; is there a true FPU in the system
  113.     beq.s    nofpu
  114.     fsave    C_FSTATE(a0)        ; save internal state frame
  115.     tst.b    C_FSTATE(a0)        ; if NULL frame then the FPU is not in use
  116.     beq.s    nofpu        ; skip programmer's model save
  117.     fmovem.x    fp0-fp7,C_FREGS(a0)        ; save data registers
  118.     fmovem.l    fpcr/fpsr/fpiar,C_FCTRL(a0)    ; and control registers
  119. nofpu:
  120.     lea    C_SFMT(a0),a2
  121.     move.w    (a1)+,d1    ; fetch frame format word
  122.     move.w    d1,(a2)+    ; and stash it away for later
  123.     lsr.w    #8,d1        ; isolate the frame format identifier
  124.     lsr.w    #4,d1
  125.     lea    _framesizes,a3
  126.     move.b    0(a3,d1.w),d1
  127.     bra.s    bcover
  128. bcint:    move.w    (a1)+,(a2)+    ; copy CPU internal state
  129. bcover:    dbf    d1,bcint
  130. short1:
  131.     move.l    a1,C_SSP(a0)    ; a1 now points above the state frame
  132.     move.l    usp,a1        ; save user stack pointer
  133.     move.l    a1,C_USP(a0)
  134.     btst    #13,d0        ; check for supervisor mode
  135.     beq.s    L_CONT1        ; user mode; we already have stack in a1
  136. L_SUPER1:
  137. ; moving from the save state buffer 
  138. ; means not testing longframe again. (AKP)
  139.     move.l    C_SSP(a0),a1    ; was using super stack pointer before interrupt
  140.                 ; 
  141. L_CONT1:
  142.     move.l    ($408).w,C_TERM(a0) ; save GEMDOS terminate vector
  143.     move.l    (sp)+,C_A0(a0)    ; save old register a0
  144.     rts
  145.  
  146.  
  147. _save_context:
  148.     move.l    a0,-(sp)    ; save a0
  149.     move.l    8(sp),a0    ; get address of context save area
  150.  
  151.     tst.w    _no_mem_prot
  152.     bne.s    noprot2
  153.     pmove    crp,C_CRP(a0)    ; save the CRP from the MMU
  154.     pmove    tc,C_TC(a0)    ; save the TC from the MMU
  155. noprot2:
  156.  
  157. ; if running with a true coprocessor we need to save the FPU state
  158.     tst.w    _fpu        ; is there a true FPU in the system
  159.     beq.s    nofpu2
  160.     fsave    C_FSTATE(a0)        ; save internal state frame
  161.     tst.b    C_FSTATE(a0)        ; if NULL frame then the FPU is not in use
  162.     beq.s    nofpu2        ; skip programmer's model save
  163.     fmovem.x    fp0-fp7,C_FREGS(a0)        ; save data registers
  164.     fmovem.l    fpcr/fpsr/fpiar,C_FCTRL(a0)    ; and control registers
  165. nofpu2:
  166. ; note: I am somewhat unsure of this assumption, viz that save_context
  167. ; can never be called in a situation where a co-processor
  168. ; mid-instruction stack frame would be required. I suspect this is a
  169. ; valid assumption, in which case the above FPU code is redundant, the
  170. ; next line is not however!
  171.  
  172.     clr.w    C_SFMT(a0)        ; mark as a 4 word stack frame
  173.     clr.b    C_PTRACE(a0)        ; no pending traces, thanks!
  174.  
  175.     movem.l    d0-d7/a0-a6,(a0)    ; save D0-D7/A0-A6
  176.     lea    8(sp),a1
  177.     move.l    a1,C_SSP(a0)    ; save supervisor stack pointer
  178.                 ; note that it should be pointing above the PC
  179.     move.l    -4(a1),C_PC(a0)    ; save PC
  180.     move.l    usp,a1
  181.     move.l    a1,C_USP(a0)    ; save user stack pointer
  182.     move.w    sr,d0
  183.     move.w    d0,C_SR(a0)    ; save status register
  184.     move.l    ($408).w,C_TERM(a0)    ; save GEMDOS terminate vector
  185.     move.l    (sp)+,C_A0(a0)    ; save old a0
  186.     moveq.l    #0,d0        ; return 0
  187.     rts
  188.  
  189. _restore_context:
  190.     ori.w    #$0700,sr    ; mask interrupts
  191.     move.l    4(sp),a0    ; address of context save area
  192.  
  193. ; Switch stacks now - starting now ssp is in the memory space of
  194. ; the process we're switching to. Thus, we can change memory context
  195. ; to there.
  196.  
  197.     move.l    C_SSP(a0),sp    ; supervisor stack pointer
  198.     move.l    C_USP(a0),a1
  199.     move.l    a1,usp        ; set user stack pointer
  200.     move.l    C_TERM(a0),($408).w    ; restore GEMDOS terminate vector
  201.  
  202. ; Set memory context now: actually, this isn't necessary, since
  203. ; we're coming back to a context in the same process as is running
  204. ; now.
  205. ;    tst.w    _no_mem_prot
  206. ;    bne.s    noprot3
  207. ;    pmove    C_CRP(a0),crp    ; restore MMU root pointer
  208. ;    pmove    C_TC(a0),tc    ; restore MMU control register
  209. noprot3:
  210.  
  211. %ifndef ONLY030
  212.     tst.w    ($59e).w    ; test longframe (AKP)
  213.     beq.s    short3
  214. %endif
  215. ; was moveq.l #0,d0, but I don't think that's what was desired */
  216.     moveq.l    #0,d1
  217.     lea    C_SFMT(a0),a1
  218.     move.w    (a1)+,d0    ; fetch frame format word
  219.     move.w    d0,d1        ; copy it for later
  220.     lsr.w    #8,d1        ; isolate the frame format identifier
  221.     lsr.w    #4,d1
  222.     lea    _framesizes,a2
  223.     move.b    0(a2,d1.w),d1
  224.     sub.w    d1,sp
  225.     sub.w    d1,sp
  226.     move.l    sp,a2
  227.     bra.s    rcover
  228. rcint:    move.w    (a1)+,(a2)+
  229. rcover:    dbf    d1,rcint
  230.     move.w    d0,-(sp)    ; frame format identifier
  231. ; if running with a true coprocessor we need to restore the FPU state
  232.  
  233.     tst.w    _fpu        ; is there a true FPU in the system
  234.     beq.s    short3
  235.     tst.b    C_FSTATE(a0)        ; if NULL frame then the FPU is not in use
  236.     beq.s    short4        ; skip programmer's model restore
  237.     fmovem.l    C_FCTRL(a0),fpcr/fpsr/fpiar    ; restore control registers
  238.     fmovem.x    C_FREGS(a0),fp0-fp7        ; and data registers
  239. short4:    frestore    C_FSTATE(a0)            ; finally the internal state
  240. short3:
  241.     move.l    C_PC(a0),-(sp)    ; push the PC
  242.     move.w    C_SR(a0),d0    ; fetch status register
  243.     move.w    d0,-(sp)    ; push the status register
  244.     tst.b    C_PTRACE(a0)        ; check for a pending trace
  245.     movem.l    (a0),d0-d7/a0-a6    ; restore registers d0-d7/a0-a6
  246.     beq.s    notrace
  247.     jmp    _new_trace
  248. notrace:
  249.     rte            ; jump back to old context
  250.  
  251.  
  252. _change_context:
  253.     ori.w    #$0700,sr    ; mask interrupts
  254.     move.l    4(sp),a0    ; address of context save area
  255.  
  256. ; Switch stacks now - starting now ssp is in the memory space of
  257. ; the process we're switching to. Thus, we can change memory context
  258. ; to there.
  259.  
  260.     move.l    C_SSP(a0),sp    ; supervisor stack pointer
  261.     move.l    C_USP(a0),a1
  262.     move.l    a1,usp        ; set user stack pointer
  263.     move.l    C_TERM(a0),($408).w    ; restore GEMDOS terminate vector
  264.  
  265. ; Set memory context now
  266.     tst.w    _no_mem_prot
  267.     bne.s    noprot4
  268.     pmove    C_CRP(a0),crp    ; restore MMU root pointer
  269.     pmove    C_TC(a0),tc    ; restore MMU control register
  270. noprot4:
  271. %ifndef ONLY030
  272.     tst.w    ($59e).w    ; test longframe (AKP)
  273.     beq.s    short6
  274. %endif
  275. ; was moveq.l #0,d0, but I don't think that's what was desired */
  276.     moveq.l    #0,d1
  277.     lea    C_SFMT(a0),a1
  278.     move.w    (a1)+,d0    ; fetch frame format word
  279.     move.w    d0,d1        ; copy it for later
  280.     lsr.w    #8,d1        ; isolate the frame format identifier
  281.     lsr.w    #4,d1
  282.     lea    _framesizes,a2
  283.     move.b    0(a2,d1.w),d1
  284.     sub.w    d1,sp
  285.     sub.w    d1,sp
  286.     move.l    sp,a2
  287.     bra.s    rcover2
  288. rcint2:    move.w    (a1)+,(a2)+
  289. rcover2: dbf    d1,rcint2
  290.     move.w    d0,-(sp)    ; frame format identifier
  291. ; if running with a true coprocessor we need to restore the FPU state
  292.  
  293.     tst.w    _fpu        ; is there a true FPU in the system
  294.     beq.s    short3
  295.     tst.b    C_FSTATE(a0)        ; if NULL frame then the FPU is not in use
  296.     beq.s    short5        ; skip programmer's model restore
  297.     fmovem.l    C_FCTRL(a0),fpcr/fpsr/fpiar    ; restore control registers
  298.     fmovem.x    C_FREGS(a0),fp0-fp7        ; and data registers
  299. short5:    frestore    C_FSTATE(a0)            ; finally the internal state
  300. short6:
  301.     move.l    C_PC(a0),-(sp)    ; push the PC
  302.     move.w    C_SR(a0),d0    ; fetch status register
  303.     move.w    d0,-(sp)    ; push the status register
  304.     tst.b    C_PTRACE(a0)        ; check for a pending trace
  305.     movem.l    (a0),d0-d7/a0-a6    ; restore registers d0-d7/a0-a6
  306.     beq.s    notrace2
  307.     jmp    _new_trace
  308. notrace2:
  309.     rte            ; jump back to old context
  310.  
  311.     END
  312.