mirror of
https://github.com/Interlisp/maiko.git
synced 2026-01-16 16:19:10 +00:00
1052 lines
33 KiB
C
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 */
|