home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / mint / mint095s / context.s < prev    next >
Text File  |  1993-08-03  |  6KB  |  161 lines

  1. |
  2. | routines for saving/restoring user contexts
  3. |
  4. | long build_context(struct context *sav):
  5. |    Called from an interrupt handler (such as the trap #1 routine
  6. |    for system calls) saves the context of the interrupted
  7. |    routine. Assumes that no user registers have been changed
  8. |    since the interrupt, and that the PC and status register
  9. |    are still on the stack. Returns the stack pointer being used
  10. |    at the time of the interrupt **in register a1**.
  11. |
  12. | long save_context(struct context *sav):
  13. |    Saves the context of the calling routine in the area pointed
  14. |    to by sav. Save_context always returns 0 when initially called;
  15. |    this is so processes can (by suitably manipulating the
  16. |    saved registers) tell when the return from save_context is
  17. |    actually caused by restoring the context, e.g.:
  18. |        if (save_context(sav) == 0) {        <<-- L1
  19. |            /* do some stuff */
  20. |            sav.regs[D0] = 1;    /* for restore context */
  21. |            restore_context(sav);    /* goes back to L1 */
  22. |        }
  23. |        else /* this is the second time through */
  24. |
  25. | void restore_context(struct context *sav):
  26. |    Restores a context previously saved by build_context or save_context.
  27. |    Since the program counter is part of the context, this function
  28. |    will never return (it's like longjmp()).
  29.  
  30.     .globl    _build_context
  31.     .globl     _save_context
  32.     .globl    _restore_context
  33.     .globl    _fpu
  34.     .globl    _m68010
  35.  
  36. _build_context:
  37.     movel    a0, sp@-    | save a0; we'll use it for scratch
  38.     movel    sp@(8), a0    | get address of save area
  39.     tstw    _fpu        | is there a real FPU in the system?
  40.     beq    nofpu        | no -- we can skip the FPU save
  41.     fsave    a0@(78)        | save internal state frame
  42.     tstb    a0@(78)        | if NULL frame then FPU not in use
  43.     beq    nofpu
  44.     fmovemx    fp0-fp7,a0@(294)        | save data registers
  45.     fmoveml    fpcr/fpsr/fpi,a0@(390)    | and control registers
  46. nofpu:
  47.     moveml    d0-d7/a0-a6, a0@ | save registers D0-D7/A0-A6
  48.     movel    sp@(14), a0@(66) | save PC of context
  49.     movew    sp@(12), d0    | get SR of context
  50.     movew    d0, a0@(64)    | save it 
  51.     tstw    0x59e        | test longframe (AKP)
  52.     beq    short1        | short
  53.     lea    sp@(20), a1    | else long
  54.     movew    sp@(18), d1    | fetch frame format word
  55.     movew    d1, a0@(402)    | stash it away for later
  56.     tstw    _m68010        | are we running on a 68010?
  57.     bne    short2        | yes -- definitely a simple interrupt frame
  58. |
  59. | note: in order to have got to this point in the code we must be
  60. | running on an 020/030
  61. |
  62.     bftst    d1{#16:#4}    | is it the simple interrupt frame?
  63.     beq    short2        | yes -- just dump the stack contents
  64.     moveml    a1@+, d1-d3    | get instruction address/4 internal words
  65.     moveml    d1-d3, a0@(404)    | save them
  66.     bra    short2
  67. short1:
  68.     lea    sp@(18), a1    | save supervisor stack pointer
  69. short2:                | note that it should be pointing above the PC
  70.     movel    a1, a0@(70)
  71.     movel    usp, a1        | save user stack pointer
  72.     movel    a1, a0@(60)
  73.     btst    #13, d0        | check for supervisor mode
  74.     beq    L_CONT1        | user mode; we already have stack in a1
  75. L_SUPER1:
  76. | note: this was lea a0@(18), but moving from the save state buffer 
  77. | means not testing longframe again. (AKP)
  78.     movel    a0@(70), a1    | was using super stack pointer before interrupt
  79.                 | 
  80. L_CONT1:
  81.     movel    0x408, a0@(74)    | save GEMDOS terminate vector
  82.     movel    sp@+, a0@(32)    | save old register a0
  83.     rts
  84.  
  85. _save_context:
  86.     movel    a0, sp@-    | save a0
  87.     movel    sp@(8), a0    | get address of context save area
  88.  
  89. | if running with a true coprocessor we need to save the FPU state
  90.  
  91.     tstw    _fpu        | is there a true FPU in the system
  92.     beq    nofpu2
  93.     fsave    a0@(78)        | save internal state frame
  94.     tstb    a0@(78)        | if NULL frame then the FPU is not in use
  95.     beq    nofpu2        | skip programmer's model save
  96.     fmovemx    fp0-fp7,a0@(294)        | save data registers
  97.     fmoveml    fpcr/fpsr/fpi,a0@(390)    | and control registers
  98. nofpu2:
  99. | AGK: I am somewhat unsure of this assumption, viz that save_context
  100. | can never be called in a situation where a co-processor
  101. | mid-instruction stack frame would be required. I suspect this is a
  102. | valid assumption, in which case the above FPU code is redundant, the
  103. | next line is not however!
  104.  
  105.     clrw    a0@(402)        | mark as a 4 word stack frame
  106.  
  107.     moveml    d0-d7/a0-a6, a0@    | save D0-D7/A0-A6
  108.     lea    sp@(8), a1
  109.     movel    a1, a0@(70)    | save supervisor stack pointer
  110.                 | note that it should be pointing above the PC
  111.     movel    a1@(-4), a0@(66)    | save PC
  112.     movel    usp, a1
  113.     movel    a1, a0@(60)    | save user stack pointer
  114.     movew    sr, d0
  115.     movew    d0, a0@(64)    | save status register
  116.     movel    0x408, a0@(74)    | save GEMDOS terminate vector
  117.     movel    sp@+, a0@(32)    | save old a0
  118.     moveql    #0, d0        | return 0
  119.     rts
  120.  
  121. _restore_context:
  122.     orw    #0x0700, sr    | mask interrupts
  123.     movel    sp@(4), a0    | address of context save area
  124.     movel    a0@(70), sp    | supervisor stack pointer
  125.     movel    a0@(60), a1
  126.     movel    a1, usp        | set user stack pointer
  127.     movel    a0@(74), 0x408    | restore GEMDOS terminate vector
  128.  
  129.     tstw    0x59e        | test longframe (AKP)
  130.     beq    short3
  131.  
  132.     movew    a0@(402),d0    | fetch frame format word
  133.     tstw    _m68010        | are we on a 68010?
  134.     bne    just0        | yes, so it's a simple interrupt frame
  135.  
  136.     bftst    d0{#16:#4}    | is it the simple interrupt frame ?
  137.     beq    just0        | yes so just push a zero
  138.     moveml    a0@(404),d1-d3    | saved instruction address/4 internal words
  139.     moveml    d1-d3,sp@-
  140. just0:    movew    d0,sp@-
  141.  
  142. short3:
  143.     movel    a0@(66), sp@-    | push the PC
  144.     movew    a0@(64), d0    | get status register
  145.     movew    d0, sp@-    | push the status register
  146.  
  147. | if running with a true co-processor we need to restore the FPU state
  148.  
  149.     tstw    _fpu
  150.     beq    nofpu3
  151.     tstb    a0@(78)            | if NULL frame then FPU not in use
  152.     beq    short7            | skip programmer's model restore
  153.     fmoveml    a0@(390), fpcr/fpsr/fpi    | restore control registers
  154.     fmovemx    a0@(294), fp0-fp7        | and data registers
  155. short7: frestore a0@(78)            | finally the internal state
  156.  
  157. nofpu3:
  158.     moveml    a0@, d0-d7/a0-a6     | restore registers d0-d7/a0-a6
  159.     rte                | jump back to old context
  160.  
  161.