Admin Panel
#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;"
);