1
0
mirror of https://github.com/Interlisp/maiko.git synced 2026-01-16 16:19:10 +00:00
2021-01-19 21:23:26 -08:00

1052 lines
33 KiB
C

/* $Id: llstk.c,v 1.5 2001/12/26 22:17:03 sybalsky Exp $ (C) Copyright Venue, All Rights Reserved */
/************************************************************************/
/* */
/* (C) Copyright 1989-95 Venue. All Rights Reserved. */
/* Manufactured in the United States of America. */
/* */
/************************************************************************/
#include "version.h"
/******************************************************************/
/*
File Name : llstk.c
Desc. : Low Level stack operations
Including :
Edited by : Takeshi Shimizu(March 14, 1988)
*/
/******************************************************************/
#include <stdio.h> /* for printf */
#ifdef FSBCHECK
#include <string.h> /* for memset */
#endif
#include "lispemul.h"
#include "lispmap.h"
#include "adr68k.h"
#include "address.h"
#include "lsptypes.h"
#include "initatms.h"
#include "lspglob.h"
#include "emlglob.h"
#include "cell.h"
#include "stack.h"
#include "return.h"
#include "llstkdefs.h"
#include "commondefs.h"
#include "dbgtooldefs.h"
#include "testtooldefs.h"
#include "kprintdefs.h"
#include "storagedefs.h"
extern int extended_frame;
/******************************************************************/
/*
Func Name : extendstack()
Desc. : if LastStackAddr_word is exceeded,then allocate
one new lisppage for STACK area.
Edited by : Take(March 14, 1988)
*/
/******************************************************************/
static DLword *extendstack(void) {
register LispPTR easp;
register LispPTR scanptr;
easp = InterfacePage->endofstack;
if (easp < LOLOC(*LastStackAddr_word)) {
if ((easp > LOLOC(*GuardStackAddr_word)) && ((*STACKOVERFLOW_word) == NIL)) {
extended_frame = 1;
((INTSTAT *)Addr68k_from_LADDR(*INTERRUPTSTATE_word))->stackoverflow = 1;
*STACKOVERFLOW_word = *PENDINGINTERRUPT_word = ATOM_T;
}
newpage(STK_OFFSET | (scanptr = easp + 2));
/* I don't concern about DOLOCKPAGES */
MAKEFREEBLOCK(Addr68k_from_StkOffset(scanptr), DLWORDSPER_PAGE - 2);
InterfacePage->endofstack = scanptr = easp + DLWORDSPER_PAGE;
SETUPGUARDBLOCK(Addr68k_from_StkOffset(InterfacePage->endofstack), 2);
MAKEFREEBLOCK(Addr68k_from_StkOffset(easp), 2);
return ((DLword *)Addr68k_from_StkOffset(scanptr));
} else
return (NIL);
} /* end extendstack */
/******************************************************************/
/*
Func Name : moveframe(oldfx68k)
Edited by : Take(March 14, 1988)
*/
/******************************************************************/
static LispPTR moveframe(register FX *oldfx68k) {
register int size;
register DLword *next68k;
register DLword *new68k;
int nametbl_on_stk = NIL;
int at_eos = NIL;
PreMoveFrameCheck(oldfx68k);
#ifdef FLIPCURSOR
flip_cursorbar(10);
#endif
size = FX_size(oldfx68k) + DLWORDSPER_CELL;
S_CHECK(size > 0, "size of stack block < 0");
next68k = Addr68k_from_StkOffset(oldfx68k->nextblock);
tryfsb:
if (FSBP(next68k)) {
/* merge free blocks */
new68k = next68k + FSB_size(next68k);
if (FSBP(new68k)) {
for (; FSBP(new68k); new68k = new68k + FSB_size(new68k))
FSB_size(next68k) += FSB_size(new68k);
new68k = (DLword *)oldfx68k;
goto out;
} else if (StkOffset_from_68K(new68k) == InterfacePage->endofstack) {
if ((StkOffset_from_68K(new68k) > LOLOC(*GuardStackAddr_word)) &&
((*STACKOVERFLOW_word) == NIL))
at_eos = T; /* search FSB in earlier STACK area by freestackblock */
else if (extendstack() != NIL) {
new68k = (DLword *)oldfx68k;
goto out;
} else {
/* These lines are different from Original Code */
return (0xFFFF); /* No space */
}
} /* else if end */
}
CHECK_FX(oldfx68k);
S_CHECK(oldfx68k->usecount == 0, "use count > 0");
/* we don't check \INTERRUPTABLE */
#ifdef BIGVM
if (oldfx68k->validnametable && ((oldfx68k->nametable >> 16) == STK_HI))
#else
if (oldfx68k->validnametable && (oldfx68k->hi2nametable == STK_HI))
#endif /* BIGVM */
{
/* frame contains a name table, so we care that the alignment
of the new block be same as old */
#ifdef STACKCHECK
{
DLword n;
#ifdef BIGVM
n = oldfx68k->nametable & 0xFFFF;
#else
n = oldfx68k->lonametable;
#endif /* BIGVM */
if ((n <= StkOffset_from_68K(oldfx68k)) && (n >= oldfx68k->nextblock)) {
WARN("moveframe:check!!", sff(LADDR_from_68k(oldfx68k)));
return 0; /* ? */
}
}
#endif
nametbl_on_stk = T;
/* Find a free stack block */
new68k = freestackblock(size, (StackWord *)oldfx68k,
(LADDR_from_68k(oldfx68k) - DLWORDSPER_CELL) % DLWORDSPER_QUAD);
} else
new68k = freestackblock(size, (StackWord *)oldfx68k, -1); /* Not needed to align */
if (new68k == 0) return (0xFFFF); /* exhausted */
if (new68k < Stackspace) error("freestackblock returned gunk.");
if (at_eos && ((UNSIGNED)new68k > (UNSIGNED)oldfx68k)) {
/* extendstack already done in freestackblock */
((STKBLK *)new68k)->flagword = STK_FSB_WORD;
if (((STKBLK *)new68k)->size == 0) error("0-long stack freeblock.");
goto tryfsb;
}
/* copy frame and dummy bf pointer too */
blt(new68k, (((DLword *)oldfx68k) - DLWORDSPER_CELL), size);
((Bframe *)new68k)->residual = T;
new68k = new68k + DLWORDSPER_CELL; /* now NEW points to the FX */
((FX *)new68k)->nextblock = (StkOffset_from_68K(new68k) + size) - DLWORDSPER_CELL;
/* (CHECK (fetch (BF CHECKED) of (fetch (FX BLINK) of OLDFRAME)))*/
CHECK_BF((Bframe *)Addr68k_from_StkOffset(GETBLINK(oldfx68k)));
/* Set true BFptr,not residual */
SETBLINK(new68k, GETBLINK(oldfx68k));
if (nametbl_on_stk) {
S_CHECK(((((UNSIGNED)new68k - (UNSIGNED)oldfx68k) >> 1) % DLWORDSPER_QUAD) == 0,
"Misalignment of stack blocks, with nametable on stack");
#ifdef BIGVM
((FX *)new68k)->nametable += (((UNSIGNED)new68k - (UNSIGNED)oldfx68k) >> 1);
#else
((FX *)new68k)->lonametable += (((UNSIGNED)new68k - (UNSIGNED)oldfx68k) >> 1);
#endif
}
if (((Bframe *)DUMMYBF(oldfx68k))->residual) {
MAKEFREEBLOCK(((DLword *)oldfx68k) - DLWORDSPER_CELL, size);
} else {
MAKEFREEBLOCK(oldfx68k, size - DLWORDSPER_CELL);
}
out:
#ifdef FLIPCURSOR
flip_cursorbar(10);
#endif
return (S_POSITIVE | StkOffset_from_68K(new68k));
} /* moveframe end */
/******************************************************************/
/*
Func Name : do_stackoverflow(incallp)
retval: If There is no space for stack then return 1
else return 0
incallp:
If Calling during function call,incallp=T
else NIL
Edited by : Take(March 28, 1988)
*/
/******************************************************************/
int do_stackoverflow(int incallp) {
register DLword *next68k;
DLword newfx;
DLword savenext;
DLword *oldPVar;
int movedistance;
LispPTR moveframe(register FX * oldfx68k);
#ifdef STACKCHECK
LispPTR stackcontents;
LispPTR TopIVAR;
stackcontents = *((LispPTR *)CurrentStackPTR);
TopIVAR = *((LispPTR *)IVar);
#endif
/* Don't care PC,FuncObj, */
/* if incall flag ON, don't care that IVar
became residual, and it is pointed to by copied FX's BLINK */
oldPVar = PVar;
if (*NeedHardreturnCleanup_word) { warn("HardreturnCleanup in do_stackoverflow"); }
if (incallp) { savenext = CURRENTFX->nextblock; /* save old nextblock */ }
BEFORE_CONTEXTSW; /* Don't Use MIDPUNT and Don't care IFPAGE */
/* Call MOVEFRAME directly */
if ((newfx = (DLword)moveframe(CURRENTFX)) == 0xFFFF) {
/* To make immediately call HARDRESET */
Irq_Stk_Check = 0;
Irq_Stk_End = 0;
return (1); /* Whole space exhausted */
}
/* Return from MOVEFRAME directly */
PVar = (DLword *)Addr68k_from_StkOffset(newfx + FRAMESIZE);
movedistance = ((UNSIGNED)PVar - (UNSIGNED)oldPVar) >> 1;
AFTER_CONTEXTSW;
if (incallp) {
/* set next(it pointed to old IVar) with offset */
CURRENTFX->nextblock = savenext + movedistance;
/* including Last Arg(kept in TOS */
#ifdef BIGVM
S_CHECK(FuncObj == (struct fnhead *)Addr68k_from_LADDR(CURRENTFX->fnheader),
"in call, but stack frame doesn't match FN being executed.");
#else
S_CHECK(FuncObj == (struct fnhead *)Addr68k_from_LADDR((CURRENTFX->hi2fnheader << 16) |
CURRENTFX->lofnheader),
"in call, but stack frame doesn't match FN being executed.");
#endif /* BIGVM */
CHECK_FX(CURRENTFX);
/* We should re-Set up IVAR,CURRENTFX->nextblock */
IVar += movedistance;
} /* incallp */
return (0); /* Normal return */
/* If incallp ,we CAN continue executing FN or APPLY by just returning */
/* new PVar will set in funcall */
} /* end do_stackoverflow */
/******************************************************************/
/*
Func Name : freestackblock(n,sart,align)
Desc. : Search the FSB has specified size n or more
Return useful area's ptr.
If there is no space for STACK,return 0
Edited by : take(15-Jul-87)
take(11-Apr-88)
*/
/******************************************************************/
DLword *freestackblock(DLword n, StackWord *start68k, int align)
/* size you want(in DLword) */
/* searching will start68k at here */
/* if Negative,it needn't align */
{
register int wantedsize;
register StackWord *scanptr68k;
register STKBLK *freeptr68k;
register StackWord *easp68k;
register DLword freesize;
DLword *extendstack(void);
if (n % 2) error("asking for odd-length stack block");
/* compute actually size you needed */
wantedsize = n + STACKAREA_SIZE + MINEXTRASTACKWORDS;
easp68k = (StackWord *)(Addr68k_from_StkOffset(InterfacePage->endofstack));
/*** DEBUG ***/
S_CHECK(n > 2, "asking for block < 2 words long");
S_CHECK(start68k != 0, "start68k = 0");
S_CHECK(start68k >= (StackWord *)Addr68k_from_StkOffset(InterfacePage->stackbase),
"start68k before stack base");
STARTOVER:
if (start68k)
scanptr68k = start68k;
else
scanptr68k = (StackWord *)Addr68k_from_StkOffset(InterfacePage->stackbase);
SCAN:
switch ((unsigned)(STKWORD(scanptr68k)->flags)) {
case STK_FSB: goto FREESCAN; break;
case STK_GUARD:
if ((UNSIGNED)scanptr68k < (UNSIGNED)easp68k) goto FREESCAN;
if (start68k) {
scanptr68k = (StackWord *)Addr68k_from_StkOffset(InterfacePage->stackbase);
goto SCAN;
} else
goto NEWPAGE;
break;
case STK_FX:
scanptr68k = (StackWord *)Addr68k_from_StkOffset(((FX *)scanptr68k)->nextblock);
break;
default:
#ifdef STACKCHECK
StackWord *orig68k = scanptr68k;
#endif
while (STKWORD(scanptr68k)->flags != STK_BF) {
S_WARN(STKWORD(scanptr68k)->flags == STK_NOTFLG, "NOTFLG not on", scanptr68k);
scanptr68k = (StackWord *)(((DLword *)scanptr68k) + DLWORDSPER_CELL);
};
#ifdef STACKCHECK
if (((Bframe *)scanptr68k)->residual) {
if (scanptr68k != orig68k) {
WARN("freestackblock:scanptr68k !=org", printf(":0x%x\n", LADDR_from_68k(scanptr68k)));
return 0; /* ? */
}
} else {
if (((Bframe *)scanptr68k)->ivar != StkOffset_from_68K(orig68k)) {
WARN("BF doesn't point TopIVAR", printf(":0x%x\n", LADDR_from_68k(scanptr68k)));
return 0; /* ? */
}
}
#endif
/* Used to be a +=, but SunOS4/Sparc compiles it wrong */
scanptr68k = (StackWord *)((DLword *)scanptr68k + DLWORDSPER_CELL);
break;
} /* end switch(scanptr68k */
NEXT:
if (scanptr68k != start68k) {
S_CHECK((UNSIGNED)scanptr68k <= (UNSIGNED)easp68k, "scan ptr past end of stack");
goto SCAN;
}
NEWPAGE:
easp68k = (StackWord *)extendstack();
if (easp68k)
goto STARTOVER;
else {
warn("freestackblock:StackFull MP9319");
return (0);
}
FREESCAN:
freeptr68k = (STKBLK *)scanptr68k;
freesize = FSB_size(freeptr68k);
FREE:
scanptr68k = (StackWord *)(((DLword *)freeptr68k) + freesize);
if (freesize == 0) error("FREESIZE = 0");
switch ((unsigned)(STKWORD(scanptr68k)->flags)) {
case STK_FSB: freesize = freesize + FSB_size(scanptr68k); goto FREE;
case STK_GUARD:
if ((UNSIGNED)scanptr68k < (UNSIGNED)easp68k) {
freesize = freesize + FSB_size(scanptr68k);
goto FREE;
}
break;
default: break;
} /* end switch(scanp.. */
if (freesize >= wantedsize) {
if ((align < 0) || (align == (StkOffset_from_68K(freeptr68k) % DLWORDSPER_QUAD)))
wantedsize = MINEXTRASTACKWORDS;
else
wantedsize = MINEXTRASTACKWORDS + DLWORDSPER_CELL;
scanptr68k = (StackWord *)(((DLword *)freeptr68k) + wantedsize);
SETUPGUARDBLOCK(scanptr68k, n);
MAKEFREEBLOCK(freeptr68k, wantedsize);
MAKEFREEBLOCK(((DLword *)scanptr68k) + n, freesize - wantedsize - n);
return ((DLword *)scanptr68k);
} else
MAKEFREEBLOCK(freeptr68k, freesize);
goto NEXT;
} /* freestackblock end */
/******************************************************************/
/*
Func Name : decusecount68k(frame)
Desc. : Search the FSB has specified size n or more
Return useful are ptr.
Edited by : take(March 14, 1988)
*/
/******************************************************************/
#define BF_size(ptr68k) ((StkOffset_from_68K(ptr68k)) - ((Bframe *)(ptr68k))->ivar + 2)
void decusecount68k(register FX *frame68k) {
DLword *alink68k;
register Bframe *blink68k;
DLword *clink68k;
register DLword *ivar68k;
register int size;
if (FX_INVALIDP(frame68k)) return;
CHECK_FX(frame68k);
/* I don't check if \INTERRUPTABLE is NIL */
while (StkOffset_from_68K(frame68k)) {
if (frame68k->usecount != 0) {
frame68k->usecount--;
return;
} else {
alink68k = Addr68k_from_StkOffset(GETALINK(frame68k));
blink68k = (Bframe *)Addr68k_from_StkOffset(GETBLINK(frame68k));
clink68k = Addr68k_from_StkOffset(GETCLINK(frame68k));
size = FX_size(frame68k);
if (((Bframe *)DUMMYBF(frame68k))->residual) { /* this frame has dummy BF */
MAKEFREEBLOCK(((DLword *)frame68k) - DLWORDSPER_CELL, size + DLWORDSPER_CELL);
} else {
MAKEFREEBLOCK(frame68k, size);
}
if (blink68k->usecnt != 0) {
blink68k->usecnt--;
} else {
/*** ivar68k=Addr68k_from_StkOffset(blink68k->ivar);
GETWORD(ivar68k)=STK_FSB_WORD;
GETWORD(ivar68k+1)=ivar68k -(DLword *)blink68k +2; **/
MAKEFREEBLOCK(Addr68k_from_StkOffset(blink68k->ivar), BF_size(blink68k));
}
if (alink68k != clink68k) decusecount68k((FX *)alink68k);
frame68k = (FX *)clink68k;
} /* else end */
} /*while end */
} /* decusecount68k end */
#ifdef ORG_FILPCORSORBAR
extern DLword *EmCursorBitMap68K;
extern int LispWindowFd;
#ifdef XWINDOW
extern int Current_Hot_X, Current_Hot_Y;
#endif /* XWINDOW */
extern struct cursor CurrentCursor;
void flip_cursorbar(int n)
{
GETWORD(EmCursorBitMap68K + n) = ~(GETWORD(EmCursorBitMap68K + n));
#ifdef SUNDISPLAY
win_setcursor(LispWindowFd, &CurrentCursor);
#endif /* SUNDISPLAY */
#ifdef XWINDOW
/* JDS 011213 When using current_hot_y, remember fn does 15-it! */
Set_XCursor(Current_Hot_X, 15 - Current_Hot_Y);
#endif /* XWINDOW */
}
#else
extern short *DisplayRegion68k;
extern int DisplayRasterWidth;
void flip_cursorbar(int n) {
register short *word;
word = DisplayRegion68k + (n * DisplayRasterWidth);
GETWORD(word) ^= 0xFFFF;
}
#endif
/**************************************************************/
/*
blt(dest,source,size)
*/
/**************************************************************/
void blt(register DLword *dest68k, register DLword *source68k, int nw) {
/******* OLD def ,
Due to C compiler's bug, we can't use pre-decrement for register val
source68k += nw;
dest68k += nw;
while(nw)
{
GETWORD(--dest68k)= GETWORD(--source68k);
nw--;
}
**** OLD def ****/
source68k = source68k + nw - 1;
dest68k = dest68k + nw - 1;
while (nw--) { GETWORD(dest68k--) = GETWORD(source68k--); }
}
/**************************************************************/
/*
stack_check(start68k)
for DEBUG
*/
/**************************************************************/
#ifdef FSBCHECK
struct big_fsbs {
DLword offset;
DLword size;
} bigFSB[100];
int bigFSBindex;
#endif
void stack_check(StackWord *start68k) {
StackWord *scanptr68k;
StackWord *endstack68k;
DLword *top_ivar;
DLword save_nextblock;
DLword savestack1, savestack2;
DLword setflg = NIL;
DLword freesize;
#ifdef FSBCHECK
bigFSBindex = 0;
memset((char *)bigFSB, 0, sizeof(bigFSB));
#endif
if ((CURRENTFX->nextblock != StkOffset_from_68K(CurrentStackPTR)) || (!FSBP(CurrentStackPTR))) {
if ((DLword *)CURRENTFX >= CurrentStackPTR) {
WARN("CURRENTFX >= CurrentStackPTR??\n",
printf("CURRENTFX=0x%x,CurrentStackPTR=0x%x\n", LADDR_from_68k(CURRENTFX),
LADDR_from_68k(CurrentStackPTR)));
}
setflg = T;
printf("set CURRENTFX->nextblock in debugger. But it will be reset after this check \n");
save_nextblock = CURRENTFX->nextblock;
savestack1 = GETWORD(CurrentStackPTR + 2);
savestack2 = GETWORD(CurrentStackPTR + 3);
CURRENTFX->nextblock = StkOffset_from_68K(CurrentStackPTR + 2);
GETWORD(CurrentStackPTR + 2) = STK_FSB_WORD;
GETWORD(CurrentStackPTR + 3) = (((UNSIGNED)EndSTKP - (UNSIGNED)(CurrentStackPTR + 2)) >> 1);
}
if (start68k)
scanptr68k = start68k;
else
scanptr68k = (StackWord *)Addr68k_from_StkOffset(InterfacePage->stackbase);
endstack68k = (StackWord *)Addr68k_from_StkOffset(InterfacePage->endofstack);
if (STKWORD(endstack68k)->flags != STK_GUARD) printf("?? endstack is not GUARD BLK\n");
while (scanptr68k < endstack68k) {
switch ((unsigned)(STKWORD(scanptr68k)->flags)) {
case STK_FSB:
freesize = FSB_size(scanptr68k);
if (freesize == 0) { warn("FSB freesize = 0!"); }
#ifdef FSBCHECK
if (freesize > STACKAREA_SIZE + MINEXTRASTACKWORDS) {
if (bigFSBindex < 100) {
bigFSB[bigFSBindex].offset = StkOffset_from_68K(scanptr68k);
bigFSB[bigFSBindex].size = freesize;
bigFSBindex++;
}
}
#endif
scanptr68k = (StackWord *)((DLword *)scanptr68k + freesize);
putchar('F');
break;
case STK_GUARD:
freesize = FSB_size(scanptr68k);
if (freesize == 0) { warn("Guard block freesize = 0!"); }
scanptr68k = (StackWord *)((DLword *)scanptr68k + freesize);
putchar('G');
break;
case STK_FX:
CHECK_FX((FX *)scanptr68k);
scanptr68k = (StackWord *)Addr68k_from_StkOffset(((FX *)scanptr68k)->nextblock);
putchar('X');
break;
default:
top_ivar = (DLword *)scanptr68k;
while (STKWORD(scanptr68k)->flags != STK_BF) {
if (STKWORD(scanptr68k)->flags != STK_NOTFLG) {
WARN("StackCheck:!=STK_NOTFLG", printf("content:0x%x\n", GETWORD(scanptr68k)));
}
scanptr68k = (StackWord *)((DLword *)scanptr68k + DLWORDSPER_CELL);
} /* while end */;
CHECK_BF((Bframe *)scanptr68k);
if (((Bframe *)scanptr68k)->residual) {
if ((DLword *)scanptr68k != top_ivar)
printf("Residual has real IVAR:0x%x\n", LADDR_from_68k(scanptr68k));
} else {
if (((Bframe *)scanptr68k)->ivar != StkOffset_from_68K(top_ivar))
printf("BF doesn't point TopIVAR:0x%x\n", LADDR_from_68k(scanptr68k));
}
scanptr68k = (StackWord *)((DLword *)scanptr68k + DLWORDSPER_CELL);
putchar('B');
break;
} /*switch end */
if (scanptr68k != start68k) {
if (scanptr68k > endstack68k) {
WARN("scanptr exceeded end stack",
printf("scanptr68k=%p endstack68k=%p", scanptr68k, endstack68k));
}
}
} /* while end */
#ifdef FSBCHECK
if (bigFSBindex != 0) {
int i;
printf("\nBIG FSB(s):\n");
for (i = 0; i < bigFSBindex; i++) {
printf("Offset: 0x%x , Size: 0x%x\n", bigFSB[i].offset, bigFSB[i].size);
}
}
#endif
printf("\nStack Check done\n");
if (setflg) {
CURRENTFX->nextblock = save_nextblock;
GETWORD(CurrentStackPTR + 2) = savestack1;
GETWORD(CurrentStackPTR + 3) = savestack2;
}
} /*stack_check end */
/**************************************************************/
/*
walk_stack(start68k)
for DEBUG
Walk the stack, printing information about what we
see as we go. Unlike stack_check, this prints frame
names, alink/clink/next values, free-block lengths, etc.
*/
/**************************************************************/
void walk_stack(StackWord *start68k) {
StackWord *scanptr68k;
StackWord *endstack68k;
DLword *top_ivar;
DLword save_nextblock;
DLword savestack1, savestack2;
DLword setflg = NIL;
DLword freesize;
if ((CURRENTFX->nextblock != StkOffset_from_68K(CurrentStackPTR)) || (!FSBP(CurrentStackPTR))) {
if ((DLword *)CURRENTFX >= CurrentStackPTR) {
WARN("CURRENTFX >= CurrentStackPTR??\n",
printf("CURRENTFX=0x%x,CurrentStackPTR=0x%x\n", LADDR_from_68k(CURRENTFX),
LADDR_from_68k(CurrentStackPTR)));
}
setflg = T;
printf("set CURRENTFX->nextblock in debugger. But it will be reset after this check \n");
save_nextblock = CURRENTFX->nextblock;
savestack1 = GETWORD(CurrentStackPTR + 2);
savestack2 = GETWORD(CurrentStackPTR + 3);
CURRENTFX->nextblock = StkOffset_from_68K(CurrentStackPTR + 2);
GETWORD(CurrentStackPTR + 2) = STK_FSB_WORD;
GETWORD(CurrentStackPTR + 3) = (((UNSIGNED)EndSTKP - (UNSIGNED)(CurrentStackPTR + 2)) >> 1);
}
/* Start from where caller specifies, (as real address!); if addr=0 */
/* start from stackbase. */
if (start68k) {
scanptr68k = (StackWord *)((unsigned long)start68k & -2);
printf("Starting at 0x%tx.", (DLword *)scanptr68k - Stackspace);
} else {
scanptr68k = (StackWord *)Addr68k_from_StkOffset(InterfacePage->stackbase);
printf("Stack base = 0x%tx.", (DLword *)scanptr68k - Stackspace);
}
endstack68k = (StackWord *)Addr68k_from_StkOffset(InterfacePage->endofstack);
printf(" End of stack = 0x%tx.\n\n", (DLword *)endstack68k - Stackspace);
if (STKWORD(endstack68k)->flags != STK_GUARD)
printf("?? endstack is not GUARD BLK\nendstack = %p, flags = %d\n\n", endstack68k,
STKWORD(endstack68k)->flags);
while (scanptr68k < endstack68k) {
switch ((unsigned)(STKWORD(scanptr68k)->flags)) {
/* Free stack block */
case STK_FSB:
freesize = FSB_size(scanptr68k);
printf("%04tx: Free block (len %d/0x%x)\n", (DLword *)scanptr68k - Stackspace, freesize,
freesize);
if (freesize == 0) { freesize = 2; }
scanptr68k = (StackWord *)((DLword *)scanptr68k + freesize);
break;
case STK_GUARD:
freesize = FSB_size(scanptr68k);
printf("%04tx: Guard block (len %d/0x%x)\n", (DLword *)scanptr68k - Stackspace, freesize,
freesize);
if (freesize == 0) { freesize = 2; }
scanptr68k = (StackWord *)((DLword *)scanptr68k + freesize);
break;
case STK_FX:
CHECK_FX((FX *)scanptr68k);
printf("%04tx: ", (DLword *)scanptr68k - Stackspace);
{
FX *fx = (FX *)scanptr68k;
struct fnhead *fnobj;
#ifdef BIGVM
fnobj = (struct fnhead *)Addr68k_from_LADDR(fx->fnheader);
#else
fnobj =
(struct fnhead *)Addr68k_from_LADDR(((int)fx->hi2fnheader << 16) | fx->lofnheader);
#endif /* BIGVM */
print(fnobj->framename);
printf("\talink: 0x%04x, clink: 0x%04x, next: 0x%04x\n", fx->alink, fx->clink,
fx->nextblock);
}
{
Bframe *dummybf, *mtmp;
int mblink;
/* Now make sure the FX is connected to */
/* a Basic Frame. */
dummybf = (Bframe *)DUMMYBF(scanptr68k);
/* Check for connection via BLINK field: */
if (StkOffset_from_68K(dummybf) != GETBLINK(scanptr68k)) {
mblink = GETBLINK(scanptr68k);
mtmp = (Bframe *)Addr68k_from_StkOffset(mblink);
if ((dummybf->residual == NIL) || (dummybf->ivar != mtmp->ivar))
printf(" [Bad residual]\n");
}
}
scanptr68k = (StackWord *)Addr68k_from_StkOffset(((FX *)scanptr68k)->nextblock);
break;
default:
top_ivar = (DLword *)scanptr68k;
while (STKWORD(scanptr68k)->flags != STK_BF) {
if (STKWORD(scanptr68k)->flags != STK_NOTFLG) {
printf("%04tx: Bad BF IVAR 0x%x\n", (DLword *)scanptr68k - Stackspace,
GETWORD(scanptr68k));
}
scanptr68k = (StackWord *)((DLword *)scanptr68k + DLWORDSPER_CELL);
} /* while end */;
/* CHECK_BF(scanptr68k); */
{
Bframe *bf = (Bframe *)scanptr68k;
printf("%04tx: BF usecnt %d, resid %d, padding %d, ivar 0x%04x\n",
(DLword *)scanptr68k - Stackspace, bf->usecnt, bf->residual, bf->padding,
bf->ivar);
if (((Bframe *)scanptr68k)->ivar != StkOffset_from_68K(top_ivar))
printf(" [but top_ivar = 0x%04tx]\n", top_ivar - Stackspace);
}
scanptr68k = (StackWord *)((DLword *)scanptr68k + DLWORDSPER_CELL);
break;
} /*switch end */
if (scanptr68k != start68k) {
if (scanptr68k > endstack68k) {
WARN("scanptr exceeded end stack",
printf("scanptr68k=%p endstack68k=%p", scanptr68k, endstack68k));
}
}
} /* while end */
#ifdef FSBCHECK
if (bigFSBindex != 0) {
int i;
printf("\nBIG FSB(s):\n");
for (i = 0; i < bigFSBindex; i++) {
printf("Offset: 0x%x , Size: 0x%x\n", bigFSB[i].offset, bigFSB[i].size);
}
}
#endif
printf("\nStack Check done\n");
if (setflg) {
CURRENTFX->nextblock = save_nextblock;
GETWORD(CurrentStackPTR + 2) = savestack1;
GETWORD(CurrentStackPTR + 3) = savestack2;
}
} /* walk_stack end */
/**************************************************************/
/*
quick_stack_check()
for DEBUGING using FNSTKCHECK
*/
/**************************************************************/
void quick_stack_check(void) {
StackWord *start68k;
StackWord *scanptr68k;
StackWord *endstack68k;
DLword *top_ivar;
DLword save_nextblock;
DLword savestack1, savestack2;
DLword setflg = NIL;
DLword freesize;
#ifdef FSBCHECK
bigFSBindex = 0;
memset((char *)bigFSB, 0, sizeof(bigFSB));
#endif
if ((CURRENTFX->nextblock != StkOffset_from_68K(CurrentStackPTR)) || (!FSBP(CurrentStackPTR))) {
if ((DLword *)CURRENTFX >= CurrentStackPTR) {
WARN("CURRENTFX >= CurrentStackPTR??\n",
printf("CURRENTFX=0x%x,CurrentStackPTR=0x%x\n", LADDR_from_68k(CURRENTFX),
LADDR_from_68k(CurrentStackPTR)));
return;
}
setflg = T;
save_nextblock = CURRENTFX->nextblock;
savestack1 = GETWORD(CurrentStackPTR + 2);
savestack2 = GETWORD(CurrentStackPTR + 3);
CURRENTFX->nextblock = StkOffset_from_68K(CurrentStackPTR + 2);
GETWORD(CurrentStackPTR + 2) = STK_FSB_WORD;
GETWORD(CurrentStackPTR + 3) = (((UNSIGNED)EndSTKP - (UNSIGNED)(CurrentStackPTR + 2)) >> 1);
}
scanptr68k = start68k = (StackWord *)Addr68k_from_StkOffset(InterfacePage->stackbase);
endstack68k = (StackWord *)Addr68k_from_StkOffset(InterfacePage->endofstack);
if (STKWORD(endstack68k)->flags != STK_GUARD) printf("?? endstack is not GUARD BLK\n");
while (scanptr68k < endstack68k) {
switch ((unsigned)(STKWORD(scanptr68k)->flags)) {
case STK_FSB:
freesize = FSB_size(scanptr68k);
if (freesize == 0) {
warn("FSB freesize = 0!");
return;
}
#ifdef FSBCHECK
if (freesize > STACKAREA_SIZE + MINEXTRASTACKWORDS) {
if (bigFSBindex < 100) {
bigFSB[bigFSBindex].offset = StkOffset_from_68K(scanptr68k);
bigFSB[bigFSBindex].size = freesize;
bigFSBindex++;
}
}
#endif
scanptr68k = (StackWord *)((DLword *)scanptr68k + freesize);
break;
case STK_GUARD:
freesize = FSB_size(scanptr68k);
if (freesize == 0) {
warn("Guard block freesize = 0!");
return;
}
scanptr68k = (StackWord *)((DLword *)scanptr68k + freesize);
break;
case STK_FX:
CHECK_FX((FX *)scanptr68k);
scanptr68k = (StackWord *)Addr68k_from_StkOffset(((FX *)scanptr68k)->nextblock);
break;
default:
top_ivar = (DLword *)scanptr68k;
while (STKWORD(scanptr68k)->flags != STK_BF) {
if (STKWORD(scanptr68k)->flags != STK_NOTFLG) {
warn("StackCheck:!=STK_NOTFLG");
printf("content:0x%x\n", GETWORD(scanptr68k));
return;
}
scanptr68k = (StackWord *)((DLword *)scanptr68k + DLWORDSPER_CELL);
} /* while end */;
CHECK_BF((Bframe *)scanptr68k);
if (((Bframe *)scanptr68k)->residual) {
if ((DLword *)scanptr68k != top_ivar)
printf("Residual has real IVAR:0x%x\n", LADDR_from_68k(scanptr68k));
} else {
if (((Bframe *)scanptr68k)->ivar != StkOffset_from_68K(top_ivar))
printf("BF doesn't point TopIVAR:0x%x\n", LADDR_from_68k(scanptr68k));
}
scanptr68k = (StackWord *)((DLword *)scanptr68k + DLWORDSPER_CELL);
break;
} /*switch end */
if (scanptr68k != start68k) {
if (scanptr68k > endstack68k) {
WARN("scanptr exceeded end stack",
printf("scanptr68k=%p endstack68k=%p", scanptr68k, endstack68k));
}
}
} /* while end */
#ifdef FSBCHECK
if (bigFSBindex != 0) {
int i;
printf("\nBIG FSB(s):\n");
for (i = 0; i < bigFSBindex; i++) {
printf("Offset: 0x%x , Size: 0x%x\n", bigFSB[i].offset, bigFSB[i].size);
}
}
#endif
if (setflg) {
CURRENTFX->nextblock = save_nextblock;
GETWORD(CurrentStackPTR + 2) = savestack1;
GETWORD(CurrentStackPTR + 3) = savestack2;
}
return;
} /* quick_stack_check end */
/************************************************************************/
/* */
/* C H E C K _ F X */
/* */
/* Consistency checks on a Frame Extension; used when the */
/* STACKCHECK compile switch is on. */
/* */
/* The function just returns if things are OK; calls error */
/* if there are problems. */
/* */
/************************************************************************/
void check_FX(FX *fx68k) {
Bframe *dummybf, *mtmp;
int mblink;
/* The FX better really be an FX */
if (((FX *)(fx68k))->flags != STK_FX) error("CheckFX:NOT FX");
/* Make sure the NEXTBLOCK field of the FX */
/* Points BEYOND the start of the FX; some */
/* stack blocks have been corrupted this */
/* way. --JDS 2/3/98 */
if (fx68k->nextblock < StkOffset_from_68K(fx68k) /*+FRAMESIZE*/) {
error("FX's nextblock field < the FFX.");
}
/* Now make sure the FX is connected to */
/* a Basic Frame. */
dummybf = (Bframe *)DUMMYBF(fx68k);
/* Check for connection via BLINK field: */
if (StkOffset_from_68K(dummybf) == GETBLINK(fx68k)) return;
mblink = GETBLINK(fx68k);
mtmp = (Bframe *)Addr68k_from_StkOffset(mblink);
if ((dummybf->residual != NIL) && (dummybf->ivar == mtmp->ivar))
return;
else
error("CheckFX:bad residual case");
} /* END check_FX */
/************************************************************************/
/* */
/* C H E C K _ B F */
/* */
/* Check a Basic Frame (BF) for consistency. This is used */
/* when STACKCHECK is defined. */
/* */
/************************************************************************/
void check_BF(Bframe *bf68k) {
Bframe *iptr68k;
/* For starterd, it must BE a BF */
if (bf68k->flags != STK_BF) error("checkBF:not BF1");
/* If the frame is residual (whatever that means), it's OK */
if (bf68k->residual == T)
return;
else {
if (bf68k->ivar & 1)
error("IVAR is ODD in a BF");
else
for (iptr68k = (Bframe *)Addr68k_from_StkOffset(bf68k->ivar);
iptr68k <= (Bframe *)(((DLword *)bf68k) - 2); iptr68k++) /* inc 2DLword */
{
/* Make sure none of the "ivar" slots have stack-type */
/* bits set. */
if (iptr68k->flags != STK_NOTFLG) warn("CheckBF:Stack-bits set in IVAR");
}
}
} /* end check_BF */
/************************************************************************/
/* */
/* */
/* */
/* */
/* */
/************************************************************************/
int check_stack_rooms(FX *fx68k) {
int size;
DLword *freeptr68k, *endstk68k;
CHECK_FX(fx68k);
freeptr68k = Addr68k_from_StkOffset(fx68k->nextblock);
if (!FSBP(freeptr68k)) error("check_stack_rooms: nextblock doesn't point to an FSB");
/*endstk68k=freeptr68k + FSB_size(freeptr68k);
size=((UNSIGNED)endstk68k - (UNSIGNED)CurrentStackPTR) >> 1;*/
return (FSB_size(freeptr68k));
} /* end check_stack_rooms */