Annotation of MiNT/src/context.spp, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.