#include "bases.h" asm( "| the stack consists of a single linked linear list like this:" "|" "| struct stack" "| { struct stack *next; points to the next underlying structure" "| struct StackSwapStruct sss; holds previous stackframe when used," "| itself when unused, the current stackborders" "| are in the task structure ;-)" "| APTR top_of_stackframe; } previous variable value" "| Note: stack->sss.stk_Lower is not reliable" "|" "| For better performance stackframes are cached in a 'unused' list when" "| not in use. (AllocMem() is really a performance killer)." "|" "|" "| Caution:" "| Race condition ahead! exec might preempt our task at any time storing" "| the current register set on top of the free stack. NEVER set a sp higher" "| than the location of important data." "|\n" " .comm ___used_stack,8;" /* pointer to used stackframes */ /* pointer to unused stackframes */ " .text;" " .even;" " .globl ___stkrst;" "___stkrst:;" " exg d0,a3;" /* better use an address register*/ " movel a2,sp@-;" " moveml d0/d1/a0/a1/a5/a6,sp@-;" " movel sp,a2;" " lea "A4(___used_stack)",a5;" " tstl a5@;" " jeq l0;" /* No previous stackframe*/ "l2: movel "A4(___stackborders)",a0;" " cmpl a0@,a3;" " jcs l1;" " cmpl a0@(4:W),a3;" " jle l0;" /* Stackpointer points to current frame*/ "l1: movel "A4(_SysBase)",a6;" /* Go to previous stack*/ " movel a5,a1;" " movel a1@,a0;" " movel a0@,a1@+;" " movel a1@,a0@;" " movel a0,a1@;" " addql #4,a0;" " movel a0@(12:W),"A4(___stk_limit)";" " jsr a6@(-0x2dc);" /* StackSwap(sss:a0)*/ " tstl a5@;" " jne l2;" "l0: moveml a2@+,d0/d1/a0/a1/a5/a6;" /* Restore registers*/ " movel a2@(4:W),sp@-;" /* preserve returnaddress on current stackframe*/ " movel a2@,a2;" /* be careful to not clobber any registers now*/ " cmpl sp,a3;" /* Depending on whether sp moves up or down*/ " jls l3;" /* use one of two possible routines*/ " movel sp@,a3@-;" /* moves up (pop): copy returnaddress first*/ " movel a3,sp;" /* then set sp*/ " jra l4;" "l3: exg a3,sp;" /* moves down (push): set sp first*/ " movel a3@,sp@-;" /* then copy returnaddress*/ " movel sp,a3;" "l4: exg d0,a3;" /* move back*/ " addql #4,d0;" /* compensate for returnaddress*/ " rts;" );