mirror of
https://github.com/Interlisp/maiko.git
synced 2026-01-21 10:03:00 +00:00
1263 lines
34 KiB
C
Executable File
1263 lines
34 KiB
C
Executable File
/* $Id: llstk.c,v 1.5 2001/12/26 22:17:03 sybalsky Exp $ (C) Copyright Venue, All Rights Reserved */
|
|
static char *id = "$Id: llstk.c,v 1.5 2001/12/26 22:17:03 sybalsky Exp $ Copyright (C) Venue";
|
|
|
|
|
|
|
|
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* (C) Copyright 1989-95 Venue. All Rights Reserved. */
|
|
/* Manufactured in the United States of America. */
|
|
/* */
|
|
/* The contents of this file are proprietary information */
|
|
/* belonging to Venue, and are provided to you under license. */
|
|
/* They may not be further distributed or disclosed to third */
|
|
/* parties without the specific permission of Venue. */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
#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 */
|
|
#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"
|
|
|
|
extern int extended_frame;
|
|
|
|
|
|
|
|
|
|
/******************************************************************/
|
|
/*
|
|
Func Name : moveframe(oldfx68k)
|
|
|
|
Edited by : Take(March 14, 1988)
|
|
*/
|
|
/******************************************************************/
|
|
LispPTR moveframe(register FX *oldfx68k)
|
|
{
|
|
register int size;
|
|
register DLword *next68k;
|
|
register DLword *new68k;
|
|
DLword *freestackblock(DLword n, StackWord *start68k, int align);
|
|
DLword *extendstack(void);
|
|
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 earler 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)));}
|
|
}
|
|
#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(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 IVar
|
|
,became resudual and it is pointed 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 immidiately call HARDRESET */
|
|
Irq_Stk_Check = 0;
|
|
Irq_Stk_End=0;
|
|
return(1); /* Whole space exausted */
|
|
}
|
|
|
|
|
|
/* 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 : extendstack()
|
|
Desc. : if LastStackAddr_word is exceeded,then allocate
|
|
one new lisppage for STACK area.
|
|
|
|
Edited by : Take(March 14, 1988)
|
|
|
|
*/
|
|
/******************************************************************/
|
|
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 : 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;
|
|
StackWord *ooscan, *oscan;
|
|
register StackWord *orig68k;
|
|
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 : orig68k = scanptr68k;
|
|
|
|
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)));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(((Bframe*)scanptr68k)->ivar
|
|
!= StkOffset_from_68K(orig68k))
|
|
{
|
|
WARN("BF doesn't point TopIVAR",
|
|
printf(":0x%x\n",
|
|
LADDR_from_68k(scanptr68k)));
|
|
}
|
|
}
|
|
#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:
|
|
ooscan = oscan; oscan = scanptr68k;
|
|
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)
|
|
|
|
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;
|
|
flip_cursorbar(n)
|
|
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;
|
|
|
|
flip_cursorbar(int n)
|
|
{
|
|
register short *word;
|
|
word = DisplayRegion68k + (n * DisplayRasterWidth);
|
|
GETWORD(word) ^= 0xFFFF;
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
/**************************************************************/
|
|
/*
|
|
blt(dest,source,size)
|
|
*/
|
|
/**************************************************************/
|
|
blt(register DLword *dest68k, register DLword *source68k, int nw)
|
|
{
|
|
/******* OLD def ,
|
|
Due to C compiler's bug, we can't use pre-decriment 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
|
|
*/
|
|
/**************************************************************/
|
|
stack_check(StackWord *start68k)
|
|
{
|
|
StackWord *scanptr68k;
|
|
StackWord *endstack68k;
|
|
DLword *top_ivar;
|
|
DLword save_nextblock;
|
|
DLword savestack1,savestack2;
|
|
DLword setflg=NIL;
|
|
DLword freesize;
|
|
|
|
#ifdef FSBCHECK
|
|
struct big_fsbs { DLword offset; DLword size;} bigFSB[100];
|
|
int bigFSBindex=0;
|
|
|
|
memset((char*)bigFSB, 0, 100 * 2 * 2);
|
|
#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(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(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=0x%x endstack68k=0x%x",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.
|
|
|
|
*/
|
|
/**************************************************************/
|
|
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%x.", (DLword*)scanptr68k-Stackspace);
|
|
}
|
|
else
|
|
{
|
|
scanptr68k =
|
|
(StackWord *)Addr68k_from_StkOffset(InterfacePage->stackbase);
|
|
printf("Stack base = 0x%x.", (DLword*)scanptr68k-Stackspace);
|
|
}
|
|
|
|
endstack68k=(StackWord *)Addr68k_from_StkOffset(InterfacePage->endofstack);
|
|
|
|
printf(" End of stack = 0x%x.\n\n", (DLword*)endstack68k-Stackspace);
|
|
|
|
if(STKWORD(endstack68k)->flags !=STK_GUARD)
|
|
printf("?? endstack is not GUARD BLK\nendstack = 0x%x, 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("%04x: 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("%04x: 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(scanptr68k);
|
|
|
|
printf("%04x: ",
|
|
(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("%04x: 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("%04x: 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%04x]\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=0x%x endstack68k=0x%x",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
|
|
*/
|
|
/**************************************************************/
|
|
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
|
|
struct big_fsbs { DLword offset; DLword size;} bigFSB[100];
|
|
int bigFSBindex=0;
|
|
|
|
memset((char*)bigFSB, 0, 100 * 2 * 2);
|
|
#endif
|
|
|
|
if((CURRENTFX->nextblock != StkOffset_from_68K(CurrentStackPTR))
|
|
||(!FSBP(CurrentStackPTR)))
|
|
{
|
|
if((DLword*)CURRENTFX >= CurrentStackPTR)
|
|
{
|
|
return(0);
|
|
WARN("CURRENTFX >= CurrentStackPTR??\n",
|
|
printf("CURRENTFX=0x%x,CurrentStackPTR=0x%x\n",
|
|
LADDR_from_68k(CURRENTFX),LADDR_from_68k(CurrentStackPTR)));
|
|
}
|
|
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(1);
|
|
}
|
|
#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(1);
|
|
}
|
|
scanptr68k = (StackWord *)
|
|
((DLword *)scanptr68k + freesize);
|
|
break;
|
|
case STK_FX : CHECK_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(1);
|
|
}
|
|
scanptr68k = (StackWord *)
|
|
((DLword *)scanptr68k + DLWORDSPER_CELL);
|
|
}/* while end */;
|
|
CHECK_BF(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=0x%x endstack68k=0x%x",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(0);
|
|
|
|
}/* 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. */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
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. */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
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 */
|
|
|
|
|
|
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* */
|
|
/* */
|
|
/* */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
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 */
|