Annotation of MiNT/src/asm/context.s, revision 1.1.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.