mirror of
https://github.com/cahirwpz/libnix.git
synced 2025-12-08 14:58:56 +00:00
69 lines
2.0 KiB
C
Executable File
69 lines
2.0 KiB
C
Executable File
#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.
|
|
|
|
|
.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
|
|
");
|