*-------------------------------------------------------------------------
*   Context switch for Atari ST Icon
*-------------------------------------------------------------------------
*   Stack arrangement for a C function call
*       (reference version 3.03 Lattice C Manual, page 242)
*-------------------------------------------------------------------------
*
*                ========   SP (a7) ->  |-------------------| Low
*                expression evaluation  |    temporaries    |
*                                       |-------------------|
*                addressed as negative  |  auto data items  |
*                      offsets from FP  |     .  .  .       |
*                ========   FP (a6) ->  |-------------------|
*                called routine pushes  | caller's saved FP |
*                                       |-------------------|
*                pushed by jsr          |  return address   |
*                                       |-------------------|
*                first argument is      |    arguments      |
*                a6 plus 8 bytes        |     .  .  .       |
*                old SP value   ----->  |-------------------| High
*
*-------------------------------------------------------------------------
        text                         control section for instructions
        xdef    coswitch
        xref    interp
        xref    syserr
*   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *
coswitch  equ  *
        link    a6,#0                push frame pointer & allocate no locals
        move.l  8(a6),a0             a0 = address of old_cs
        move.l  12(a6),a1            a1 = address of new_cs
        move.l  a7,(a0)              store stack pointer in old_cs
        movem.l d2-d7/a2-a6,4(a0)    store needed registers in old_cs
        move.l  (a1),a7              load stack pointer from new_cs
        tst.l   16(a6)               if(first == 0) {
        bne     nofirst
        moveq   #0,d0                    zero return value
        move.l  d0,a6                    zero frame pointer
        move.l  d0,-(a7)                 push two zero arguments
        move.l  d0,-(a7)                    for interp()
        jsr     interp                   call interp()
        addq.l  #8,a7                    remove interp() args from stack
        pea     mesg                     push argument for syserr()
        jsr     syserr                   call syserr()
*   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *
*  Following instructions not needed because syserr() never returns         *
*                                                                           *
*       addq.l  #4,a7                    remove syserr() args from stack    *
*       bra     done                 } else                                 *
*   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *
nofirst equ     *
        movem.l 4(a1),d2-d7/a2-a6        restore preserved regs from new_cs
*   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *
done    equ     *
        unlk    a6                   restore frame pointer from stack
        rts                          return to calling program
*   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *
        data                         control section for initialized statics
mesg    dc.b    'interp() returned in coswitch',0
        end
