Admin Panel
#include <exec/execbase.h>
#include <proto/exec.h>
#include <stdlib.h>
// force using the section based init
#define __libnix__ 1
#include "stabs.h"
extern struct ExecBase *SysBase;
extern UWORD *__SaveSP;
register UWORD *a7 __asm("sp");
#if defined(__KICK13__)
extern void * AllocVec(unsigned, int);
extern void FreeVec(void *);
#endif
#undef StackSwap
#define StackSwap __StackSwap
#pragma GCC push_options
#pragma GCC optimize ("-Os")
#pragma GCC optimize ("-fomit-frame-pointer")
// keeps d0/d1/a0/a1 free for local use.
void __stkswap() {
register struct StackSwapStruct *newStack asm("a2");
register struct ExecBase *SysBase asm("a6");
register UWORD *tmp, *upper asm("a1"), *sp;
struct Task *task = SysBase->ThisTask;
Disable();
tmp = (UWORD*) newStack->stk_Lower;
newStack->stk_Lower = task->tc_SPLower;
task->tc_SPLower = tmp;
tmp = (UWORD*) newStack->stk_Upper;
newStack->stk_Upper = (ULONG) task->tc_SPUpper;
task->tc_SPUpper = tmp;
// copy stack
sp = (UWORD*) newStack->stk_Upper;
upper = tmp;
while (sp != a7)
*--upper = *--sp;
task->tc_SPReg = a7 = upper;
Enable();
}
// performs no push/pop of a2/a6, it's not necessary...
__attribute((noinline)) void StackSwap(volatile struct StackSwapStruct *newStack) {
asm("move.l %0,a2"::"r" (newStack));
asm("move.l %0,a6"::"r" (SysBase));
__stkswap();
}
/*
* swapstack.c
*
* A libnix startup module to swap to a new stack if the old one is not
* big enough (minimum value set by the value of the __stack variable).
*
* Code derived from a stackswap module by Kriton Kyrimis (kyrimis@theseas.ntua.gr)
*
* Fixed by Bebbo.
*
* Usage: put this snippet into your main:
extern void __stkinit(void);
void * __x = __stkinit;
unsigned long __stack = YOUR_STACK_SIZE;
*/
extern unsigned long __stack;
void __request(const char *text);
static volatile struct StackSwapStruct stack;
static char *newstack;
void __stkinit() {
ULONG size, needed = __stack;
struct Task *task;
char *new;
register UWORD *upper asm("a2"), *to asm("a0"), *sp;
/* Determine original stack size */
task = SysBase->ThisTask;
#if defined(__KICK13__)
task->tc_SPUpper = __SaveSP + 6;
#else
size = (char*) task->tc_SPUpper - (char*) task->tc_SPLower;
if (needed <= size)
return;
#endif
/* Round size to next long word */
needed = (needed + (sizeof(LONG) - 1)) & ~(sizeof(LONG) - 1);
/* Allocate new stack */
newstack = new = AllocVec(needed, MEMF_PUBLIC);
if (!new) {
__request("Couldn't allocate new stack!");
exit(RETURN_FAIL);
}
/* Build new stack structure */
stack.stk_Lower = new;
stack.stk_Upper = (ULONG) (new + needed);
/* Copy required parts of old stack */
to = upper = (UWORD*) stack.stk_Upper;
sp = __SaveSP;
while (sp != a7)
*--to = *--sp;
stack.stk_Pointer = to;
/* Switch to new stack */
StackSwap(&stack);
__SaveSP += upper - (UWORD*) stack.stk_Upper;
}
void __stkexit() {
ULONG size;
register UWORD *upper asm("a2"), *to asm("a0"), *sp;
if (!newstack)
return;
/* Copy required parts of old stack */
to = upper = (UWORD*) stack.stk_Upper;
sp = __SaveSP;
while (sp != a7)
*--to = *--sp;
stack.stk_Pointer = to;
/* Switch back to old stack */
StackSwap(&stack);
__SaveSP += upper - (UWORD*) stack.stk_Upper;
/* And clean up */
FreeVec(newstack);
}
/* The same priority as the detach module - you cannot use them both */
ADD2INIT(__stkinit, -70);
ADD2EXIT(__stkexit, -70);