Annotation of MiNT/src/gas/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:        .globl  _build_context
                     60: 
                     61:        .globl  _save_context
                     62: 
                     63:        .globl  _restore_context
                     64: 
                     65:        .globl  _fpu
                     66: 
                     67:        .globl  _m68010
                     68: 
                     69: 
                     70: 
                     71: _build_context:
                     72: 
                     73:        movel   a0, sp@-        | save a0; we'll use it for scratch
                     74: 
                     75:        movel   sp@(8), a0      | get address of save area
                     76: 
                     77:        tstw    _fpu            | is there a real FPU in the system?
                     78: 
                     79:        beq     nofpu           | no -- we can skip the FPU save
                     80: 
                     81:        fsave   a0@(78)         | save internal state frame
                     82: 
                     83:        tstb    a0@(78)         | if NULL frame then FPU not in use
                     84: 
                     85:        beq     nofpu
                     86: 
                     87:        fmovemx fp0-fp7,a0@(294)                | save data registers
                     88: 
                     89:        fmoveml fpcr/fpsr/fpi,a0@(390)  | and control registers
                     90: 
                     91: nofpu:
                     92: 
                     93:        moveml  d0-d7/a0-a6, a0@ | save registers D0-D7/A0-A6
                     94: 
                     95:        movel   sp@(14), a0@(66) | save PC of context
                     96: 
                     97:        movew   sp@(12), d0     | get SR of context
                     98: 
                     99:        movew   d0, a0@(64)     | save it 
                    100: 
                    101:        tstw    0x59e           | test longframe (AKP)
                    102: 
                    103:        beq     short1          | short
                    104: 
                    105:        lea     sp@(20), a1     | else long
                    106: 
                    107:        movew   sp@(18), d1     | fetch frame format word
                    108: 
                    109:        movew   d1, a0@(402)    | stash it away for later
                    110: 
                    111:        tstw    _m68010         | are we running on a 68010?
                    112: 
                    113:        bne     short2          | yes -- definitely a simple interrupt frame
                    114: 
                    115: |
                    116: 
                    117: | note: in order to have got to this point in the code we must be
                    118: 
                    119: | running on an 020/030
                    120: 
                    121: |
                    122: 
                    123:        bftst   d1{#16:#4}      | is it the simple interrupt frame?
                    124: 
                    125:        beq     short2          | yes -- just dump the stack contents
                    126: 
                    127:        moveml  a1@+, d1-d3     | get instruction address/4 internal words
                    128: 
                    129:        moveml  d1-d3, a0@(404) | save them
                    130: 
                    131:        bra     short2
                    132: 
                    133: short1:
                    134: 
                    135:        lea     sp@(18), a1     | save supervisor stack pointer
                    136: 
                    137: short2:                                | note that it should be pointing above the PC
                    138: 
                    139:        movel   a1, a0@(70)
                    140: 
                    141:        movel   usp, a1         | save user stack pointer
                    142: 
                    143:        movel   a1, a0@(60)
                    144: 
                    145:        btst    #13, d0         | check for supervisor mode
                    146: 
                    147:        beq     L_CONT1         | user mode; we already have stack in a1
                    148: 
                    149: L_SUPER1:
                    150: 
                    151: | note: this was lea a0@(18), but moving from the save state buffer 
                    152: 
                    153: | means not testing longframe again. (AKP)
                    154: 
                    155:        movel   a0@(70), a1     | was using super stack pointer before interrupt
                    156: 
                    157:                                | 
                    158: 
                    159: L_CONT1:
                    160: 
                    161:        movel   0x408, a0@(74)  | save GEMDOS terminate vector
                    162: 
                    163:        movel   sp@+, a0@(32)   | save old register a0
                    164: 
                    165:        rts
                    166: 
                    167: 
                    168: 
                    169: _save_context:
                    170: 
                    171:        movel   a0, sp@-        | save a0
                    172: 
                    173:        movel   sp@(8), a0      | get address of context save area
                    174: 
                    175: 
                    176: 
                    177: | if running with a true coprocessor we need to save the FPU state
                    178: 
                    179: 
                    180: 
                    181:        tstw    _fpu            | is there a true FPU in the system
                    182: 
                    183:        beq     nofpu2
                    184: 
                    185:        fsave   a0@(78)         | save internal state frame
                    186: 
                    187:        tstb    a0@(78)         | if NULL frame then the FPU is not in use
                    188: 
                    189:        beq     nofpu2          | skip programmer's model save
                    190: 
                    191:        fmovemx fp0-fp7,a0@(294)                | save data registers
                    192: 
                    193:        fmoveml fpcr/fpsr/fpi,a0@(390)  | and control registers
                    194: 
                    195: nofpu2:
                    196: 
                    197: | AGK: I am somewhat unsure of this assumption, viz that save_context
                    198: 
                    199: | can never be called in a situation where a co-processor
                    200: 
                    201: | mid-instruction stack frame would be required. I suspect this is a
                    202: 
                    203: | valid assumption, in which case the above FPU code is redundant, the
                    204: 
                    205: | next line is not however!
                    206: 
                    207: 
                    208: 
                    209:        clrw    a0@(402)                | mark as a 4 word stack frame
                    210: 
                    211: 
                    212: 
                    213:        moveml  d0-d7/a0-a6, a0@        | save D0-D7/A0-A6
                    214: 
                    215:        lea     sp@(8), a1
                    216: 
                    217:        movel   a1, a0@(70)     | save supervisor stack pointer
                    218: 
                    219:                                | note that it should be pointing above the PC
                    220: 
                    221:        movel   a1@(-4), a0@(66)        | save PC
                    222: 
                    223:        movel   usp, a1
                    224: 
                    225:        movel   a1, a0@(60)     | save user stack pointer
                    226: 
                    227:        movew   sr, d0
                    228: 
                    229:        movew   d0, a0@(64)     | save status register
                    230: 
                    231:        movel   0x408, a0@(74)  | save GEMDOS terminate vector
                    232: 
                    233:        movel   sp@+, a0@(32)   | save old a0
                    234: 
                    235:        moveql  #0, d0          | return 0
                    236: 
                    237:        rts
                    238: 
                    239: 
                    240: 
                    241: _restore_context:
                    242: 
                    243:        orw     #0x0700, sr     | mask interrupts
                    244: 
                    245:        movel   sp@(4), a0      | address of context save area
                    246: 
                    247:        movel   a0@(70), sp     | supervisor stack pointer
                    248: 
                    249:        movel   a0@(60), a1
                    250: 
                    251:        movel   a1, usp         | set user stack pointer
                    252: 
                    253:        movel   a0@(74), 0x408  | restore GEMDOS terminate vector
                    254: 
                    255: 
                    256: 
                    257:        tstw    0x59e           | test longframe (AKP)
                    258: 
                    259:        beq     short3
                    260: 
                    261: 
                    262: 
                    263:        movew   a0@(402),d0     | fetch frame format word
                    264: 
                    265:        tstw    _m68010         | are we on a 68010?
                    266: 
                    267:        bne     just0           | yes, so it's a simple interrupt frame
                    268: 
                    269: 
                    270: 
                    271:        bftst   d0{#16:#4}      | is it the simple interrupt frame ?
                    272: 
                    273:        beq     just0           | yes so just push a zero
                    274: 
                    275:        moveml  a0@(404),d1-d3  | saved instruction address/4 internal words
                    276: 
                    277:        moveml  d1-d3,sp@-
                    278: 
                    279: just0: movew   d0,sp@-
                    280: 
                    281: 
                    282: 
                    283: short3:
                    284: 
                    285:        movel   a0@(66), sp@-   | push the PC
                    286: 
                    287:        movew   a0@(64), d0     | get status register
                    288: 
                    289:        movew   d0, sp@-        | push the status register
                    290: 
                    291: 
                    292: 
                    293: | if running with a true co-processor we need to restore the FPU state
                    294: 
                    295: 
                    296: 
                    297:        tstw    _fpu
                    298: 
                    299:        beq     nofpu3
                    300: 
                    301:        tstb    a0@(78)                 | if NULL frame then FPU not in use
                    302: 
                    303:        beq     short7                  | skip programmer's model restore
                    304: 
                    305:        fmoveml a0@(390), fpcr/fpsr/fpi | restore control registers
                    306: 
                    307:        fmovemx a0@(294), fp0-fp7               | and data registers
                    308: 
                    309: short7: frestore a0@(78)                       | finally the internal state
                    310: 
                    311: 
                    312: 
                    313: nofpu3:
                    314: 
                    315:        moveml  a0@, d0-d7/a0-a6        | restore registers d0-d7/a0-a6
                    316: 
                    317:        rte                             | jump back to old context
                    318: 
                    319: 
                    320: 

unix.superglobalmegacorp.com

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