Annotation of MiNT/src/asm/context.s, revision 1.1

1.1     ! root        1: ;
        !             2: 
        !             3: ; routines for saving/restoring user contexts
        !             4: 
        !             5: ;
        !             6: 
        !             7: ; long build_context(struct context *sav):
        !             8: 
        !             9: ;      Called from an interrupt handler (such as the trap #1 routine
        !            10: 
        !            11: ;      for system calls) saves the context of the interrupted
        !            12: 
        !            13: ;      routine. Assumes that no user registers have been changed
        !            14: 
        !            15: ;      since the interrupt, and that the PC and status register
        !            16: 
        !            17: ;      are still on the stack. Returns the stack pointer being used
        !            18: 
        !            19: ;      at the time of the interrupt **in register a1**.
        !            20: 
        !            21: ;
        !            22: 
        !            23: ; long save_context(struct context *sav):
        !            24: 
        !            25: ;      Saves the context of the calling routine in the area pointed
        !            26: 
        !            27: ;      to by sav. Save_context always returns 0 when initially called;
        !            28: 
        !            29: ;      this is so processes can (by suitably manipulating the
        !            30: 
        !            31: ;      saved registers) tell when the return from save_context is
        !            32: 
        !            33: ;      actually caused by restoring the context, e.g.:
        !            34: 
        !            35: ;              if (save_context(sav) == 0) {           <<-- L1
        !            36: 
        !            37: ;                      /* do some stuff */
        !            38: 
        !            39: ;                      sav.regs[D0] = 1;       /* for restore context */
        !            40: 
        !            41: ;                      restore_context(sav);   /* goes back to L1 */
        !            42: 
        !            43: ;              }
        !            44: 
        !            45: ;              else /* this is the second time through */
        !            46: 
        !            47: ;
        !            48: 
        !            49: ; void restore_context(struct context *sav):
        !            50: 
        !            51: ;      Restores a context previously saved by build_context or save_context.
        !            52: 
        !            53: ;      Since the program counter is part of the context, this function
        !            54: 
        !            55: ;      will never return (it's like longjmp()).
        !            56: 
        !            57: ;
        !            58: 
        !            59: ; $Log: context.s,v $
        !            60: 
        !            61: ; Revision 1.6  1992/03/31  14:02:08  AGK
        !            62: 
        !            63: ; Fixed for real Motorola syntax (many thanks to ERS for keeping these
        !            64: 
        !            65: ; files in step with the GAS ones).
        !            66: 
        !            67: ;
        !            68: 
        !            69: ; Revision 1.5  1992/03/31  13:55:28  AGK
        !            70: 
        !            71: ; Checked in MiNT 0.93 sources
        !            72: 
        !            73: ;
        !            74: 
        !            75: ; Revision 1.4  1991/05/31  15:55:00  AGK
        !            76: 
        !            77: ; Tested only a byte in the save frame, not a word (my mistake). Bumped FPU
        !            78: 
        !            79: ; frame size up to 216 bytes, the 68882 manual is wrong (thanks Motorola!)
        !            80: 
        !            81: ;
        !            82: 
        !            83: ; Revision 1.3  1991/05/31  09:58:44  AGK
        !            84: 
        !            85: ; Fixed stack frame format manipulation so we use d1, not d0, which is
        !            86: 
        !            87: ; needed later for super/user mode determination.
        !            88: 
        !            89: ;
        !            90: 
        !            91: ; Revision 1.2  1991/05/31  09:48:06  AGK
        !            92: 
        !            93: ; Changes to accomodate longer stack frames etc.
        !            94: 
        !            95: ;
        !            96: 
        !            97: ; Revision 1.1  1991/05/30  17:22:02  AGK
        !            98: 
        !            99: ; Initial revision
        !           100: 
        !           101: ;
        !           102: 
        !           103:        SECTION TEXT
        !           104: 
        !           105:        
        !           106: 
        !           107:        XDEF    _build_context
        !           108: 
        !           109:        XDEF    _save_context
        !           110: 
        !           111:        XDEF    _restore_context
        !           112: 
        !           113:        XREF    _fpu
        !           114: 
        !           115:        XREF    _m68010
        !           116: 
        !           117:        
        !           118: 
        !           119: _build_context:
        !           120: 
        !           121:        move.l  a0,-(sp)        ; save a0; we'll use it for scratch
        !           122: 
        !           123:        move.l  8(sp),a0        ; get address of save area
        !           124: 
        !           125: 
        !           126: 
        !           127: ; if running with a true coprocessor we need to save the FPU state
        !           128: 
        !           129: 
        !           130: 
        !           131:        tst.w   _fpu            ; is there a true FPU in the system
        !           132: 
        !           133:        beq.s   nofpu
        !           134: 
        !           135:        fsave   78(a0)          ; save internal state frame
        !           136: 
        !           137:        tst.b   78(a0)          ; if NULL frame then the FPU is not in use
        !           138: 
        !           139:        beq.s   nofpu           ; skip programmer's model save
        !           140: 
        !           141:        fmovem.x        fp0-fp7,294(a0)         ; save data registers
        !           142: 
        !           143:        fmovem.l        fpcr/fpsr/fpiar,390(a0) ; and control registers
        !           144: 
        !           145: nofpu:
        !           146: 
        !           147:        movem.l d0-d7/a0-a6,(a0)        ; save registers D0-D7/A0-A6
        !           148: 
        !           149:        move.l  14(sp),66(a0)   ; save PC of context
        !           150: 
        !           151:        move.w  12(sp),d0       ; get SR of context
        !           152: 
        !           153:        move.w  d0,64(a0)       ; save it 
        !           154: 
        !           155:        tst.w   ($59e).w        ; test longframe (AKP)
        !           156: 
        !           157:        beq.s   short1          ; short
        !           158: 
        !           159:        lea     20(sp),a1       ; else long
        !           160: 
        !           161:        
        !           162: 
        !           163:        move.w  18(sp),d1       ; fetch frame format word
        !           164: 
        !           165:        move.w  d1,402(a0)      ; and stash it away for later
        !           166: 
        !           167:        tst.w   _m68010         ; are we on a 68010?
        !           168: 
        !           169:        bne.s   short2          ; yes -- so it's a simple interrupt frame
        !           170: 
        !           171: ; note: in order to have got to this point in the code we must be
        !           172: 
        !           173: ; running on an 020/030 hence we can use the extra processor instructions
        !           174: 
        !           175:        bftst   d1{16:4}        ; is it the simple interrupt frame ?
        !           176: 
        !           177:        beq.s   short2          ; yes so just dump the stack contents
        !           178: 
        !           179:        movem.l (a1)+,d1-d3     ; instruction address/4 internal words
        !           180: 
        !           181:        movem.l d1-d3,404(a0)
        !           182: 
        !           183:        bra.s   short2
        !           184: 
        !           185: short1:
        !           186: 
        !           187:        lea     18(sp),a1       ; save supervisor stack pointer
        !           188: 
        !           189: short2:                                ; note that it should be pointing above the PC
        !           190: 
        !           191:        move.l  a1,70(a0)
        !           192: 
        !           193:        move.l  usp,a1          ; save user stack pointer
        !           194: 
        !           195:        move.l  a1,60(a0)
        !           196: 
        !           197:        btst    #13,d0          ; check for supervisor mode
        !           198: 
        !           199:        beq.s   L_CONT1         ; user mode; we already have stack in a1
        !           200: 
        !           201: L_SUPER1:
        !           202: 
        !           203: ; note: this was lea a0@(18), but moving from the save state buffer 
        !           204: 
        !           205: ; means not testing longframe again. (AKP)
        !           206: 
        !           207:        move.l  70(a0),a1       ; was using super stack pointer before interrupt
        !           208: 
        !           209:                                ; 
        !           210: 
        !           211: L_CONT1:
        !           212: 
        !           213:        move.l  ($408).w,74(a0) ; save GEMDOS terminate vector
        !           214: 
        !           215:        move.l  (sp)+,32(a0)    ; save old register a0
        !           216: 
        !           217:        rts
        !           218: 
        !           219: 
        !           220: 
        !           221: _save_context:
        !           222: 
        !           223:        move.l  a0,-(sp)        ; save a0
        !           224: 
        !           225:        move.l  8(sp),a0        ; get address of context save area
        !           226: 
        !           227: 
        !           228: 
        !           229: ; if running with a true coprocessor we need to save the FPU state
        !           230: 
        !           231: 
        !           232: 
        !           233:        tst.w   _fpu            ; is there a true FPU in the system
        !           234: 
        !           235:        beq.s   nofpu2
        !           236: 
        !           237:        fsave   78(a0)          ; save internal state frame
        !           238: 
        !           239:        tst.b   78(a0)          ; if NULL frame then the FPU is not in use
        !           240: 
        !           241:        beq.s   nofpu2          ; skip programmer's model save
        !           242: 
        !           243:        fmovem.x        fp0-fp7,294(a0)         ; save data registers
        !           244: 
        !           245:        fmovem.l        fpcr/fpsr/fpiar,390(a0) ; and control registers
        !           246: 
        !           247: nofpu2:
        !           248: 
        !           249: ; note: I am somewhat unsure of this assumption, viz that save_context
        !           250: 
        !           251: ; can never be called in a situation where a co-processor
        !           252: 
        !           253: ; mid-instruction stack frame would be required. I suspect this is a
        !           254: 
        !           255: ; valid assumption, in which case the above FPU code is redundant, the
        !           256: 
        !           257: ; next line is not however!
        !           258: 
        !           259: 
        !           260: 
        !           261:        clr.w   402(a0)         ; mark as a 4 word stack frame
        !           262: 
        !           263: 
        !           264: 
        !           265:        movem.l d0-d7/a0-a6,(a0)        ; save D0-D7/A0-A6
        !           266: 
        !           267:        lea     8(sp),a1
        !           268: 
        !           269:        move.l  a1,70(a0)       ; save supervisor stack pointer
        !           270: 
        !           271:                                ; note that it should be pointing above the PC
        !           272: 
        !           273:        move.l  -4(a1),66(a0)   ; save PC
        !           274: 
        !           275:        move.l  usp,a1
        !           276: 
        !           277:        move.l  a1,60(a0)       ; save user stack pointer
        !           278: 
        !           279:        move.w  sr,d0
        !           280: 
        !           281:        move.w  d0,64(a0)       ; save status register
        !           282: 
        !           283:        move.l  ($408).w,74(a0) ; save GEMDOS terminate vector
        !           284: 
        !           285:        move.l  (sp)+,32(a0)    ; save old a0
        !           286: 
        !           287:        moveq.l #0,d0           ; return 0
        !           288: 
        !           289:        rts
        !           290: 
        !           291: 
        !           292: 
        !           293: _restore_context:
        !           294: 
        !           295:        ori.w   #$0700,sr       ; mask interrupts
        !           296: 
        !           297:        move.l  4(sp),a0        ; address of context save area
        !           298: 
        !           299:        move.l  70(a0),sp       ; supervisor stack pointer
        !           300: 
        !           301:        move.l  60(a0),a1
        !           302: 
        !           303:        move.l  a1,usp          ; set user stack pointer
        !           304: 
        !           305:        move.l  74(a0),($408).w ; restore GEMDOS terminate vector
        !           306: 
        !           307: 
        !           308: 
        !           309:        tst.w   ($59e).w        ; test longframe (AKP)
        !           310: 
        !           311:        beq.s   short3
        !           312: 
        !           313: 
        !           314: 
        !           315:        move.w  402(a0),d0      ; fetch frame format word
        !           316: 
        !           317:        tst.w   _m68010
        !           318: 
        !           319:        bne.s   just0
        !           320: 
        !           321: 
        !           322: 
        !           323: ; again, we reach here only on an 020/030
        !           324: 
        !           325: 
        !           326: 
        !           327:        bftst   d0{16:4}        ; is it the simple interrupt frame ?
        !           328: 
        !           329:        beq.s   just0           ; yes so just push a zero
        !           330: 
        !           331:        movem.l 404(a0),d1-d3   ; saved instruction address/4 internal words
        !           332: 
        !           333:        movem.l d1-d3,-(sp)
        !           334: 
        !           335: just0: move.w  d0,-(sp)
        !           336: 
        !           337:        
        !           338: 
        !           339: short3:
        !           340: 
        !           341:        move.l  66(a0),-(sp)    ; push the PC
        !           342: 
        !           343:        move.w  64(a0),d0       ; get status register
        !           344: 
        !           345:        move.w  d0,-(sp)        ; push the status register
        !           346: 
        !           347: 
        !           348: 
        !           349: ; if running with a true coprocessor we need to restore the FPU state
        !           350: 
        !           351: 
        !           352: 
        !           353:        tst.w   _fpu            ; is there a true FPU in the system
        !           354: 
        !           355:        beq.s   nofpu3
        !           356: 
        !           357:        tst.b   78(a0)          ; if NULL frame then the FPU is not in use
        !           358: 
        !           359:        beq.s   short7          ; skip programmer's model restore
        !           360: 
        !           361:        fmovem.l        390(a0),fpcr/fpsr/fpiar ; restore control registers
        !           362: 
        !           363:        fmovem.x        294(a0),fp0-fp7         ; and data registers
        !           364: 
        !           365: short7:        frestore        78(a0)                  ; finally the internal state
        !           366: 
        !           367: 
        !           368: 
        !           369: nofpu3:
        !           370: 
        !           371:        movem.l (a0),d0-d7/a0-a6 ; restore registers d0-d7/a0-a6
        !           372: 
        !           373:        rte                     ; jump back to old context
        !           374: 
        !           375: 
        !           376: 
        !           377:        END
        !           378: 

unix.superglobalmegacorp.com

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